Bölüm 4 · Sunum 1

Değdi mi? Çarpışma ve sekme

Ekranda gezen şekilleri oyuna çeviren soru: iki şey birbirine değdi mi?

Tuval sınırıDikdörtgenler: AABBDaireler: distSekme

Top rakete değdi mi? Bilgisayar bunu nereden bilecek?

Ekranda yalnızca renkli pikseller var. Program “top” ve “raket” diye bir şey görmüyor; elinde birkaç sayı var.

Çarpışma algılama

Çarpışma algılamaİki ya da daha fazla oyun nesnesinin (ya da bir nesne ile sınırın) geometrik olarak kesişip kesişmediğini her frame kontrol etme işlemidir.

Görsel değil, mantıksal bir testtir: koşul true olunca kodumuz tepki verir. Tuvalde kendiliğinden bir efekt oluşmaz.

AdımİşÖrnek
1Girdiyi okukeyIsDown
2Konumu güncelletopX += hizX * dt
3Çarpışmayı kontrol etKenar, başka blok
4Tepki uygulaSekme, skor, oyun bitişi
5Çizrect, ellipse

Her şey bununla başladı: Pong, 1972

Pong oyununun ekran görüntüsü
Kaynak: Wikimedia Commons, Pong.png (kamu malı)

İki raket, bir top, iki kural:

  • Top rakete değerse yön değiştirir.
  • Top kenardan çıkarsa karşı taraf sayı alır.
Elli yıldır aynı iskeletHareket et → değdi mi? → tepki ver. Bugünün mobil oyunlarında da döngü aynı.

Mini Pong: fareyle raketi oynatın

Bu oyunun tamamı bugün göreceğimiz iki testten ibaret: tuval kenarı ve dikdörtgen örtüşmesi.

Çarpışma olunca ne olur? (1/2)

PongRaket topa değer: yön değişir. Kenar: sekme ya da sayı.
Breakout / ArkanoidTop tuğlaya değer: tuğla kaybolur, skor artar.
Pac-ManHayalete değince can gider; duvara değince yol kesilir.
Super Mario Bros.Zemine inmek, düşmana üstten ya da yandan değmek, altın almak.

Çarpışma olmasa çoğu oyun “boşlukta süzülen şekiller”e iner: raket topa değmez, mermi hedefi delip geçer, karakter duvardan yürür.

Çarpışma olunca ne olur? (2/2)

Flappy BirdBoruya bir kez değmek: oyun biter.
Space Invaders / GalagaMermi uzaylıya değer: düşman yok olur.
Angry BirdsKuş, blok ve domuz kesişince yıkım ve skor. Arkada bir fizik motoru çalışır.
Pinball / bilardoTop engele ya da kenara değer: sekme.

Skor artışı, can kaybı, sekme, kapı açma, ölme… Bu kuralların çoğu, tam da çarpışma testi true olduğu anda uygulanır.

Kuşun kanadı boruya değdi mi? Gagası? Tüyleri?

Karakterin çizimi çok detaylı olabilir. Oyun gerçekten her pikseli tek tek mi kontrol ediyor?

Hitbox: görünmeyen sade şekil

Hitbox (çarpışma kutusu)Çizim ne kadar süslü olursa olsun, “değdi mi?” sorusu çoğu zaman görünmeyen sade bir kutuya ya da daireye sorulur.

Ticari oyunlarda soru iki adımda sorulur

1 · Kaba testUcuzdur. Her nesnenin etrafındaki büyük kutuya bakılır. Kutular uzaksa “değmedi” denir ve iş biter.
2 · İnce testPahalıdır. Yalnızca kutular örtüşünce devreye girer: çoklu hitbox, üçgen-üçgen ya da piksel düzeyinde kontrol.

Amaç, birbirinden uzak çiftler için boşuna ağır hesap yapmamak. Bugün öğreneceğimiz yöntemler (sınır, AABB, dist) bu kaba testlerdir ve Pong’dan Flappy Bird’e oyun hissinin omurgasını oluşturur.

Algılama, fizik simülasyonu değildirGerçekçi sekme, sürtünme, dönme ileri konulardır. Burada yönü tersine çevirmek (hizX = -hizX) yeterli bir tepkidir.

İlk test: tuval sınırı

Sınır (boundary) çarpışmasıHareketli nesnenin tuval kenarına (x = 0, x = width, y = 0, y = height) ya da tanımlı bir oyun alanı sınırına değip değmediğinin kontrolüdür.
ŞekilSol kenarSağ kenarÜst kenarAlt kenar
Dikdörtgen (x, y, w, h)xx + wyy + h
Daire, merkez (cx, cy), yarıçap rcx - rcx + rcy - rcy + r

Hatırlatma: rect sol üst köşeden, ellipse merkezden konumlanır. Kenarların formülü bu yüzden farklı.

Kare tuvalden çıkmasın

Tuvale tıklayıp sağ oka basılı tutun. Karenin sağ kenarı kareX + BOYUT; tuvali aşarsa kareyi geri çekiyoruz.

constrain ile aynı iş, ama…

constrain(x, 0, width - BOYUT)Geçen bölümde aynı sınırı tek satırda uygulamıştık. Pratik bir kısayol.
Açık if bloklarıSınırın ne zaman devreye girdiğini gösterir. O anda başka bir şey yapma şansı verir.
Sekme için constrain yetmezTop duvara çarpınca yön de değişmeli. Bunun için konumu düzelten if ile hızı tersine çeviren satır birlikte yazılır.

Daire için test merkez ve yarıçapla yapılır: topX - r < 0 sol duvara, topX + r > width sağ duvara değmedir.

İki dikdörtgen tam olarak ne zaman “çarpışmış” sayılır?

Birazdan B kutusunu fareyle gezdireceksiniz. Kenarlardaki renkli çubuklara dikkat edin: kutuların eksenlerdeki gölgeleri.

İki eksende birden örtüşme gerekir

B’yi A’nın tam yanına, sonra tam altına götürün: tek eksende örtüşme yetmiyor. Bir eksende boşluk varsa çarpışma yoktur.

AABB ve dört koşul

AABB (Axis-Aligned Bounding Box)Eksen hizalı sınır kutusu: kenarları tuvalin x ve y eksenlerine paralel dikdörtgen. rect() ile çizilen kutular AABB’dir.

Kutu rotate ile döndürülürse kenarlar eksene paralel kalmaz; bu dört koşul tek başına yetmez.

KoşulAnlamı
ax < bx + bwA’nın solu, B’nin sağından solda
ax + aw > bxA’nın sağı, B’nin solundan sağda
ay < by + bhA’nın üstü, B’nin altından yukarıda
ay + ah > byA’nın altı, B’nin üstünden aşağıda

Dördü birden true ise çarpışma var. İlk ikisi x ekseni, son ikisi y ekseni içindir.

Testi bir fonksiyona koymak

SimetriktirHangisine A, hangisine B dediğiniz fark etmez: (A, B) ile (B, A) aynı sonucu verir.
Analitik geometri burada işe yarıyorKoordinatlar, eşitsizlikler, iki nokta arası uzaklık… Formül ezberlemek değil; “gördüğüm şekil hangi geometrik soruya denk geliyor?” diye sormak yeter.

Oyuncu engele değince engel kızarsın

Az önceki örnekte oyuncu engelin içinden geçebiliyordu. Neden durmadı?

Test true döndü, engel kızardı. Peki oyuncuyu durduran bir satır var mıydı?

Algılama ile çözümleme ayrı adımlardır

AlgılamaDeğdi mi?Yalnızca soruyu sorar: true ya da false. Az önce yaptığımız buydu.
ÇözümlemeDeğdiyse ne olacak?Oyuncuyu dışarı itmek, hızı ters çevirmek, hareketi iptal etmek. Ayrıca yazılır.

Önce algılamayı doğru yazın, sonra tepkiyi ekleyin. Birazdan sekmede ikisini birlikte göreceğiz.

koşul ? doğruysa : değilse. Yeni başlarken açık if / else daha okunaklıdır.

Peki iki daire? Dört koşul burada da işe yarar mı?

Dairenin “sol üst köşesi” yok. Elimizde merkez ve yarıçap var. Daire Tıklama oyununda benzer bir soruyu nasıl çözmüştük?

Merkezler arası mesafe, yarıçapların toplamından küçükse

Daire–daire çarpışmasıİki dairenin merkezleri arasındaki mesafe, yarıçapların toplamından küçükse daireler kesişir: d < r1 + r2.

Mesafe nereden geliyor? Pisagor

Daire çarpışması: Öklid mesafesi d ve yarıçap toplamı
  • Yatay fark dx = x2 - x1, dikey fark dy = y2 - y1.
  • Dik üçgende hipotenüs: d = sqrt(dx * dx + dy * dy).
  • p5.js’te hepsi tek çağrı: dist(x1, y1, x2, y2).
< mi, <= mi?Tam dışarıdan değmeyi de saymak için <= kullanılabilir. Hangisini seçerseniz oyunun her yerinde aynısını kullanın.

İki daire: ok tuşlarıyla yaklaştırın

Yeşil daire sabit; sarı daireyi ok tuşlarıyla yaklaştırın. Bütün test iki satır: mesafeyi ölç, yarıçapların toplamıyla karşılaştır.

Bunu daha önce görmüştük

Bölüm 1Daire Tıklamadist(mouseX, mouseY, hedefX, hedefY) < hedefYaricap
Fare bir nokta, hedef bir daireydi.
Bugünİki dairedist(x1, y1, x2, y2) < r1 + r2
Aynı sorunun genel hâli. Noktanın yarıçapı sıfır kabul edilirse ikisi aynı.

Top duvara çarptı. Geri dönmesi için hangi sayıyı değiştirmeliyiz?

Top sağa ve aşağı doğru gidiyor. Sağ duvara çarpınca hangi yönü değişmeli, hangisi aynı kalmalı?

Hız vektörü ve sekme

Hız vektörüNesnenin yatay (hizX) ve dikey (hizY) yönlerdeki hızı, piksel/saniye. Güncelleme: x += hizX * dt, y += hizY * dt.

Sekme: çarpılan duvara dik olan bileşenin işaretini ters çevir. Diğeri aynı kalır.

OlayKonum düzeltmesiHız tepkisi
Sol duvar: x - r < 0x = rhizX = -hizX
Sağ duvar: x + r > widthx = width - rhizX = -hizX
Üst duvar: y - r < 0y = rhizY = -hizY
Alt duvar: y + r > heighty = height - rhizY = -hizY

Duvarlara çarpan top

Her duvar için iki iş: önce topu içeri it (konum), sonra yönü çevir (hız). Algılama ve çözümleme burada birlikte.

Konum düzeltmesini silersek ne olur?

Top duvarın biraz içine girmiş hâlde kaldı. Bir sonraki frame’de test ne söyler?

Top duvara yapışıp titrer

Duvarın içindeyim. Dön!
🏀
frame 1 · hizX = −
Hâlâ içindeyim. Dön!
🏀
frame 2 · hizX = +
Hâlâ içindeyim…
😵‍💫
frame 3 · hizX = −
Önce içeri it, sonra çevirTop duvarın içinde kalırsa test art arda true olur; hız her frame yeniden ters döner.
Köşedeİki duvara birden değince iki if de çalışır; hizX ve hizY aynı frame’de ters döner. Bu beklenen davranıştır.

Hangi çift için hangi test?

ÇiftŞekillerTest
Kare ya da top ↔ tuval kenarıDikdörtgen ya da daire ↔ sınırKenar if’leri
Blok ↔ blokİki rect (AABB)Dört koşullu örtüşme
Top ↔ topİki ellipsedist < r1 + r2
Fare ↔ hedef daireNokta ↔ dairedist < yarıçap

Çarpışma hep bir çift üzerinden düşünülür: “A ile B değdi mi?” Yeni bir nesne eklediğinizde soru aynı: şekli ne? Sınır mı, AABB mi, dist mi?

Hepsi bir arada: mini tuğla kırma

Breakout’un özü: sınır testi (duvarlar), kutu örtüşmesi (raket ve tuğlalar), sekme (vy = -vy) ve tuğlalar için bir dizi ile splice.

Bu konunun üç sınırı

Algılama ≠ çözümlemeTest yalnızca “değdi mi?” der. Konumu düzeltmek ve hızı çevirmek ayrıca yazılır.
Test şekle göre seçilirDikdörtgen için aralık örtüşmesi, daire için merkezler arası uzaklık. İki modeli karıştırmak yanlış sonuç verir.
Hızlı nesnelerTek frame’lik sıçrama, ince bir engelin içinden geçmeye yol açabilir. Küçük adımlar ya da daha büyük hitbox bunu azaltır.
Processing kaynağı okurkenJeff Thompson’ın örneklerinde boolean hit, float x, void draw(), size(600, 400) görürsünüz. p5.js’te karşılıkları let hit, let x, function draw(), createCanvas(600, 400). Matematik aynı; yalnızca yazım farklı.

Yapay zekâyla: sekme yönü

  1. Yatay bir duvara (tavan ya da zemin) çarpan top için hizX ve hizY nasıl değişir? Önce kendiniz yazın.
  2. Yapay zekâdan aynı senaryoyu doğrulamasını isteyin.
  3. Köşeye çarpınca iki bileşenin birden tersine dönmesini bir cümleyle not edin.

Kod zamanı

  1. Kare örneğine yukarı ve aşağı hareketi ekleyin; dört kenarın hepsinde dursun. constrain kullanmayın.
  2. AABB örneğinde oyuncu engelin içine giremesin. İpucu: hareketten önceki konumu saklayın; çarpışma varsa geri dönün.
  3. Seken topa yerçekimi ekleyin: her frame hizY += 600 * dt. Zeminden her sekişte hızın %15’ini kaybetsin.
  4. İki seken top çizin; birbirlerine değdikleri sürece ikisi de kırmızı olsun.
  5. Zorlu: kendi mini Pong’unuzu yazın. Raket klavyeyle, hareket deltaTime ile.

A = (0, 0, 50, 50), B = (50, 20, 30, 30). Çarpışıyorlar mı?

  1. Evet
  2. Hayır

ax + aw > bx → 50 > 50 yanlış. Kenarlar tam değiyor ama örtüşmüyor. Kenar kenara durmayı da saymak isteseydik >= yazardık.

Merkezler (100, 100) ve (160, 180); yarıçaplar 40 ve 50. Çarpışıyorlar mı?

  1. Evet
  2. Hayır

dx = 60, dy = 80 → d = 100. Yarıçapların toplamı 90. 100 < 90 yanlış: aralarında 10 piksel boşluk var.

Top sağa ve yukarı gidiyor: hizX = 200, hizY = −150. Tavana çarptı. Yeni hızlar?

  1. −200 ve −150
  2. 200 ve 150
  3. −200 ve 150
  4. 200 ve −150

Tavan yatay bir duvar: yalnızca dikey bileşen ters döner. Top sağa gitmeye devam eder, artık aşağı doğru.

Merak edenler için kaynaklar

Bugün ne öğrendik?

  • Çarpışma algılama her frame sorulan mantıksal bir sorudur: değdi mi?
  • Tuval sınırı: dikdörtgende x + w > width, dairede x + r > width.
  • AABB: iki dikdörtgen, hem x hem y ekseninde örtüşüyorsa çarpışır. Dört koşul.
  • İki daire: dist < r1 + r2.
  • Sekme: önce konumu içeri it, sonra ilgili hız bileşenini ters çevir.
  • Oyunlar süslü çizimi değil, sade bir hitbox’ı test eder.

Sıradaki ders

Menü, oyun, bitiş

Durum makinesi: oyun şu an hangi ekranda?