Mermiler video oyunlarında nasıl çalışır?


64

C # ile bir video oyunu tasarlarken bu soru ile karşılaştım.

Battlefield veya Call of Duty gibi oyunları göz önüne alırsak , aynı anda yüzlerce hatta binlerce mermi uçuyor. Olaylar sürekli olarak tetiklenir ve bildiğim kadarıyla, bu çok fazla işlem gücünü emer… ya da öyle mi? Çeşitli oyun geliştiricilerin (2B ve 3B) mermileri nasıl yönettiğini ve her biri için en verimli yöntemin ne olduğunu bilmek istiyorum.

Soruyu okudum Video oyunlarında mermiler nasıl taklit edilir? ancak mermilerin program tasarımı açısından nasıl çalıştığına değinmez.

Birkaç fikrim vardı, ama her birinin dezavantajı var:


Düşünebildiğim en verimli yöntem (2D oyunlar için):

Diyelim ki Bullet adında bir sınıf oluşturacağımı ve kullanıcının bir düğmeyi basılı tuttuğunu ancak her 0.01 saniyede bir Bullet nesnesi yapılacağını söyleyin. Bu Kurşun:

  • 1 Hız

  • 2 Vurulduğu yerden başlama

  • 3 Sprite dokusu

  • 4 Bir vuruş etkisi

Madde işareti kendi sınıfı olacağından çizim, hareket ve eylem dinleyicilerinin kendisini yönetebilirdi.

İşlemcide, bu nesnelerin binlerce örneğinin başlatılmasının ardından imha edilmesinin (isabet etkisi tetiklendiğinde) işlemesi zor olmaz mıydı? RAM alanı?


3D oyunlar için verimli yöntem - Sahip olduğum bir başka düşünce ise:

Bir silah sınıfı oluşturduğumu varsayalım. Bu silahın, bazıları:

  • 1 Silahın nerede hedef aldığını tespit edin ve bir hedefe mi bakıyor olduğunu belirleyin

  • 2 Silah atış animasyonunu tetikleyin

  • 3 Silahın işaret ettiği yerden sağlık çıkarmak için bir şey gösteren bir doDamage () yöntemi vardır

  • 4 Düğmeye basıldığında bir madde imi animasyon sınıfını bildirir

Daha sonra statik bir sınıf oluşturabilirim, BulletAnimation, tetikleyen silahın nerede olduğunu, silahın nereye (mermi varış yeri için) gösterildiğini ve mermi için kullanılacak uygun bir sprite ve hız hakkında bilgi alabileceğini söyleyebilirim. . Bu sınıf daha sonra, bir mermi silahtan atılan bir mermiyi simüle etmek için hem pozisyonlara hem de istenen sprite dayalı olarak sprite'lar (yeni bir iplikte belki idk) çizer.


İkincisi kodlamak çok daha zor görünüyor ve bir seferinde binlerce mermi için sürekli olarak bunu yapmak için statik olarak adlandırmak çok fazla işlem gücü gerektirmiyor mu? Hem başlangıç ​​hem de bitiş konumlarında sürekli güncellemeler almak da zor olacaktır.

Sorum şu ki, oyun yaratıcılarının bunu yapmanın en etkili yolu nedir? Bu yöntem 2D'den 3D oyunlara değişiyor mu?


16
Bugün bile, oyunların çoğunun mermilerin uçuşlarını taklit etmediğini unutmayın. "Yeterince hızlı" olarak kabul edilen herhangi bir şey için, bunun yerine basit bir hitscan yapılır - temel olarak, etkinin tetiğe bastığınız anda aynı anda gerçekleştiği varsayılır. Her halükarda "yüzlerce veya binlerce mermi" gerçekten büyük bir miktar değil - oyunların çok eski konsollardan (çeşitli mermi cehennem oyunları) bugünkü makinelerden binlerce kez daha az güçlü olduğu bir şeydi. Sadece mermi başına olabildiğince az iş yaptığınızdan emin olmanız gerekir :)
Luaan

42
Madde işaretleri genellikle pew-pew-pewteknoloji yoluyla çalışır :)
MonkeyZeus

5
Aynı anda etrafta uçuşan yüzlerce veya binlerce kurşun yoktur. Onları bu kadar hızlı ateşleyen silah yok. Güçlü Phalanx bile saniyede 75 mermiye çıkıyor. Vikipedi'de listelenen “Etkili atış menzili” ne dayanarak, mermiler en fazla yaklaşık 3 saniye boyunca uçar, böylece bir Phalanx bir seferde 225 mermiyi havada bırakabilir. Bir M16 yaklaşık 12 tur / sn'de tepededir ve bu hızı koruyamaz (sürekli ateş için maksimum 0,25 çevre / sn'dir). Sadece bir seferde pek çok silah ateşlenemiyor!
Cort Ammon

3
Sadece bunu belirtmek için, nesneleri çok basit olduklarında bireysel sınıflar yapmak asla iyi değildir. Her bir mermi türü için bir mermi örneği olması çok daha iyidir. Kod uzunluğundaki hafif ek yük ve ne olursa olsun, madde işareti başına fazladan 4 baytlık bir sözcük kaydeder (tür bir tamsayıysa). Ayrıca, bir nesne kolayca bir liste tarayabilir.
Büyük Ördek

4
@Cort - oyun alanında sadece bir ateşli silah olduğunu varsayalım. OP, düzinelerce oyuncunun aynı anda otomatik silah ateşleyebileceği Battlefield ve CoD gibi oyunlardan bahsetti. Eğer her bir tur uzayda fiziksel olarak hesaba katılmışsa saçma bir sayı olması mantıksız değildir.
Jesse Williams,

Yanıtlar:


78

Bunları simüle etmenin neden zor olacağını düşündüğünüzü kesinlikle görebiliyorum, ancak kurşunları (gerçekten tüm mermileri) kolaylaştırmak için yeterince kısıtlamalar var.

  1. Genellikle hacimli bir şey yerine, tek bir nokta olarak simüle edilirler. Bu çarpışma algılamasını önemli ölçüde kolaylaştırır, çünkü artık sadece bir daireye karşı bir çizgi gibi çok basit yüzeylere karşı çarpışmalar yapmam gerekiyor.

  2. Nasıl hareket edeceklerini biliyoruz, bu yüzden onlar için saklamamız veya hesaplamamız gereken fazla bilgi yok. Listeniz makul derecede doğruydu, genellikle mermiyi kim vurdu ve türü ne gibi, onunla ilişkili birkaç şey daha olacak.

  3. Tüm mermiler birbirine çok benzeyeceğinden, onları dinamik bir şekilde oluşturma yüklerinin önüne geçmek için önceden tahsis edebiliriz. Bir dizi 1000 mermi atayabiliyorum ve şimdi sadece bir indeksle erişilebilirler ve hepsinin hafızada sıralı olması dolayısıyla işlemlerin hızlı bir şekilde gerçekleştirilmesidir.

  4. Sabit bir kullanım ömrüne / aralığına sahipler, böylece eski mermileri geçebilir ve hafızayı çok hızlı bir şekilde yeni mermilere dönüştürebilirim.

  5. Bir şeye çarptıklarında onları da sona erdirebilirim, böylece sınırlı bir ömürleri olur.

  6. Ne zaman yaratıldıklarını bildiğimizden beri, yenilerine ihtiyacımız varsa ve önceden tahsis edilen listemizde hiç özgürümüz yoksa, sadece en eskilerini alıp geri dönüşüm yapabilirim ve insanlar mermilerin biraz erken bitip bitmediğini farketmezler. .

  7. Bunlar sprite (genellikle) veya düşük poli model olarak işlenir ve ekranda çok az yer kaplar, bu nedenle görüntülemesi hızlıdır.

Bütün bunları dikkate alarak, mermiler nispeten ucuz olma eğilimindedir. Bütçemiz kurşunlar tarafından tüketilip tüketildiyse, genellikle bir seferde ateş edebileceğiniz atış sayısını sınırlamak için yeniden tasarlardık (bunu birçok eski arcade oyununda görürsünüz), anında hareket eden ışın silahlarını kullanın veya bütçede kaldığımızdan emin olmak için yangın oranını düşürün.


12
Modern oyunlarda her şeyi karmaşık hale getiren aslında 5) 'e katılmıyorum. Daha önceki atıcılarda bu kabul edilebilirdi, günümüzde COD bile oyuncuların ahşap duvarlardan atış yapmasına izin veriyor. 6) nadir bir sorun olsa da, herhangi bir rekabetçi sistem için kabul edilemez.
SBoss

17
@SBoss sonra tekrar ifade eder: "Bir kez girip giremeyecekleri bir şeye çarptıklarında, onları sona erdirebilirim, bu yüzden sınırlı bir ömürleri olur.". Ve 6 için karakter başına maksimum ateş hızını kapatarak ve daha sonra bir dizi uzunluk tutarak en kötü olayı elde edersiniznum_characters * max_bullets_per_character
cırcır

14
@SBoss Ben # 6 örneğin örneğin için daha fazla olduğunu düşünüyorum. Yavaş hareket eden bir merminin birşeye çarpmadan / kaybolmadan önce ekrandan uzaklaşabileceği yukarıdan aşağıya boş alan oyunları. Açıkçası, mermilerin hızlı hareket ettiği ve dünyanın sınırlarına çabucak ulaştığı CoD tipi oyunlarda sorun değil.
BlueRaja - Danny Pflughoeft

1
Oyunların büyük çoğunluğu mermileri (dış balistik) hiç modellemiyor. Çoğu oyun, "hit-scan" adı verilen bir teknik kullanır.
Aron,

45

Muhtemelen, mermileri uygulamak için en etkili yollardan biri hitscan olarak bilinen şeyi kullanmaktır . Uygulamasında oldukça basittir - ateş ederken, silahın neyi hedeflediğini kontrol eder (muhtemelen en yakın varlık / nesneyi / ağı bulmak için bir ışın kullanarak) ve sonra ona vurup hasar görürsünüz. Gerçek, hızlı hareket eden görünmez bir merminin ateşlendiğinden daha fazla görünmesini istiyorsanız, hasara uğramadan önce mesafeye bağlı olarak hafif bir gecikme ekleyerek sahte yapabilirsiniz.

Bu yaklaşım esas olarak ateşlenen merminin sonsuz hıza sahip olduğunu varsayar ve tipik olarak lazerler ve partikül ışınları / toplar ve belki de bazı keskin nişancı tüfekleri gibi silah türleri için kullanılır .

Bir sonraki yaklaşım, ateşlenen mermiyi, kendi çarpışmasına maruz kalan kendi varlığı / nesnesi ve yönünü ve hızını değiştiren yerçekimi ve / veya hava direnci olarak modellenen bir mermi olarak modellemek olacaktır. Ekstra fizik denklemleri nedeniyle hitscan yaklaşımından daha karmaşık ve gerçek bir madde işareti nesnesi olduğu için yoğun olan kaynak, ancak daha gerçekçi madde işaretleri sağlayabilir.

Mermi temelli mermiler ile oyundaki diğer nesneler arasındaki çarpışmaları yönetme gelince, nesnelerinizi dörtlü veya sekizli olarak sıralayarak çarpışma algılaması büyük ölçüde basitleştirilebilir . Octrees öncelikle 3d oyunlarda, quadtrees ise 2d veya 3d oyunlarda kullanılabilir. Bu ağaçlardan birini kullanmanın avantajları, olası çarpışma kontrollerinin sayısını büyük ölçüde azaltabilmenizdir. Örneğin, seviye içerisinde aktif 20 nesneniz varsa, bu ağaçlardan birini kullanmadan, mermi ile çarpışma olup olmadığını 20 için kontrol etmeniz gerekir. 20 nesneyi ağacın yaprakları (uç düğümleri) arasında bölüştürürseniz, çek sayısını, kurşunla aynı yaprakta bulunan birçok varlığa indirgeyebilirsiniz.

Bu yaklaşımlar gelince - hitscan ve mermi, her ikisi de 2d veya 3d oyunlarda serbestçe kullanılabilir. Silahın ne olduğuna ve yaratıcının silahın nasıl çalışması gerektiğine nasıl karar verdiğine bağlıdır.


Tasarım deseni, Hitscan ve dört / oktree bilgileri gerçekten yardımcı olur. Ayrıca, bilgi için teşekkürler!
Eric,

8
Eğer bir hitscanı dava etmiyorsanız ama mermileri simüle ediyorsanız, ince nesneler aracılığıyla çarpıtabilirler çünkü çok hızlı hareket ederler. Bu durumda, oyunlardaki her şeyin sahte olduğunu unutmayın. Bir mermi sadece birkaç santim uzunluğunda olsa bile, çarpışma algılamayı mermi bir metre uzunluğundamış gibi yapabilirsiniz. Bu yolla, nesnelere çarpmadan gelen mermiler hakkında çok fazla endişelenmenize gerek kalmadan güzel mermi atışı ve uçuş simülasyonlarının zamanını yapabilirsiniz :).
Roy T.

2
Mermilerin fiziğinin (örneğin top mermilerinin aksine) yerçekimi (kurşun damlası), hava direnci gibi şeylere saygı gösterdiği oyunlar var mı? (Odak noktalarının hassas hedef atışı olduğu veya özel bir şey olduğu özel oyunların yanı sıra oyunlar: FPS, vb.) Ben bir oyuncu değilim, ama aslına uygunluk seviyesine (bazen de) ihtiyaç duyulduğuna şaşırdım.
davidbak

3
@davidbak: Tipik oyun içi karşılaşmaya ve oyun türünden beklenen gerçekliğe dayanıyor. Çoğunlukla (sadece?) Yakın çeyrek savaşlarla mücadele ediyorsanız, o zaman gerçekten de bu sadakat seviyesine ihtiyaç yoktur. Ancak, uzun menzilli mücadele seçeneği mevcutsa (örneğin, daha RPG benzeri bir ortamda keskin nişancılar veya okçular), füzeleri etkileyen yerçekimi bugünlerde beklenmektedir. Roket fırlatıcınızı yukarı doğru hedeflerseniz, hala roketin bir yere inip patlamasını beklersiniz, değil mi? Yine de, yörüngeler her zaman gerçek fizikten hesaplanmaz, sadece bir yaklaşım (performans nedenleriyle)
hoffmale

1
@davidbak Battlefield bu yana Kötü Şirket 2 kurşun damlası vardı. Her ikisi de tüfekler, tabanca, tank mermileri, roketler için. Battlefield 3 Origin ücretsizdir (IIRC). Tabii ki Battlefield 4 de bu 'özelliğe' sahip. Bunu görebileceğiniz diğer oyun "Sniper Elite". 2 veya 3 yeni başlıklardır. Fizik bu oyunda önemli bir rol oynamaktadır.
Apache,

7

Ben hiçbir uzman değilim, ama sorunuzu yanıtlamak için, evet, bahsettiğiniz şeylerin çoğuna ihtiyacınız olacak.

2D örneğiniz için, bir madde işareti için bir konum ve hıza sahip olabilirsiniz. (Madde imlerinizi nasıl uyguladığınıza bağlı olarak bir ömür veya maksimum mesafeye de ihtiyacınız olabilir.) Bu genellikle 2 (x, y) değerlerini içerir. Eğer yüzerlerse, bu 16 bayttır. 100 merminiz varsa, bu sadece 1600 bayt veya yaklaşık 1.5k. Bugün makinede hiçbir şey yok.

Ardından, sprite bahsediyorsunuz. Her bir mermiyi temsil etmek için yalnızca tek bir sprite gerekecektir. Boyutu, çizdiğiniz bit derinliğine ve ekranda ne kadar büyük görünmesi gerektiğine bağlı olacaktır. Sıkıştırılmamış bile, örneğin, kanal başına 32-bit tam yüzdelik 256x256, bu sprite için 1 MB. (Ve bu çok büyük olurdu!) Her mermi yerine aynı sprite çizerdin, ama sprite her kopyası için ek hafıza almaz. Bir hit etkisi için benzer olurdu.

Her 0.01 saniyede bir ateş etmekten bahsediyorsun. Silahınızdan saniyede 100 mermi gelir. Çok fazla fütüristik bir silah için bile! Göre bu wikipedia makalesinde :

Tetik çekildiğinde, mermilerin ateşlenme hızı döngüsel hızdır. Tipik atış hızı, saldırı tüfeği için 600–900 RPM, bazı durumlarda 1,000-1,100 RPM, hafif makineli tüfekler ve makineli tabancalar için 900-1,200 RPM ve makineli tüfekler için 600-1,200 RPM'dir. M134 Saldırı helikopterleri ve diğer savaş araçlarına monte edilmiş minigunlar, saniyede 100 mermi (6.000 RPM) olan ateş hızlarına ulaşabilir.

Yani bu bir saldırı helikopteri oranı!

Battlefield / Call of Duty / vb. Bölümünde bahsettiğiniz büyük bir dünya için, tüm bu mermi konumlarını hesaplayabilir, ancak eylem uzaktaysa hepsini çizemez. Ya da yakına gelene kadar onları simüle etmeyebilirler. (İtiraf etmeliyim ki, bu kısımda biraz tahmin ediyorum, çünkü o kadar büyük bir şey üzerinde çalışmadım.)


6

İşlemcide, bu nesnelerin binlerce örneğinin başlatılmasının ardından imha edilmesinin (isabet etkisi tetiklendiğinde) işlemesi zor olmaz mıydı? RAM alanı?

Bence bilgisayarların ne kadar hızlı olduğunu hafife alıyorsun. Bu bazen 80'li ve 90'lı sistemlerde bir sorun oldu . Kısmen, orijinal Space Invaders'ın şu anki isabet edinceye kadar başka bir mermi atmana izin vermemesinin nedeni budur. Bazı oyunlar ekranda çok fazla sprite varsa "yavaşlama" yaşadı.

Bugünlerde olsa? Tekstüre alma ve aydınlatma için gerekli olan piksel başına binlerce işlem için yeterli işlem gücünüz var . Binlerce hareketli cisimle ilgili bir sorun yok; bu, her bir parçanın diğer parçalarla çarpışma işlemi yaptığı ve bir balistik eğri izlediği, yıkılabilir bir arazi (örn. Red Faction) yapmanızı sağlar.

Algoritmik olarak biraz dikkatli olmanız gerekir - binlerce nesneye sahip olduğunuzda, her nesneyi diğer nesnelere karşı kontrol etmenin saf yaklaşımını yapamazsınız. Madde işaretleri, genellikle diğer madde işaretleriyle çarpışmaları kontrol etmez.

Küçük bir yan fıkra: Ağ bağlantılı Doom'un ilk sürümü (90'ların orijinali), ateşlenen her kurşun için ağ üzerinden bir paket gönderdi. Bir veya daha fazla oyuncu makineli tüfeği aldığında, bu kolayca ağın altını kapatabilir. 90'lı yıllar, üniversite kullanılamaz duruma geldiğinde üniversite yöneticileri veya iş ağlarında yasadışı bir şekilde Doom oynayan insanlarla dolup taşıyordu.



1
IIRC, ilk ağ doomundaki asıl sorun, bunun yerine yayın paketlerini kullanarak her paketin her rakip oyuncuya ayrı olarak gönderilmesi gerekliliğinden kaçınmasıdır. Bu gönderilen paket sayısını azalttı, ancak maalesef oyunu oynamayanlar da dahil olmak üzere ağdaki her makinede önemli bir CPU yükü yarattı.
supercat

1

Bir uzmandan çok uzaktayım ama boş zamanlarımda çok oyunculu bir 2D shooter oyunu üzerinde çalışıyorum.

Benim yöntem

İstemci ve sunucu arasında değişen madde imi sınıfları vardır (çevrimdışıyken bile, bir sunucu örneği ayrı bir işlemde başlatılır ve 'ana' oyunla bağlanır).

Her tik (saniyede 60), müşteri oyuncunun fare imleci ile ekranın merkezi (karakterlerinin olduğu) arasında bir rol oynar ve sunucuya gönderilen bilgilerin bir parçasıdır. Eğer oyuncu o anda da ateş açıyorsa (silahın yüklenip hazır olduğunu varsayarsak), basitçe bazı koordinatlarla ve bir silahın atışını kullanarak silahın istatistiklerinden türetilmiş bir sunucu tarafı mermi örneği oluşturulur. o). Daha sonra mermi örneği, müşteriden topladığımız rulmandan X ve Y hızlarını elde etmek için bazı matematik fonksiyonlarını kullanır.

Her takip eden onay için, mermi kendisini bu koordinatlar tarafından hareket ettirir ve taban hasarını önceden tanımlanmış bir miktarda azaltır. Bu değer 1'in altına düşerse veya dünyadaki sağlam bir nesneye çarparsa, mermi örneği silinir ve test noktası çarpışmaları 2B'de inanılmaz derecede ucuz olduğundan hızlı ateşli silahların bile performans üzerinde ihmal edilebilir bir etkisi vardır.

Müşteriye gelince, madde işareti bilgileri gerçekten ağ üzerinden alınmaz (testlerde israfın kanıtlandığı kanıtlanmıştır), bunun yerine onay başına güncellemenin bir parçası olarak her karakter 'kovulmuş' bir Boolean'a sahiptir, bu durum doğru olduğunda müşteri yerel olarak oluşturur. Neredeyse tam olarak sunucu olanları gibi çalışan mermi nesnesi, tek fark olması bir sprite var.

Bu, gördüğünüz merminin sunucu üzerinde tam olarak doğru bir temsili olmasa da, bir oyuncu için herhangi bir farkın zar zor farkedileceği ve ağ avantajlarının tutarsızlıklardan ağır basacağı anlamına gelir.

Farklı yöntemler hakkında not

Bazı oyunlar, benimkiler de dahil olmak üzere, bazı mermileri fiziksel nesnelermiş gibi hareket ettirir, oysa diğerleri sadece atış yönünde bir vektör oluşturur ya da merminin oluşturduğu tıkaçtaki tüm yolunu hesaplar; Grev oyunları. Mermi ateşlemesinin bir animasyonu gibi gizlemek için birkaç müşteri tarafı hilesi var, ancak tüm amaç ve amaçlar için her mermi sadece bir lazer .

Karmaşık hit kutulara sahip olan 3D modellerde, FIRST'i basit bir sınırlama kutusuyla çarpışmaları test etmek standarttır ve eğer başarılı olursa, daha 'ayrıntılı' çarpışma algılamasına devam eder.


0

Buna çarpışma tespiti denir. 8-bit bilgisayarlar bunu donanımdaki oyuncu-füze grafiklerini kullanarak yaptılar. Günümüz oyun motorlarında fizik motorları ve lineer cebir kullanılır. Bir silahın mevcut yönü 3B vektör olarak temsil edilir. Bu ateş yönünde sonsuz bir çizgi sağlar. Her hareketli nesnenin bir veya daha fazla sınırlayıcı küre vardır, çünkü bir çizgi ile çarpışmayı tespit eden en basit nesnedir. İkisi kesişirse, bu bir hit, eğer değilse, hit yok. Ancak manzara yolunda olabilir, bu yüzden de kontrol edilmek zorundadır (hiyerarşik sınır ciltleri kullanılarak). Kesişen en yakın nesne, vurulmuş olandır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.