holodepth

HTML5 Canvas · Sprite ve varlık sistemi

Varlık önbellekleme: tarayıcı ve bellek katmanları

Canvas oyununda aynı sprite levhası on kez «ihtiyaç duyuldu» diye on kez ağdan indirilmez; tarayıcı HTTP önbelleği ilk yanıtı saklar, siz de isteğe bağlı olarak bellek içi ( in-memory ) bir sözlükte HTMLImageElement veya onu üreten Promise tutarsınız. Bu sayfa tekilleştirme ( aynı URL için tek uçuş ), sürümleme ile önbellek kırma ve eşzamanlı yükleme yarışlarını Canvas öğretim hedefiyle sabitler. Dosyayı ilk kez getirmek Resim yükleme sayfasında; dilimleme Sprite levhası, kare zamanlaması Kare animasyonu başlıklarındadır.

Zaman ve çizim disiplini için Kare yönetimi ve Update vs render ile birlikte düşünün; ağır yükleme fazını oyun döngüsünden ayırmak kare fazları düşüncesiyle uyumludur.

Özet: iki katmanlı önbellek

Katman Ne tutar? Yöneten
HTTP önbelleği Ağ yanıt gövdesi ( dosya baytları ) Tarayıcı + başlıklar
Bellek sözlüğü Promise veya Image Uygulama kodu
Görüntü nesnesi Dekode edilmiş raster Tarayıcı / GPU
Sürüm URL veya sorgu anahtarı Yayın süreciniz
Tüketim drawImage Dilim çizimi

Tarayıcı önbelleği ve uygulama sözlüğü: roller

İlk fetch veya img.src = url isteği sunucuya gider; yanıt Cache-Control ve benzeri başlıklarla tarayıcı diske veya belleğe alınabilir. İkinci kez aynı URL ile istek yapan kod, ağ paketini görmeyebilir — ama yine de yeni bir Image nesnesi oluşturup dekode ederseniz JavaScript belleğinde ikinci kopya oluşturmuş olursunuz. Bu yüzden üretimde genelde «tek URL → tek uygulama düzeyi önbellek girişi» hedeflenir.

Statik site veya sürüm çözümlemesi zayıfsa kullanıcı eski dosyayı görmeye devam eder; bu, Canvas hatası gibi görünür ama aslında önbellek politikasıdır. Geliştirici araçlarında «önbelleği devre dışı bırak» ile davranış farkını ayırt etmek yaygın teşhis adımıdır.

Bu sayfa sunucu başlıklarını yapılandırmayı öğretmez — yalnız istemci tarafı tekilleştirme ve sürümleme ile ürün kodunun önbellekle nasıl uyumlu kalacağını sabitler.

Promise önbelleği: aynı URL için tek uçuş

İki modül aynı karede loadImage(url) çağırabilir; tarayıcı ağ katmanında istekleri birleştirse bile istemci tarafında yine de iki ayrı HTMLImageElement üretilip iki kez dekode edilebilir. Promise önbelleği bu yüzden «tek uçuş» ( aynı mantıksal anahtar için tek paylaşılan Promise ) sağlar: ikinci çağrı yeni istek başlatmak yerine aynı vaadi döner. Bu, HTTP önbelleğinin ne yaptığından bağımsız bir optimizasyondur — katman farkı birinci bölümde özetlenmiştir.

Önbellek anahtarı dizedir; göreli / mutlak URL farkı iki giriştir — normalleştirme yedinci bölümde. Vaat reddedilirse haritadan silmek ( aşağıdaki .catch kalıbı ) gerekir; aksi halde sonsuza kadar reddedilmiş bir Promise kalır ve yeniden denemeler boşa çıkar. Başarılı sonuçta girişi tutmak ise tekrar await maliyetini önler — bellek ile takas ( bellek bütçesi ).

Uzun oturumlarda harita büyür; seviye değişiminde clear() veya kullanılmayan anahtarları delete etmek, atlasları bırakmayı mümkün kılar — ayrıntılı strateji yine dördüncü bölümde, burada yalnız Promise katmanının ömür yönetimine değinilir.

loadFn enjeksiyonu ( dependency injection ), önbellek modülünü ağ politikasından ayırır; loadImage veya dekodlu yükleme ile birleştirmek tek satırda yapılır. Böylece güvenlik beyaz listesi yükleme katmanında kalır; bu kutu rastgele URL üretmez ( resim yükleme · anti-kalıplar ile hizalı ).

/**
 * loadFn: (url) => Promise<HTMLImageElement> — aynı url için paylaşılan Promise döner.
 * Hata: giriş silinir; başarılı sonuç aynı Promise ile yeniden kullanılır.
 */
function createImagePromiseCache() {
  const map = new Map();
  return {
    load(url, loadFn) {
      let p = map.get(url);
      if (!p) {
        p = loadFn(url).catch((err) => {
            map.delete(url);
            throw err;
          });
        map.set(url, p);
      }
      return p;
    },
    has(url) {
      return map.has(url);
    },
    delete(url) {
      map.delete(url);
    },
    clear() {
      map.clear();
    },
  };
}

Sürümleme ve önbellek kırma: güvenli URL sözleşmesi

Yayınlanan varlık değiştiğinde tarayıcı eski dosyayı sunmaya devam edebilir; en basit istemci çözümü sorgu parametresi ( ?v=20260515 ) veya dosya adına karma eklemektir. Parametre değerini sizin kontrolünüzdeki bir derleme kimliğinden üretin; kullanıcı girdisiyle birleştirmeyin.

Aynı mantıksal varlık, farklı sürümde farklı tam URL olduğunda uygulama önbelleğinde iki giriş bulunur — bu beklenen davranıştır; eski girişi temizlemek bellek kazanır. Serbest bırakma ( garbage collection ) yalnız referanslar düştüğünde gerçekleşir; global listede tutulan Image’leri elle «unut» etmek gerekir.

Ön yükleme listelerinde ( toplu yükleme ) sürümlenmiş URL’e geçmek, tüm haritayı tutarlı kılar.

/** version: derleme / yayın kimliği; null/undefined ise url aynen döner. */
function withCacheVersionQuery(url, version) {
  if (version == null || version === "") return url;
  const sep = url.includes("?") ? "&" : "?";
  return `${url}${sep}v=${encodeURIComponent(String(version))}`;
}

Bellek bütçesi: ne zaman temizlemek gerekir

Büyük atlaslar mobil cihazlarda kolayca yüzlerce megabayt grafik belleği tüketir; tüm levhaları oyun başında yüklemek basit ama riskli bir stratejidir. Seviye bazlı yükleme: yeni bölüme girerken haritayı doldur, çıkarken referansları bırak — Map.clear() ve ilgili değişkenleri sıfırlamak yeterli olabilir, nesneler başka yerde tutulmuyorsa.

«Zayıf» ( WeakRef ) referanslar ileri bir konudur; çoğu Canvas projesinde açık yaşam döngüsü ( yükle → kullan → bırak ) daha anlaşılırdır. Bellek profili çıkarmak için tarayıcı geliştirici araçları yeterlidir — bu sayfa profilleme rehberi değildir.

Sekme arka plandayken görüntüleri tutmak pil ve bellek açısından maliyetlidir; ürün politikası sekmeyi dondurmak ise duraklatma ile bağlanır, önbelleği boşaltma kararı ayrıca verilir.

Ön yükleme ipuçları ve kritik yol

İlk karede takılmayı azaltmak için kritik görseller ( arayüz, oyuncu levhası ) yüklenene kadar ilerlemeyi kilitlemek veya düşük çözünürlüklü yer tutucu göstermek yaygındır — akış decode ve giriş ekranı tasarımının bir parçasıdır. İsteğe bağlı <link rel="preload"> ( HTML ) bazı tarayıcılarda ilk isteği öne çeker; tutarlılık için yine de kodda aynı sürümlenmiş URL’i kullanın.

Service Worker ile önbellek stratejisi kurmak bu serinin dışındadır; temel Canvas öğreniminde önce tekilleştirilmiş Image yükleme yeterlidir. İşçi iş parçacığına taşımak decode’u karmaşıklaştırır — ayrı araştırma gerektirir.

Çoklu format ( WebP yedekli PNG ) kaynak seçimi önbellekten bağımsız bir katmandır; seçim yapıldıktan sonra önbellek anahtarı nihai URL olmalıdır.

Önbellek ve CORS: tuval güvenliği köprüsü

Aynı görüntü nesnesini önbellekte tutarken crossOrigin ataması o anki tüketimle uyumlu olmalıdır; kirlenmiş tuval, daha sonra aynı dosyayı «düzgün yükledim» sansanız bile okuma API’lerini kilitleyebilir. Politikayı proje başında tekilleştirin — resim yükleme · CORS bölümüyle aynı hat üzerinde durun.

Farklı kökten yakalanmış iki kopya ( biri kirli, biri temiz ) aslında aynı dosya olsa bile farklı güvenlik durumunda olabilir; tek yükleme yolundan geçirmek bu sürprizi azaltır.

Veri URL’leri ( data: ) ve yerel blob URL’leri önbellek anahtarı olarak geçerli ama yaşam döngüsü farklıdır; blob URL’leri kullanımdan sonra revokeObjectURL ile serbest bırakılmalıdır — sprite levhası akışında daha az yaygındır.

Yinelenen haritalar ve tutarsız anahtar

Aynı dosya için biri göreli ( /assets/a.png ), biri mutlak ( https://site/a.png ) iki anahtar iki ayrı önbellek girişi yaratır. Temel kural: uygulama içinde tek normalleştirilmiş URL biçimi ( genelde mutlak veya taban + göreli çözümleyici ).

Ön yükleme dizisi ve çalışma anı istekleri farklı dize kullanırsa tekilleştirme bozulur; küçük bir resolveAssetUrl(path) fonksiyonu tüm yükleme noktalarına yayılır.

Sürüm parametresi bazen yalnız ön yüklemede eklenip oyun sırasında unutulursa iki farklı gerçek kaynak kullanılmış olur — ya hep sürümlü ya hep ham yol seçin.

Anti-kalıplar: sözlüksüz kopya ve aşırı kırma

Aşağıdaki örnekler ya bellek şişmesi ya da güncelleme sonrası «neden eski sprite kaldı?» sorununu üretir; kök çözüm çoğu zaman tek uçuş + sürüm + tek tip URL üçlisidir. Bu bölüm, aynı temanın yan etkilerini ayırarak teşhis etmeyi kolaylaştırır — çizim geometrisi levha sayfasında değişmez.

Her istekte yeni Image: Ağ önbelleği baytı tekrar indirmese bile her new Image() yoluyla yeniden dekod ve bellek ayırımı tetiklenebilir; özellikle aynı levha çok varlık tarafından paylaşılıyorsa tek referans üzerinden drawImage ( dilim çizimi ) tercih edilmelidir. Uygulama önbelleği resim yükleme · tekilleştirme ile aynı amaca hizmet eder; birini seçip iki kez uygulamayın.

Her yayında rastgele sorgu ( cache bust ): Date.now() veya rastgele token ile URL her seferinde benzersiz olursa tarayıcı ve CDN önbelleği devre dışı kalır; mobil veri ve soğuk açılış zarar görür. Yalnız içerik değişince withCacheVersionQuery veya eşdeğer bir sürüm kimliği artırılmalıdır.

Hata sonrası giriş silinmeden yeniden deneme: Reddedilmiş Promise haritada kaldıysa sonraki load çağrıları aynı ölü vaide takılı kalır. createImagePromiseCache içindeki silme kalıbı tam bu içindir; özelleştirirken aynı sözleşmeyi koruyun.

Haritayı sıfırlayıp sahne referanslarını eski tutmak: Önbellek boşaldı sanılırken dünya nesneleri hâlâ eski Image’e işaret eder; yeni sürüm yüklense bile çizim eski pikselleri gösterir. Temizlik anında hem Map hem oyun içi görsel tutamaçları ( levha referansı, varlık alanları ) birlikte güncellenmeli; aksi halde «dosya doğru, ekran yanlış» hayaleti oluşur — toplu ön yükleme listesiyle referansların aynı sürümlü URL’den geldiğini doğrulamak hızlı kontrol sağlar.

Bu sayfanın sınırı

CDN yapılandırması, çığ ( stale-while-revalidate ) politikaları ve kapsamlı Service Worker önbellek şemaları burada derinleştirilmez. Odak: Canvas tabanlı oyunlarda istemci tarafı görüntü yeniden kullanımı ve güvenli URL sözleşmesidir.

  • Aynı varlık için tek Promise / tek Image kuralı var mı?
  • Sürüm veya karma tek yerden üretiliyor mu?
  • URL normalleştirme tüm yükleme yollarında ortak mı?
  • Büyük oturumlarda bellek için bölüm sonu temizliği planlandı mı?
  • CORS politikası önbelleklenen nesnelerde tutarlı mı?