Doğru cevap biraz tasarladığınız asıl oyuna bağlıdır ve birbirinden bir tanesini seçmek, oyununuzda hangisinin daha fazla zamana veya alanınıza daha verimli olduğunu bulmak için profil yapmayı gerektirir.
Izgara algılama, yalnızca hareketli nesneler ve statik bir arka plan arasındaki çarpışmaları tespit etmek için geçerli görünmektedir. Bunun en büyük avantajı, statik arkaplanın bitişik bir bellek dizisi olarak temsil edilmesidir ve birden fazla okuma yapmanız gerekiyorsa (varlıklar ızgarada birden fazla hücreyi kapladığından) her çarpışma araması, iyi bir konuma sahip olan O (1) 'dir. Dezavantajı, statik arka plan büyükse, şebekenin alandan daha fazla israf olması olabilir.
Bunun yerine statik arka planı dörtlü olarak temsil ederseniz, bireysel aramaların maliyeti artar, ancak arka planın büyük blokları az miktarda yer kapladığından, bellek gereksinimleri azalır ve böylece arka planın daha fazlası içinde oturabilir. önbelleği. Böyle bir yapıda arama yapmak için 10 kat fazla okuma yapsa bile, hepsi önbellekte ise, yine de önbellek özeti olan tek bir aramaya göre 10 kat daha hızlı olacaktır.
Seçim ile karşı karşıya kalsam? Izgara uygulamasıyla giderdim, çünkü aptalca basit, zamanımı diğer, daha ilginç problemlere daha iyi harcardım. Oyunumun biraz yavaş çalıştığını fark edersem, biraz profil çizerim ve yardımın ne kullanabileceğini görürüm. Oyunun çarpışma tespiti yapmak için çok zaman harcadığı görülüyorsa, dörtlü gibi başka bir uygulama denerim (ilk önce tüm kolay düzeltmeleri uyguladıktan sonra) ve yardım edip etmediğini bulurdum.
Düzenleme: Şebeke çarpışma algılamasının çoklu, mobil varlıkların çarpışmalarını algılamakla nasıl ilişkili olduğuna dair hiçbir fikrim yok, ancak bunun yerine, uzamsal bir dizinin (Quadtree) yinelemeli çözüm üzerindeki algılama performansını nasıl iyileştirdiğini yanıtlayacağım. Naif (ve genelde mükemmel derecede ince) çözümü şöyle görünür:
foreach actor in actorList:
foreach target in actorList:
if (actor != target) and actor.boundingbox intersects target.boundingbox:
actor.doCollision(target)
Bu açıkça, O (n ^ 2) civarında performans gösteriyor; n, şu anda mermiler, uzay gemileri ve uzaylılar dahil olmak üzere oyunda canlı olan oyuncu sayısı. Ayrıca küçük statik engeller içerebilir.
Bu tür nesnelerin sayısı oldukça küçük olduğu sürece fevkalade iyi çalışıyor, ancak kontrol edilmesi gereken birkaç yüzün üzerinde nesne olduğunda biraz zayıf görünmeye başlıyor. 10 nesne yalnızca 100 çarpışma kontrolüyle sonuçlanır, 100 sonuç 10.000 kontrolle sonuçlanır. Bir milyon çekle 1000 sonuç.
Bir uzaysal endeks (dörtgenler gibi), topladığı maddeleri geometrik ilişkilere göre verimli bir şekilde numaralandırabilir. bu çarpışma algoritmasını şunun gibi bir şeye değiştirir:
foreach actor in actorList:
foreach target in actorIndex.neighbors(actor.boundingbox):
if (actor != target) and actor.boundingbox intersects target.boundingbox:
actor.doCollision(target)
Bunun verimliliği (varlıkların tekdüze dağılımını varsayarsak): genellikle O (n ^ 1.5 log (n)), çünkü endeks travers için log (n) karşılaştırmaları alır, karşılaştırmak için yaklaşık sqrt (n) komşuları olur. ve kontrol edilecek n aktörler var. Gerçekçi olsa da, komşuların sayısı her zaman oldukça sınırlıdır, çünkü bir çarpışma olursa, nesnelerin çoğu silinir veya çarpışmadan uzaklaştırılır. Böylece sadece O (n log (n)) alırsınız. 10 varlık için (yaklaşık) 10 karşılaştırma yaparsınız, 100 için, 200 yaparsınız, 1000 için 3000 yaparsınız.
Gerçekten akıllı bir dizin, komşu aramayı toplu yinelemeyle birleştirebilir ve kesişen her varlık üzerinde geri arama yapabilir. İndeks, n kez sorgulanmak yerine bir kez tarandığından, bu, yaklaşık O (n) performansı verecektir.