Atölye › Angry Birds Tarzı Sapan › 25/47. adım
Kutuların birbirinin içinden geçmemesi için collide(a, b) (çarpış) fonksiyonunu yazacağız. Uzun bir fonksiyon, o
yüzden üç adımda kuracağız. Üstteki iki satırlık yorum, fonksiyonun bitmiş hâlinin ne yaptığını anlatıyor.
İlk parça: iki kutu iç içe mi? Öyleyse onları en az bindikleri yönde ayır. Bir kutunun üstünde duran kutu dikeyde çok az, yatayda çok binmiştir; bu yüzden yukarı itilir. Bir kuleyi ayakta tutan tam budur.
Kim ne kadar itilir? Kütle karar verir: hafif tahta çok kıpırdar, ağır taş az. Kütleyi alan × yoğunluktan hesaplıyoruz.
```js
const mass = (b) => (b.w * b.h * MATERIALS[b.kind].density) / 400
// Two overlapping boxes: push them apart along the axis where they overlap least, then bounce their velocities
// along that axis like a collision between two masses, with a little friction along the other axis.
function collide(a, b) {
const ox = Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x)
const oy = Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y)
if (ox <= 0 || oy <= 0) return
const ia = 1 / mass(a)
const ib = 1 / mass(b)
let nx = 0
let ny = 0
let depth
if (ox < oy) [nx, depth] = [a.x + a.w / 2 < b.x + b.w / 2 ? 1 : -1, ox]
else [ny, depth] = [a.y + a.h / 2 < b.y + b.h / 2 ? 1 : -1, oy]
const push = depth / (ia + ib)
a.x -= nx * push * ia
a.y -= ny * push * ia
b.x += nx * push * ib
b.y += ny * push * ib
}
```const mass = (b) => (b.w * b.h * MATERIALS[b.kind].density) / 400 → kütle = alan × yoğunluk / 400. 20 × 20
bir tahta 1, aynı boy taş 2.5, kuş 4 eder.const ox = Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x) → yatay bindirme: iki sağ kenardan
soldakinden (küçüğünden) iki sol kenardan sağdakini (büyüğünü) çıkarır; sonuç iki kutunun ortak kısmının
genişliği. oy aynı şeyin dikeyi.if (ox <= 0 || oy <= 0) return → biri 0 ya da eksiyse kutular değmiyor: çık.const ia = 1 / mass(a) → ters kütle. Hafif gövdenin ters kütlesi büyüktür; itmenin büyük payı ona düşer.let nx = 0, let ny = 0 → normal: itme yönü. let depth → ne kadar itilecek.if (ox < oy) [nx, depth] = [..., ox] → yatayda daha az binmişlerse yana ayır. [nx, depth] = [1, ox] tek
satırda iki değişkene iki değer verir.a.x + a.w / 2 < b.x + b.w / 2 ? 1 : -1 → a'nın ortası b'nin ortasının solundaysa 1 (b sağa itilir), değilse −1.else [ny, depth] = [..., oy] → değilse dikey ayır: a üstteyse ny 1.const push = depth / (ia + ib) → itmeyi kütlelere göre paylaştırmak için ortak çarpan.a.x -= nx * push * ia ... → a normalin tersine, b normal yönünde itilir. İki pay toplanınca tam depth
eder: kutular artık tam değiyor, iç içe değil.const body = ... satırının altına const mass = ... satırını yaz.function step() { satırının üstüne iki yorum satırını ve collide fonksiyonunu yaz (sonra bir boş satır).
Harf harf yaz; her + ve - önemli.collide'ı kimse çağırmıyor. Kontroller yeşil olmalı.Beceriler: Çarpışma tespiti
← Veri olarak seviye Kütleye göre sek →