HTML5 Canvas · Sprite ve varlık sistemi
Sprite levhası: tek görüntüden çok kare çizmek
Sprite sheet (
veya texture atlas ), birden çok küçük kareyi tek raster dosyada toplar;
tarayıcı bir kez yükler, siz her kare için farklı kaynak dikdörtgen (
sx, sy, sw, sh ) seçersiniz. Canvas 2D’de
bu iş drawImage’in dokuz argümanlı biçimiyle yapılır — bu sayfa parametre sırasını,
düzenli ızgara matematiğini ve ölçekte «komşu piksel sızıntısı» riskini sabitler. Levha dosyası
belleğe alma
Resim yükleme sayfasında; karelerin
zamanda nasıl döneceği
Kare animasyonu başlığında kalır.
Çizim alışkanlıkları ve dönüşüm yığını için 2D bağlam ve Temizle ve yeniden çiz ile uyum düşünün; varlık önbelleği Varlık önbellekleme ile ilişkilidir.
Özet: levhadan tuvala veri yolu
| Veri | Anlam | Not |
|---|---|---|
image |
Yüklü levha | Hazır raster |
sx, sy, sw, sh |
Levhadaki kaynak pencere | Piksel; levha uzayında |
dx, dy, dw, dh |
Tuvalde hedef pencere | Dünya veya piksel birimi |
| Kare indeksi | Izgara satır / sütun | Marj ve köken ile birlikte |
| Zaman | Hangi kare seçilecek | Animasyon sayfası |
Atlas mantığı: neden tek dosya
Çoklu küçük dosya yerine tek levha, HTTP istek sayısını düşürür ve ağ gecikmesinde özellikle
mobilde hissedilir kazanç sağlar. Bellekte tek büyük doku tutulduğu için toplam piksel aynı
kalsa bile yönetim basitleşir — tek HTMLImageElement referansı, çok sayıda
çizim çağrısı. Tasarım aracından dışa aktarırken kareler arasına ince boşluk (
padding ) bırakmak, ölçeklendirmede komşu hatları yutmamayı
kolaylaştırır.
Levha «kaç sütun / kaç satır» bilgisi ya görsel olarak sabitlenir ya da dışarıdan ( JSON, doku paketleyici çıktısı ) okunur. Bu sayfa düzenli ızgara ve indeks üzerinden gider; tam otomatik dikdörtgen paketleme ( bin packing ) araç konusudur, çizim API’si konusu değildir.
Aynı levha hem karakter yürüyüşü hem UI rozetleri içerebilir; mantıksal olarak «alt atlaslar» gibi düşünmek ( farklı indeks aralıkları veya köken ofsetleri ) kod okunurluğunu artırır. Çizim sırasında hangi kütük önce hangi sonra — bu sayfanın bağlam ve sıra bölümünde özetlenir.
Dokuz argümanlı drawImage: kaynak ve hedef
İmza: ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) — kaynak piksel
bölgesi kopyalanır, hedef dikdörtgene ölçeklenerek yapıştırılır. Koordinatlar kaynakta levha
sol–üstüne göre, hedefte tuval (
veya aktif dönüşüm matrisine göre ) ölçülür. sw veya sh sıfırsa
tarayıcı çizmez veya davranış belirsizdir; üretimde savunmacı sınır koyun.
Üç argümanlı biçim tüm görüntüyü hedefe taşır; beş argümanlı biçim kaynak boyutunu değiştirmeden hedef boyutu verir; dokuzlu biçim sprite diliminin özüdür. Karıştırmak sık hata kaynağıdır — proje içinde tek sarmalayıcı fonksiyon kullanmak imzayı sabitler.
Görüntü henüz yüklenmediyse veya decode beklenmediyse çağrı sessizce başarısız
veya eksik çizim üretebilir; çağırmadan önce
hazırlık katmanından
geçirin.
/**
* Levha dilimini hedef dikdörtgene çizer. image: yüklü HTMLImageElement.
*/
function drawSpriteSlice(ctx, image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (!ctx || !image || !image.complete) return;
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) return;
ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
}
Düzenli ızgara: indeks, sütun ve marj
Kareler eş boyutlu ve soldan sağa, yukarıdan aşağıya diziliyse indeks i için
sütun i % cols, satır (i / cols) | 0 (
tamsayı bölme ) ile bulunur. Köşede originX, originY ofseti (
başlık şeridi, boşluk ) varsa her hücrenin sol–üstü bu ofsete göre kaydırılır. Kareler
arası boşluk padX, padY ile modellenir: adım genişliği
cellW + padX olur.
İndeks sınırları dışına taşmak ( animasyon fazla kare oynatıyorsa ) levhanın yan piksellerini çeker ve görsel «glitch» üretir; üst katmanda indeksi clamp’lemek veya döngü uzunluğunu animasyon mantığında sabitlemek gerekir. Bu sayfa matematiksel dikdörtgeni üretir, oyun mantığı hangi indeksi istediğine karışmaz.
Bazı araçlar «sıcak nokta» (
pivot ) meta verisi yazar; dilim çizimi yine aynı
drawImage ile yapılır, yalnız dx, dy seçiminde pivot
çıkarılır — konuşlandırma bu sayfanın sınırında, çizimle temas eden kısımda tutulur.
/**
* index: 0 uzunlu sol–üst; cols: satır başına hücre; pad*: hücreler arası boşluk.
* Dönüş: drawSpriteSlice ile uyumlu { sx, sy, sw, sh }.
*/
function gridCellRect(index, cols, cellW, cellH, originX = 0, originY = 0, padX = 0, padY = 0) {
const col = index % cols;
const row = (index / cols) | 0;
const stepW = cellW + padX;
const stepH = cellH + padY;
return {
sx: originX + col * stepW,
sy: originY + row * stepH,
sw: cellW,
sh: cellH,
};
}
Ölçek ve komşu piksel: sızıntı ve yumuşatma
Kaynak dikdörtgen komşu karelere yapışıksa, hedefte kesirli ölçek (
dw /
sw oranı irrasyonel ) veya dönüşüm sonrası alt piksel kayması, doğrusal
filtreleme nedeniyle yan taraftaki renkleri «sızdırtır». Tasarımda ara tampon (
bir piksel şeffaf veya kopya kenar ), araçta dışa aktarım
extrude veya içeride marj çoğu zaman daha ucuz çözümdür; shader
yazmadan Canvas 2D’de tam kontrol sınırlıdır.
Piksel sanatı için ctx.imageSmoothingEnabled = false ve mümkünse tam sayılı
hedef
boyutları tercih edilir; vektörel ölçekte ise yumuşatma açık kalabilir — ürün stiline göre
bağlam bazında (
kare başı ) değiştirmek yaygındır, global ve kalıcı ayarı unutmayın.
Cihaz piksel oranı (
devicePixelRatio ) tuvalin iç çözünürlüğünü büyütür; mantık
koordinatları ile çizim koordinatları ayrılmışsa dilim boyutları tutarlı kalmalıdır — ölçek
sadece tuval kurulumunda değil, dw,
dh planında da gözden geçirilmelidir.
Düzensiz kareler ve harici meta veri köprüsü
Gerçek atlaslar sıkça farklı genişlik ve yüksekliklere sahip kareler içerir; her kare için
{ name, x, y, w, h } tablosu (
JSON ) okunur ve doğrudan drawSpriteSlice’e iletilir.
Bu sayfa JSON şemasını üretmez — güvenli tüketim için şemayı doğrulayın (
pozitif w,
h, levha sınırları içinde ).
Araç çıktıları bazen döndürme ve kırpma bilgisi de ekler; Canvas 2D’de ek dönüşüm için
save /
translate /
rotate /
restore kullanılır — detay
bağlam
dokümantasyonunda. Levha sayfası yalnız dikdörtgen dilimi üretildiğini varsayar.
İsim tabanlı çizim (
"walk_03" → dikdörtgen ) bir sözlük önbelleği ile çözülür; dosya değişince
sözlüğü yenilemek gerekir —
önbellek stratejisiyle uyumlu
düşünün.
Hedef dikdörtgen: oyun birimi ve en-boy oranı
Kaynak en–boy oranı ile hedef en–boy oranı farklıysa sprite gerilir; istenmeyen sıkışma için
dw,
dh seçiminde ya «içine sığdır» (
contain ) ya da «kırp» (
cover ) politikasını kodlayın. Fizik gövdesi ile görsel sınır çoğu
zaman aynı değildir; çarpışma kutusu ayrı sayılarda tutulur — levha sayfası yalnız görsel
boyutu ilgilendirir.
Negatif dw ile yatay yansıtma tekniği (
aynaya çevirme ) kullanılabilir; bu da bağlam dönüşümü alternatifidir. İki yöntemi aynı
varlıkta karıştırmamak için ekip içi tek tercih belirleyin.
Uzamsal sıralama (
önce zemin sonra oyuncu ) için globalCompositeOperation veya sadece çizim
sırası yeterlidir; bu levha kullanımından bağımsız ama aynı kare içinde planlanmalıdır.
Bağlam durumu: save, clip ve çizim sırası
Her sprite öncesi save /
restore kullanmak maliyetlidir; yalnız dönüşüm veya opaklık değişecekse
sarın. Kalıcı olarak bırakılan translate bir sonraki varlığı yanlış yere çizer
—
kare sonunda bağlamın bilinen bir tabana dönmesi (
restore veya explicit reset ) hata ayıklamayı kolaylaştırır.
clip() ile maskelenmiş çizim, levha dilimini değil sonraki çizim komutlarını
kısıtlar; yanlışlıkla tüm sahneyi kesmek sık görülür. Dilim zaten drawImage ile
sınırlı alan kopyalar — ek clip genellikle gereksizdir.
Vurgu, seçim parıltısı gibi efektler çoğu zaman ayrı geçici tuval veya ikinci geçiş ister; bu sayfa tek geçişli basit dilim çizimini hedefler. Performans için aynı levha ve aynı filtre ayarıyla toplu çizim gruplamak küçük de olsa kazanç sağlayabilir.
Anti-kalıplar: yanlış argüman sırası ve taşan indeks
Bu dört örnek çoğu zaman birlikte görülür: yanlış parametre sırası bir karede bozulmuş kopya, marj ihmalinde sistematik «yanlış kostüm», taşan indekslerde rastgele komşu pikseller ve çizim döngüsünde ağ çağrısı ise kare süresi dalgalanması üretir. Hepsi, bu sayfada zaten önerilen sarmalayıcı ve ızgara modeli ile sınırlı kalır; yeni API öğrenilmez.
Beş ve dokuz parametreyi karıştırmak: Üç, beş ve dokuz argümanlı aşırı
yüklemeler farklı anlamlarda konum ve boy sunar; doğru imzayı ezberlemek yerine yalnız
dokuzlu yolu kullanan bir
drawSpriteSlice (
veya tek isimli yardımcı ) ile çağrıları kilitleyin. Hata ayıklamada «değerler doğru
görünüyor ama görüntü kayıyor» genelde bu karışımın işaretidir.
Marj unutulmuş ızgara: Dışa aktarımda sütunlar arası bir iki piksel boşluk
bile, saf col * cellW hesabını kaydırır ve her karede komşu kostümün
şeridini gösterir. Tasarım ölçüleriyle birebir örtüşen
padX /
padY ve gerekiyorsa originX /
originY zorunludur; araç önizlemesi ile levha piksel koordinatlarını yan yana
doğrulamak hızlı teşhis sağlar.
Levhadan taşan sx /
sy veya sw /
sh: Kaynak dikdörtgen levha sınırını kesiyorsa sonuç tarayıcıya
göre kırpılabilir veya tutarsız görünebilir; özellikle negatif kalanlar oluşturan son
kareler animasyonda taşar. İndeksi clamp’lemek, kare sayısını
animasyon tarafında sabitlemek
veya levha dışına çıkmayı geliştirme ortamında sınır kontrolleriyle tespit etmek üretimde
sürprizi
azaltır. Komşu kare «sızıntısı» ile karıştırmak için
ölçek ve filtre bölümüne bakın — biri
geometri taşması, diğeri örnekleme kaynaklıdır.
Yükleme çağrısı çizim döngüsünde: Her requestAnimationFrame
turunda new Image() veya ağ tabanlı yükleme başlatmak hem gecikme üretir hem
çizimi belirsiz bırakır; levha
önceden yüklenip hazır
tutulmalı, çizim yalnız hazır referans üzerinden
drawSpriteSlice çağırmalıdır. Geç yükleme senaryosu ayrı bir «hazır değil»
fazı veya yer tutucu ile yönetilir, kare içinde ağ bloklamaz.
Bu sayfanın sınırı
GPU dokuları, atlas bin-packing araçları ve çoklu çözünürlük (
mipmap ) burada işlenmez. Odak: Canvas 2D
drawImage ile dikdörtgen dilim seçmek ve düzenli ızgara matematiğidir.
- Dokuzlu
drawImageparametreleri doğru sırada mı? - Izgara marjı ve köken ofseti tasarımla eşleşiyor mu?
- Ölçekte komşu kare sızıntısı için tasarım tamponu var mı?
- Animasyon indeksi levha boyutları içinde mi?
- Bağlam dönüşümü kare sonunda tutarlı bir tabana dönüyor mu?