Collision Detection (Çarpışma Tespiti)
İki nesne arasında çarpışma olup olmadığını tespit etmeye çalışırken, nesnelerin vertex verilerini genellikle kullanmayız; çünkü bu nesneler çoğunlukla karmaşık şekillere sahiptir ve bu da çarpışma tespitini güçleştirir. Bu nedenle, genellikle daha basit şekiller (genellikle düzgün matematiksel tanımı olan) orijinal nesnenin üzerine üst üste koyarak çarpışma tespiti yapılır. Bu çarpışma şekillerine (collision shapes) dayanarak çarpışma kontrolü yaparız; bu kodu basitleştirir ve performansı önemli ölçüde artırır. Çarpışma şekillerine örnek olarak daireler, küreler, dikdörtgenler ve kutular verilebilir.
Basit şekiller daha kolay ve verimli çarpışma testleri sağlasa da genellikle nesneyi tam olarak sarmadığından bir dezavantajları vardır. Çarpışma, gerçekte gerçekleşmemiş olsa da tespit edilebilir; bunların gerçek şekillerin yalnızca yaklaşık değerleri olduğunu akılda tutmak gerekir.
AABB - AABB Çarpışmaları
AABB (Axis-Aligned Bounding Box), sahnenin temel eksenlerine — 2D'de x ve y eksenlerine — hizalı dikdörtgen bir çarpışma şeklidir. Eksen hizalı olması, dikdörtgen kutusunun döndürülmediği ve kenarlarının sahne eksenlerine paralel olduğu anlamına gelir. Bu kutular her zaman eksenlerle hizalı olduğundan hesaplamalar kolaylaşır. Top nesnesini bir AABB ile sarabiliriz:

Breakout'taki nesneler dikdörtgen tabanlı olduğundan, çarpışma tespiti için eksen hizalı sınır kutularını kullanmak son derece mantıklı.
AABB'lar birkaç şekilde tanımlanabilir. Bunlardan biri AABB'yi sol üst ve sağ alt konumla tanımlamak. Daha önce tanımladığımız GameObject sınıfı zaten sol üst konumu (Position vektörü) içeriyor; boyutunu konum vektörüne ekleyerek sağ alt konumu kolayca hesaplayabiliriz (Position + Size). Her GameObject, çarpışmalar için kullanabileceğimiz bir AABB içerir.
Peki çarpışmaları nasıl kontrol ederiz? Çarpışma, iki çarpışma şekli birbirinin bölgesine girdiğinde gerçekleşir. AABB'ler için bu oldukça basit: her iki nesnenin o eksendeki kenarlarının üst üste gelip gelmediğini her eksen için kontrol ederiz. Yani hem yatay kenarların hem dikdörtgenlerin dikey kenarlarının üst üste gelip gelmediğini kontrol ederiz. Hem yatay hem de dikey kenarlar üst üste geliyorsa çarpışma vardır.

Bu kavramı koda çevirmek görece basittir:
Birinci nesnenin sağ tarafının ikinci nesnenin sol tarafından büyük olup olmadığını ve ikinci nesnenin sağ tarafının birinci nesnenin sol tarafından büyük olup olmadığını kontrol ederiz; dikey eksen için de aynı şekilde.
Çarpışma kodunu daha organize tutmak için Game sınıfına ek bir fonksiyon ekliyoruz:
DoCollisions içinde top nesnesiyle seviyedeki her tuğla arasındaki çarpışmaları kontrol ediyoruz. Çarpışma tespit ettiğimizde tuğlanın Destroyed özelliğini true olarak ayarlıyoruz; bu, seviyenin bu tuğlayı render etmesini anında durduruyor:
Oyunun Update fonksiyonunu da güncellememiz gerekiyor:
Kodu çalıştırdığımızda top her tuğla ile çarpışmayı tespit etmeli ve tuğla solid değilse yıkılmalı. Ancak tespit yeterince hassas değil; topun dikdörtgen çarpışma şekli, topun doğrudan temas etmeden çoğu tuğlayla çarpışıyor.
AABB - Daire Çarpışma Tespiti
Top daireye benzer bir nesne olduğundan AABB, topun çarpışma şekli için en iyi seçenek değil. Çarpışma kodu topu dikdörtgen bir kutu olarak değerlendiriyor; bu nedenle top sprite'ı henüz tuğlaya dokunmadan çarpışma tespit ediliyor.

Topu AABB yerine dairesel bir çarpışma şekliyle temsil etmek çok daha mantıklı. Bu nedenle top nesnesine Radius değişkenini ekledik. Dairesel çarpışma şeklini tanımlamak için yalnızca bir konum vektörü ve yarıçap gerekiyor.

Tespit algoritmasını güncellememiz gerekiyor; çünkü şu an yalnızca iki AABB arasında çalışıyor. Daire ve dikdörtgen arasındaki çarpışmayı tespit etmek biraz daha karmaşık, ama şu numara işe yarıyor: AABB'de daireye en yakın noktayı buluruz; bu noktanın daireye olan uzaklığı yarıçaptan azsa çarpışma var.
Bu en yakın noktayı $\color{red}{\bar{P}}$ bulmak için şu yöntemi kullanırız:

İlk olarak topun merkezi $\color{blue}{\bar{C}}$ ile AABB'nin merkezi $\color{green}{\bar{B}}$ arasındaki fark vektörünü $\color{purple}{\bar{D}}$ elde ederiz. Ardından bu vektörü AABB'nin yarı genişliklerine $\color{orange}{w}$ ve $\color{teal}{\bar{h}}$ clamp ederek $\color{green}{\bar{B}}$'ye ekleriz. Yarı genişlikler, dikdörtgenin merkezi ile kenarları arasındaki mesafelerdir (boyutun yarısı). Bu, her zaman AABB'nin bir kenarında yer alan bir konum vektörü döndürür (dairenin merkezi AABB içinde değilse).
Clamp işlemi, bir değeri belirli bir aralık içindeki değere sıkıştırır:
Örneğin 42.0f değeri, 3.0f ile 6.0f aralığında 6.0f'a sıkıştırılır. 2D vektörü clamp etmek hem x hem y bileşeninin belirtilen aralıkta olduğu anlamına gelir.
Bu sıkıştırılmış vektör $\color{red}{\bar{P}}$, AABB'den daireye en yakın noktadır. Ardından dairenin merkezi $\color{blue}{\bar{C}}$ ile $\color{red}{\bar{P}}$ arasındaki fark vektörünü $\color{purple}{\bar{D'}}$ hesaplarız.

$\color{purple}{\bar{D'}}$'nin uzunluğu dairenin yarıçapından azsa çarpışma vardır.
Top nesnesini ilk argüman olarak CheckCollision'a ilettiğimizden, aşırı yüklenmiş CheckCollision sürümü artık otomatik uygulanır. Sonuç oldukça hassas bir çarpışma tespit algoritmasıdır.
Ancak çarpışma tespiti çalışsa da top henüz çarpışmalara hiçbir şekilde tepki vermiyor. Çarpışma gerçekleştiğinde topun konumunu ve/veya hızını güncellememiz gerekiyor. Bu, sonraki bölümün konusu.
Last updated