Düzenleme: OPs yorum rastgele bir 2D nokta döndürülmüş ve / veya hareketli bir dikdörtgen içinde olup olmadığını kontrol etmek için algoritmayı geliştirmek için önerilen negatif dairesel bağlı kontrol etkinliği hakkında şüpheci olmuştur. 2D oyun motorumda (OpenGL / C ++) biraz uğraşırken, cevabımı OP'nin mevcut dikdörtgen-nokta-nokta kontrol algoritmalarına (ve varyasyonlarına) karşı bir performans ölçütü sağlayarak yanıtımı tamamlıyorum.
Başlangıçta algoritmayı yerinde bırakmayı önerdim (neredeyse optimal olduğu için), ancak sadece oyun mantığı ile basitleştirin: (1) orijinal dikdörtgenin etrafında önceden işlenmiş bir daire kullanarak; (2) bir mesafe kontrolü yapın ve noktanın verilen daire içinde olup olmadığını; (3) OP'leri veya diğer herhangi bir basit algoritmayı kullanın (başka bir cevapta belirtildiği gibi isLeft algoritmasını öneririm). Benim önerimin arkasındaki mantık, bir noktanın daire içinde olup olmadığını kontrol etmenin, döndürülmüş bir dikdörtgenin veya başka bir çokgenin sınır kontrolünden önemli ölçüde daha verimli olmasıdır.
Bir karşılaştırma testi için ilk senaryom, yaklaşık 20 dönen / hareketli kareyle doldurulacak kısıtlı bir alanda çok sayıda görünen ve kaybolan nokta (her oyun döngüsünde değişen) çalıştırmaktır. Gösterim amacıyla bir video ( youtube bağlantısı ) yayınladım . Parametrelere dikkat edin: rastgele görünen noktaların sayısı, sayı veya dikdörtgenler. Aşağıdaki parametrelerle kıyaslayacağım:
KAPALI : Daire sınır negatif kontrolleri olmadan OP tarafından sağlanan basit algoritma
AÇIK : Dikdörtgenlerin etrafında işlenen (sınır) çevrelerin ilk hariç tutma denetimi olarak kullanılması
AÇIK + Yığın : Yığın üzerindeki döngü içinde çalışma zamanında daire sınırları oluşturma
ON + Kare Mesafesi : Daha pahalı karekök algoritmasını (Pieter Geerkens) kullanmaktan kaçınmak için kare mesafelerini daha fazla optimizasyon olarak kullanmak.
Burada, döngü boyunca yinelenen süreyi göstererek farklı algoritmaların çeşitli performanslarının bir özeti bulunmaktadır.
X ekseni, daha fazla nokta ekleyerek (ve böylece döngüyü yavaşlatarak) artan karmaşıklığı gösterir. (Örneğin, 20 dikdörtgen içeren gizli bir alanda 1000 rastgele görünen nokta denetiminde, döngü yinelenir ve algoritmayı 20000 kez çağırır.) Y ekseni, yüksek bir çözünürlük kullanarak tüm döngüyü tamamlamak için geçen süreyi (ms) gösterir performans zamanlayıcısı. Düzgün bir animasyon enterpolasyonu yapmak için yüksek fps'den yararlanamayacağı ve oyun zaman zaman 'engebeli' görünebileceği için 20 ms'den fazla iyi bir oyun için sorunlu olacaktır.
Sonuç 1 : Döngü içinde hızlı negatif kontrole sahip önceden işlenmiş dairesel bağlı bir algoritma, performansı normal algoritmaya kıyasla% 1900 artırır (orijinal döngü süresinin% 5'i kontrolsüz). Sonuç, bir döngü içindeki yineleme sayısı ile yaklaşık olarak orantılıdır, bu nedenle 10 veya 10000 rastgele görünen noktayı kontrol etmemiz önemli değildir. Böylece, bu çizimde, bir performans kaybı hissetmeden nesne sayısını güvenli bir şekilde 10k'a çıkarabilir.
Sonuç 2 : Önceki bir yorumda algoritmanın daha hızlı ancak bellek yoğun olabileceği ileri sürülmüştür. Bununla birlikte, önceden işlenmiş daire boyutu için bir kayan nokta saklamanın sadece 4 bayt aldığını unutmayın. OP eşzamanlı olarak 100.000'den fazla nesneyi çalıştırmayı planlamadığı sürece bu gerçek bir sorun oluşturmamalıdır. Alternatif ve bellek açısından verimli bir yaklaşım, döngü içindeki yığın üzerindeki çember maksimum boyutunu hesaplamak ve her yineleme ile kapsam dışı kalmasını sağlamak ve böylece bilinmeyen bir hız fiyatı için neredeyse hiç bellek kullanımı olmamasıdır. Aslında, sonuç bu yaklaşımın önceden işlenmiş bir daire boyutu kullanmaktan daha yavaş olduğunu, ancak yine de% 1150 civarında önemli bir performans artışı (yani orijinal işlem süresinin% 8'i) gösterdiğini göstermektedir.
Sonuç 3 : Gerçek mesafeler yerine kare mesafeler kullanarak ve dolayısıyla hesaplama açısından pahalı bir karekök işlemi yaparak sonuç 1 algoritmasını daha da geliştiriyorum. Bu sadece performansı hafifçe artırır (% 2400). (Not: Benzer ama biraz daha kötü bir sonuçla kare kök yaklaşımları için önceden işlenmiş diziler için karma tabloları da deniyorum)
Sonuç 4 : Dikdörtgenin hareket etmesini / çarpışmasını ayrıca kontrol ediyorum; ancak, mantıksal kontrol esasen aynı kaldığından, bu temel sonuçları (beklendiği gibi) değiştirmez.
Sonuç 5 : Dikdörtgen sayısını değiştiriyorum ve algoritmanın, alan dolduğunda daha az kalabalık (demoda gösterilmiyor) daha da verimli hale geldiğini görüyorum. Bir nokta ile nesnenin sınırları arasındaki küçük alanda görünme olasılığı azaldıkça sonuç da biraz beklenir. Diğer uçta, aynı sınırlı küçük alanda çok fazla dikdörtgen sayısını artırmaya ve döngü içinde (sin (iterator)) çalışma zamanında boyut olarak dinamik olarak değiştirmeye çalışıyorum. Bu hala performansta% 570 (veya orijinal döngü süresinin% 15'i) artmasıyla son derece iyi performans gösterir.
Sonuç 6 : Burada önerilen alternatif algoritmaları test ediyorum ve performansta çok hafif ama önemli olmayan bir fark buluyorum (% 2). İlginç ve daha basit IsLeft algoritması,% 17 (orijinal hesaplama süresinin% 85'i) performans artışı ile çok iyi bir performans sergiliyor, ancak hızlı bir negatif kontrol algoritmasının verimliliğine yakın bir yerde yok.
Demek istediğim, özellikle sınırlar ve çarpışma olaylarıyla uğraşırken önce yalın tasarım ve oyun mantığını düşünmektir. OP'nin mevcut algoritması zaten oldukça verimlidir ve başka bir optimizasyon, temel kavramın kendisini optimize etmek kadar kritik değildir. Dahası, bir algoritmanın verimliliği kritik olarak onlara bağlı olduğundan, oyunun kapsamını ve amacını iletmek iyidir.
Sadece düz koda bakmak gerçek çalışma zamanı performansı hakkındaki gerçeği ortaya çıkaramayabileceğinden, oyun tasarımı aşamasında herhangi bir karmaşık algoritmayı karşılaştırmaya çalışmayı öneririm. Örneğin, fare imlecinin bir dikdörtgen içinde olup olmadığını test etmek isterse veya nesnelerin çoğunluğu zaten dokunuyorsa, önerilen algoritma burada bile gerekli olmayabilir. Nokta kontrollerinin çoğunluğu dikdörtgen içindeyse, algoritma daha az verimli olacaktır. (Ancak, ikincil negatif kontrol olarak bir 'iç daire' sınırı oluşturmak mümkün olacaktır.) Daire / küre sınır kontrolleri, aralarında doğal olarak bir miktar boşluk bulunan çok sayıda nesnenin düzgün çarpışma tespiti için çok yararlıdır. .
Rec Points Iter OFF ON ON_Stack ON_SqrDist Ileft Algorithm (Wondra)
(ms) (ms) (ms) (ms) (ms) (ms)
20 10 200 0.29 0.02 0.04 0.02 0.17
20 100 2000 2.23 0.10 0.20 0.09 1.69
20 1000 20000 24.48 1.25 1.99 1.05 16.95
20 10000 200000 243.85 12.54 19.61 10.85 160.58