holodepth

HTML5 Canvas · Oyun mantığı ve çarpışma

AABB çarpışması: eksen hizalı sınır kutusu

AABB ( axis-aligned bounding box ), dünya eksenlerine paralel bir dikdörtgen sınırdır — Canvas 2D oyun döngüsünde en ucuz ve en yaygın yaklaşım türlerinden biridir. Gerçek sprite dikdörtgen olmasa bile, manyetik bir «vuruş kutusu» ( hitbox ) olarak AABB kullanmak; platform, top‑down ve basit fizik önizlemelerinde yeterli doğruluk / performans dengesi verir. Bu sayfa kutunun matematiksel temsilini, çakışma sınamasını ve hafif ayırt etme ( separation ) düşüncesini Canvas koordinatlarında sabitler; dönen gövdeler ve dairesel sınır için Daire çarpışması ve hareket için Hız ve hareket komşu başlıklardadır.

Kare tabanlı güncelleme ve zaman adımı Delta time ile hizalanmalıdır; çarpışmayı olay ( event ) yerine güncelleme adımı içinde çözmek, tuğla oyunlar ve platformlarda öngörülebilirlik sağlar — Oyun durumu mantığı ile birlikte düşünün.

Özet: AABB temsilleri

Temsil Alan Not
minX, minY, maxX, maxY Köşe çifti Çakışma testi için okuması kolay; genişlik doğrudan maxX - minX
x, y, w, h Sol–üst + boyut Tuval çizimi ( fillRect ) ile doğal eşleşir; test öncesi min/max’e çevrilebilir
cx, cy, hw, hh Merkez + yarı genişlik Fizik simülasyonlarında simetrik; yine min/max türetilir

Kutu nedir: temsil, birim ve tuval uzayı

AABB, döndürülmemiş dikdörtgendir: kenarlar x ve y eksenlerine paraleldir. Canvas bağlamında koordinatlar genelde sol–üst kökenli, x sağa, y aşağıdır; bu, kutunun «min y üstte / küçük y», «max y altta / büyük y» anlamına gelir. Takım içinde tek bir sözleşme seçin ( sol–üst + w/h veya min/max ) ve tüm varlık ( entity ) kodunda ona sadık kalın — karışık temsil, çarpışma ve çizimin birbirinden kaymasının bir numaralı nedenidir.

min/max temsilinde tutarlılık şartı minX ≤ maxX ve minY ≤ maxY’dir; animasyon veya fizik entegrasyonu bazen geçici olarak ters sınır üretebilir — testten önce tek bir normalizeAABB ( köşeleri sıralamak ) çağrısı birçok gizli hatayı keser. Tasarımcı köşe veya merkez tabanlı yerleşim gönderiyorsa, içeri aktarım anında tek yerde dönüştürün; dört farklı dosyada «yarı genişlik mi tam genişlik mi?» hesabı birikir.

Sprite görüntüsü şeffaf kenarlı olabilir; grafik ölçeği ile vuruş kutusu bilinçli olarak farklı tutulabilir ( daha sıkı veya daha gevşek oynanış ). AABB, görsel örtüşmeden bağımsız mantıksal sınırdır; debug için yarı saydam bir dikdörtgen çizmek, kutuyu oyuncuya değil geliştiriciye göstermenin ucuz yoludur. Vuruş kutusunu görselden türetmek ( otomatik kırpma ) isterseniz, üretim boru hattında bir kez hesaplayıp sabitleyin; her karede piksel tarama tuval oyununda pahalıdır ve bu sayfanın odağı dışındadır.

Çizim kodunuz drawImage ile merkez hizalı çalışıyorsa, çarpışma kutusu yine dünya öncelikli min/max’te kalmalıdır; çizer ile çarpışmacının aynı «çıpa»yı paylaştığından emin olun — aksi halde imajın 3 px sol boşluğu kutunun dışında kalsa bile isabet «erken» tetiklenir.

Çakışma sınaması: eksen başına aralık kesişimi

İki AABB, yalnız hem x hem y projeksiyonlarında aralıklar kesişiyorsa çakışır. Koşullar: a.minX < b.maxX, a.maxX > b.minX, aynı mantık y için — dört karşılaştırma yeterlidir. Bu, 3B’deki SAT ( ayrıştırma eksenleri ) fikrinin 2B özel halidir; ek trigonometri gerektirmez, dallanması tahmin edilebilir. X ekseninde ayrılık varsa y kontrolüne gitmeden erken çıkış yapılabilir — çok sayıda reddedilen çift için küçük ama ölçülebilir kazanç.

A tamamen B içindeyse yine aynı dört koşul sağlanır; «içerme» özel durumları ayrı dallanma gerektirmez. Tersine, yalnız kenarlara yapışıklık ayrımı istiyorsanız ( örn. tetik alanı ) karşılaştırmalara epsilon veya farklı eşitsizlik eklemek gerekir — varsayılan overlapsAABB sınırı serttir.

Kenar paylaşma ( touching ): çoğu uygulamada < / > kullanımı «yapışık ama iç içe değil» durumunu çakışmasız sayar; ince tünel oluşturma veya sızdırma ( tunneling ) önlemleri ayrı konudur. Kararınızı sabitleyin ve testleri bununla yazın. Alt piksel hassasiyetinde entegrasyon kullanıyorsanız kayan nokta gürültüsü bazen sınırda titreme yaratır — çözünürlük katmanında yuvarlama veya küçük epsilon, test katmanında değil, tek politikada toplanmalıdır.

/** min/max temsili. Kenar temasında false dönmek için <= kullanmayın (takım kararı). */
function overlapsAABB(a, b) {
  return (
    a.minX < b.maxX &&
    a.maxX > b.minX &&
    a.minY < b.maxY &&
    a.maxY > b.minY
  );
}

function aabbFromXYWH(x, y, w, h) {
  return { minX: x, minY: y, maxX: x + w, maxY: y + h };
}

Çözünürlük: gömülülük derinliği ve eksen seçimi

Çakışma bulunduktan sonra çoğu basit oyunda nesneleri ayırarak iç içe geçmeyi önlersiniz. Kesişim uzunlukları: px = min(a.maxX, b.maxX) - max(a.minX, b.minX) ve aynı şekilde py; ikisi pozitifse gömülülük vardır. Daha küçük gömülülük ekseninde itme, «en az hareketle çöz» yaklaşımıdır — platformcılarda genelde dikey öncelik ( zeminde durma ) verilir; bu ürün kuralıdır, matematik zorunluluğu değildir.

px === py ( kare gömülülük ) durumunda hangi eksenin seçileceği deterministik bir kurala bağlanmalıdır; örnekte ( aşağıdaki kod ) y eksenine düşülür — platformda bunu y ekseni önceliği ile uyumlu seçin. Ardışık çoklu çarpışmada tek geçişlik ayırma yeterli olmayabilir; nesneler zincirleme iter ( birkaç kez çöz veya sırayla tüm engelleri uygula ) yaygın pratikdir, fakat sıra bağımlılığı doğurur — bunu bilinçli kabul edin veya sabit adımda alt iterasyon sınırı koyun.

İki dinamik gövdeye simetrik çözüm uygularken itmeyi yarı yarıya paylaştırabilir veya birini kinematik ( duvar, blok ) kabul edip yalnız diğerini kaydırabilirsiniz. Kütle veya oyuncu önceliği bu katmanda politikalaşır — Temel fizik sayfasıyla birlikte tasarlanması doğaldır. Sekme veya sıçrama ( restitution ) eklemek, bu geometrik ayırmanın üzerine ayrı bir enerji katmanıdır; önce gömülülüğü giderin, sonra hızı güncelleyin — aksi halde iç içe gövde hız alırken yine kesişir.

/**
 * b sabit kabul; a'yı en küçük gömülü eksende iter.
 * nx/ny: kutuların göreli merkezine göre it yönü kabaca seçilir.
 */
function separateAABBIntoStatic(a, b) {
  const px = Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX);
  const py = Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY);
  if (px <= 0 || py <= 0) return a;

  const nx = (a.minX + a.maxX) * 0.5 < (b.minX + b.maxX) * 0.5 ? -1 : 1;
  const ny = (a.minY + a.maxY) * 0.5 < (b.minY + b.maxY) * 0.5 ? -1 : 1;

  let out = { ...a };
  if (px < py) {
    out.minX += nx * px;
    out.maxX += nx * px;
  } else {
    out.minY += ny * py;
    out.maxY += ny * py;
  }
  return out;
}

Tuval, karo ve geniş faz: O(n²) sınırı

Onlarca varlıkta çiftler halinde overlapsAABB çağırmak kabul edilebilir; yüzlerce ve üstünde ikili döngü ana iş parçacığını sıkıştırır. Düzenli ızgara ( tile map ) kullanıyorsanız, AABB’yi karo indeks aralığına bölmek geniş faz olarak iş görür; yalnız ilgili hücrelerdeki duvarlarla ince faz sınaması yapılır. Karo boyutu sabitse, kutunun kapladığı indeks aralığı floor / ceil ile iki eksende birkaç tamsayıdır; duvar listesi karo başına kısaysa bellek ve dal sayısı düşer.

Uniform olmayan serbest nesneler için basit bölme ızgarası ( spatial hash ) düşünülür — bu sayfada uygulama yok, yalnızca ölçek uyarısı verilir. Hücre boyutu, tipik varlık çapına göre seçilir: çok büyükse her şey aynı kutuya düşer, çok küçükse karma maliyet artar. Geniş faz sonrası kalan aday çiftler hâlâ overlapsAABB ile doğrulanır; yanlış negatif olmaması için hücreyi genişletilmiş sorgu kutusu ile taramak gerekir.

Tuval kökeni ( 0,0 ) dünyanızla çakışmalıdır; kamera kaydırması dünya koordinatında AABB tutup çizimde dönüşüm uygulamak, çarpışmayı ekran sapmasından ayırır. Yoğun sahnede yalnız kirli bölgeleri çizmek istiyorsanız çarpışma sonucu ile aynı dünya uzayında kirli dikdörtgen birleştirmek, Update vs render · kirli bayrak düşüncesiyle örtüşür — bu sayfa geometriyi sabitler, kısmi boyama taktikleri komşu konudur.

Dönme, tünel ve AABB sınırı

Dönen sprite görsel olarak eğilir; AABB köşeleri hâlâ eksen hizalı kalırsa köşe bölgeleri fazla hacim kapsar veya eksik kalır — bu yüzden dörtlüler için sıkı kutular, daire yaklaşımı veya dönen kutu ( OBB ) ayrı konudur. Bu seri OBB’ye girmez; ihtiyaç halinde çarpışma modelini bilinçli genişletin. Orta yol: dönüş açısına göre birkaç sabit AABB ( kare kare kılıf ) ile yaklaşım — hâlâ yaklaşımdır; en doğru yuvarlak gövdeler için Daire çarpışması daha uygun primer model olabilir.

Animasyon kareleri değiştikçe kılıf boyutunu her kare güncellemek ( en sıkı AABB ) maliyetli olabilir; çoğu prototipte sabit vuruş kutusu ile yaşanır ve sanat tarafı ona göre çizilir. «Her kare sprite sınırını ölç» yaklaşımı üretim boru hattı gerektirir.

Yüksek hızda tek karede duvarın içinden «sıçrama» ( tunneling ), AABB örneklemesiyle yakalanmayabilir; küçük zaman adımı, süpürme ( sweep ) veya alt adımlar ürün kararıdır — Delta time ve sabit adım hakkında komşu içeriklerle hizalayın. Çarpışma adımı ile çizim adımının ( Kare yönetimi ) aynı saatte kilitlendiğinden emin olun; biri ileri diğeri gecikirse oyuncu kutuyu «geçmiş» gibi görür.

Anti-kalıplar: dönüşüm ve çift temsil

Karışık temsil: Bir modülde x,y,w,h, diğerinde min/max; dönüşüm formülü dağınık — sapma birikir. Ortak toMinMax / toXYWH çiftini tek dosyada versiyonlayın; çarpışma ve çizim aynı yapıyı import etmelidir.

Ekran ve dünya karışıklığı: Çarpışmayı piksel ötesi dünyada yapmadan kamera kaydırması uygulanması. Dünya AABB’si çizime taşınırken yalnızca görüntü matrisi değişir; tersine çeviri girdi ( tıklama ) için Event koordinatları · tek köprü hattıyla uyum düşünün — bu sayfa dünya içi geometriye odaklanır.

Dönen sprite, sabit AABB: Oyun hissini bozan isabet; görsel ile mantıksal sınır bilinçli hizalanmalıdır. Geçici çözüm çoğu zaman sanatın kutuya göre hizalanması, kalıcı çözüm alternatif çarpışma şeklidir ( Dönme ve tünel ).

Çözünürlük yönü: Varsayılan «küçük eksen» her senaryoda doğru değil; platformda y ekseni önceliği yaygın kuraldır. Kodda eksen seçimini sabitleyin ve tasarım belgesine yazın; aksi halde yama yama öncelikler farklı bloklarda çelişir.

Tek geçişlik çözüm: Zincirleme duvarlarda bir itişte yeni tutun üretmek; iterasyon sınırı veya sıralı çözüm politikası yoksa zıplama ( jitter ) görülür — özellikle köşe kertiklerinde.

Bu sayfanın sınırı

OBB, çokgen–çokgen SAT, sürekli fizik motorları ve üçüncü boyut kutu ağaçları burada ele alınmaz. Amaç: Canvas 2D prototip ve hafif oyunlarda AABB’yi doğru ve öngörülebilir kullanmak.

  • Tüm varlıklar aynı AABB sözleşmesinde mi (min/max veya xywh)?
  • Çarpışma dünya uzayında mı; kamera yalnız çizimde mi?
  • Kenar teması çakışma mı sayılıyor; test buna göre mi yazıldı?
  • Çözünürlük hangi eksende öncelikli; platform kuralları net mi?
  • px === py beraberliğinde eksen seçim kuralı belgelendi mi?
  • Zincirleme çarpışmada tek geçiş yeterli mi; iterasyon / sıra politikası var mı?