Bölüm 4 · Sunum 1
Ekranda gezen şekilleri oyuna çeviren soru: iki şey birbirine değdi mi?
Ekranda yalnızca renkli pikseller var. Program “top” ve “raket” diye bir şey görmüyor; elinde birkaç sayı var.
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 |
|---|---|---|
| 1 | Girdiyi oku | keyIsDown |
| 2 | Konumu güncelle | topX += hizX * dt |
| 3 | Çarpışmayı kontrol et | Kenar, başka blok |
| 4 | Tepki uygula | Sekme, skor, oyun bitişi |
| 5 | Çiz | rect, ellipse |

İki raket, bir top, iki kural:
Bu oyunun tamamı bugün göreceğimiz iki testten ibaret: tuval kenarı ve dikdörtgen örtüşmesi.
Ç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.
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.
Karakterin çizimi çok detaylı olabilir. Oyun gerçekten her pikseli tek tek mi kontrol ediyor?
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.
hizX = -hizX) yeterli bir tepkidir.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.| Şekil | Sol kenar | Sağ kenar | Üst kenar | Alt kenar |
|---|---|---|---|---|
Dikdörtgen (x, y, w, h) | x | x + w | y | y + h |
Daire, merkez (cx, cy), yarıçap r | cx - r | cx + r | cy - r | cy + r |
Hatırlatma: rect sol üst köşeden, ellipse merkezden konumlanır. Kenarların formülü bu yüzden farklı.
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.if bloklarıSınırın ne zaman devreye girdiğini gösterir. O anda başka bir şey yapma şansı verir.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.
Birazdan B kutusunu fareyle gezdireceksiniz. Kenarlardaki renkli çubuklara dikkat edin: kutuların eksenlerdeki gölgeleri.
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.
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şul | Anlamı |
|---|---|
ax < bx + bw | A’nın solu, B’nin sağından solda |
ax + aw > bx | A’nın sağı, B’nin solundan sağda |
ay < by + bh | A’nın üstü, B’nin altından yukarıda |
ay + ah > by | A’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.
(A, B) ile (B, A) aynı sonucu verir.Test true döndü, engel kızardı. Peki oyuncuyu durduran bir satır var mıydı?
true ya da false. Az önce yaptığımız buydu.Ö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.
Dairenin “sol üst köşesi” yok. Elimizde merkez ve yarıçap var. Daire Tıklama oyununda benzer bir soruyu nasıl çözmüştük?
d < r1 + r2.
dx = x2 - x1, dikey fark dy = y2 - y1.d = sqrt(dx * dx + dy * dy).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.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.
dist(mouseX, mouseY, hedefX, hedefY) < hedefYaricapdist(x1, y1, x2, y2) < r1 + r2Top sağa ve aşağı doğru gidiyor. Sağ duvara çarpınca hangi yönü değişmeli, hangisi aynı kalmalı?
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.
| Olay | Konum düzeltmesi | Hız tepkisi |
|---|---|---|
Sol duvar: x - r < 0 | x = r | hizX = -hizX |
Sağ duvar: x + r > width | x = width - r | hizX = -hizX |
Üst duvar: y - r < 0 | y = r | hizY = -hizY |
Alt duvar: y + r > height | y = height - r | hizY = -hizY |
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.
Top duvarın biraz içine girmiş hâlde kaldı. Bir sonraki frame’de test ne söyler?
true olur; hız her frame yeniden ters döner.if de çalışır; hizX ve hizY aynı frame’de ters döner. Bu beklenen davranıştır.| Çift | Şekiller | Test |
|---|---|---|
| Kare ya da top ↔ tuval kenarı | Dikdörtgen ya da daire ↔ sınır | Kenar if’leri |
| Blok ↔ blok | İki rect (AABB) | Dört koşullu örtüşme |
| Top ↔ top | İki ellipse | dist < r1 + r2 |
| Fare ↔ hedef daire | Nokta ↔ daire | dist < 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?
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.
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ı.hizX ve hizY nasıl değişir? Önce kendiniz yazın.constrain kullanmayın.hizY += 600 * dt. Zeminden her sekişte hızın %15’ini kaybetsin.deltaTime ile.ax + aw > bx → 50 > 50 yanlış. Kenarlar tam değiyor ama örtüşmüyor. Kenar kenara durmayı da saymak isteseydik >= yazardık.
dx = 60, dy = 80 → d = 100. Yarıçapların toplamı 90. 100 < 90 yanlış: aralarında 10 piksel boşluk var.
Tavan yatay bir duvar: yalnızca dikey bileşen ters döner. Top sağa gitmeye devam eder, artık aşağı doğru.
x + w > width, dairede x + r > width.dist < r1 + r2.Sıradaki ders
Durum makinesi: oyun şu an hangi ekranda?