HTML5 Canvas · Render döngüsü
Delta time: kareler arası süre ve simülasyon adımı
Delta time (dt), animasyonlu bir canvas sahnesinde iki
ardışık kare arasında geçen gerçek süredir — çoğu uygulama bunu saniye
cinsinden tutar ve konum güncellemelerini x += v * dt biçiminde yazar. Böylece
ekran 48 Hz ile 120 Hz arasında salındığında çizilen nesnelerin ekran üstündeki
hızı
yaklaşık sabit kalır; sabit 1/60 çarpanına mahkûm kalmazsınız. Bu sayfa,
ölçümü nereden alacağınızı, birim sözleşmesini, ani gecikme ve düşük fps durumunda güvenli
sınırları ve isteğe bağlı sabit adım modelini canvas üreticisi gözüyle sabitler.
Kareyi ne zaman planlayacağınız requestAnimationFrame konusunda; pikseli ne zaman sıfırlayıp yeniden boyayacağınız Clear & redraw sayfasında. Burada yalnızca her karede çizim öncesi «ne kadar zaman geçti?» sorusunun tek tip cevabı ön plandadır.
Özet: delta kullanım kalıpları
| Kalıp | Canvas’ta tipik kullanım | Risk |
|---|---|---|
Ölçülen dt (saniye) |
Hız → konum entegrasyonu; parçacık, kamera takip, veri animasyonu | Çok büyük dt tünelleme / patlama; üst sınır gerekir |
Sabit 1/60 varsayımı |
Hızlı prototip; grafik ölçeği sabit fps’e kilitlenir | Yenileme farkı hissedilir; profesyonel üründe dt tercih edilir |
Clamp edilmiş dt |
Oyun hissi + sekmeye dönüşte güvenli adım | Üst sınır düşükse yavaş hareket «yapışık» görünebilir |
| Sabit adım + artık | Tekrarlanabilir küçük fizik adımları; çoklu step aynı karede |
Fazladan CPU; ara değerle çizim (interp) ayrı düşünülür |
Delta time: canvas simülasyonunda adım süresi
Basit zihinsel model: her requestAnimationFrame geri çağrısı bir
«şimdi»
zaman damgası taşır; bir önceki şimdi ile farkı alırsınız — işte ham delta. Bu farkı
saniyeye
bölerseniz (ms / 1000), bir kare içinde dünya durumunu ilerleten
fonksiyonlarınız
zamandan bağımsız hızlar (
units per second) ile konuşabilir. Canvas üzerinde oklar, ölçek
animasyonları, yörünge veya grafik çizgisi kaydırması aynı kalıba girer: görsel nicelikleri
dt ile ölçeklersiniz, kare sayısı ile değil.
dt = 0 ilk karede veya zaman damgası sıfırlandığında doğaldır; bu durumda «bir
önceki
konumu koru» veya fizik adımını atla dersiniz — aksi halde NaN yayan bölümler
üretebilirsiniz. Yeniden başlatma (pause → play) sonrası aynı
sıfırlama
disiplini animasyonun geri sıçramasını azaltır.
Piksel düzeyinde yoğunlaşan çizim maliyeti, dt ile doğrudan telafi
edilmez; yavaş cihazda kare süresi uzar, dt büyür, siz de aynı mantıkla daha az
sıklıkta ama daha büyük adımla ilerlersiniz — bu, CPU maliyetini düşürmez, sadece simülasyon
hızının görsel hızla uyumunu korur. Çizim optimizasyonu başka başlıkların boyasıdır.
Monotonik ölçüm ve ilk kare sözleşmesi
Üretimde tercih, tarayıcının rAF ile verdiği yüksek çözünürlüklü monotonik
zaman damgasıdır (
DOMHighResTimeStamp); sistem saatine göre geri alınabilir veya sıçrayabilen
Date.now tabanlı farklardan kaçınmış olursunuz. Önceki kare zamanını modül veya
bileşen ömrü boyunca saklayın; her turda rawDt = (now - prev) / 1000,
ardından prev = now ataması tipik sözleşmedir.
Sekme uzun süre gizlendikten sonra dönüldüğünde ham delta saniyeler mertebesine çıkabilir —
bu normaldir ve bir sonraki başlıkta ele alınır. Görünürlük değişiminde
prev = 0 veya «ilk kare bayrağı» ile bir sonraki turu sıfır deltada başlatmak,
ani sıçrama hissini kullanıcıdan gizler (
rAF ·
görünürlük
ile örtüşür; burada odak ölçüm matematiğidir).
Aynı kare içinde birden fazla alt sistem ayrı «yerel saat» tutuyorsa, hepsine aynı
global dt iletmek tutarlılık sağlar; biri kendi içinde
performance.now() farkını ayrı ölçüp farklı sonuç üretirse gölgeler ve parçacık
katmanları birbirinden kayar.
Birim disiplini: saniye veya milisaniye
Ekip içinde tek karar seçin: ya herkes dt’yi saniye (0.016…)
sayar ya da milisaniye (16.6…) — ikisini aynı dosyada karıştırmak,
hız sabitlerini on kat yanlış yazdıran sessiz hatalar üretir. Fizik ve oyun motorlarında
saniye
yaygındır; bazı grafik tween kütüphaneleri ms kullanır: sınırda
dönüştürün,
canvas çizim katmanına girmeden önce tek tipe indirger.
Açısal hızlar (
rad/s) ve doğrusal hızlar (
px/s veya dünya birimi/saniye) aynı dt ile çarpılır;
trigonometrik
animasyonlarda radyan birikimi
angle += omega * dt şeklindedir — derece/saniye
kullanıyorsanız çevrimi tek yerde yapın.
Zamanı metin olarak ekrana basan hata ayıklama HUD’ları, biçimlendirme için
dt’yi ms’e çevirebilir; simülasyon çekirdeği yine saniyede kalmalıdır. Böylece
tek kaynak gerçeği korunur.
Üst sınır, düşük fps ve kare sıçraması
Ham dt bir debug sekmesi açıldığında veya ana iş parçacığı kilitlendiğinde
yükselir;
tünelleme (
tunneling), büyük tek adımda çarpışma atlama veya patlama üretebilir.
Bu
yüzden üretim canvaslarında üst sınır (
clamp max) yaygındır — örneğin tek karede en fazla ~33 ms (
~30 fps eşleniği) simüle et; daha uzun gerçek boşlukta dünya «yavaşlar» fakat patlamaz.
Alt sınır da kullanılabilir: aşırı yüksek yenilemede mikroskobik dt bazen
sayısal
gürültü yaratabilir; çok küçük değerleri bir tabanla (
epsilon) kesmek entegratörleri stabilize eder. İki sınırı sabit
kodlamak
yerine yapılandırma veya profil anahtarı yapmak A/B karşılaştırmasını kolaylaştırır.
Düşük fps’de görsel akıcılık ile simülasyon doğruluğu trade-off’tur: üst sınır agresifse oyuncu donmuş ekranda «yavaş dünya» görür; gevşekse tek karede büyük sıçrama riski artar — oyun türüne göre ayarlanır; bu sayfa formülü sabitlemez, karar çerçevesini verir.
function clampDtSeconds(raw, minS = 1 / 240, maxS = 1 / 30) {
if (!Number.isFinite(raw) || raw <= 0) return minS;
return Math.min(maxS, Math.max(minS, raw));
}
function integrateSprite(sprite, dt) {
sprite.x += sprite.vx * dt;
sprite.y += sprite.vy * dt;
}
Sabit zaman adımı ve biriken artık
Bazı canvas projelerinde her karede yalnızca bir kez step(dt_measured) yeterli
değildir: çarpışma çözücü veya özel entegrasyon deterministik, sabit küçük adımlar ister.
Model:
gerçek kareden gelen dt’yi bir birikim değişkenine ekleyin;
birikim, sabit adım (
h) büyüklüğünü aştığı sürece döngüde fizik çağırın ve birikimden
h düşün. Bir karede iki–üç fizik adımı görülmesi normaldir; ağır sahnede üst
tavan koymak «spiral of death» (
infinite catch-up) riskini azaltır.
Çizim tarafı genelde ölçülen veya kalan artığa göre interpole edilmiş ara poz ile yapılır; aksi halde dünya diskret adımlarla zıplar gibi görünür. Bu sayfa interpolasyon matematiğini açmaz — yalnızca fizik çağrı sayısı ile tek rAF çizimi ayrımını hatırlatır ( Update vs render konusuyla örtüşür).
Küçük eğitim demolarında sabit adım yerine doğrudan dt ile tek adım çoğu zaman
yeterlidir; proje büyüdükçe tekrarlanabilirlik ve test yazımı sabit adımı zorunlu kılar.
let accumulator = 0;
const FIXED_STEP = 1 / 120;
const MAX_STEPS = 5;
function tickFrame(rawDtSeconds, stepPhysics, drawCanvas) {
accumulator += rawDtSeconds;
let steps = 0;
while (accumulator >= FIXED_STEP && steps < MAX_STEPS) {
stepPhysics(FIXED_STEP);
accumulator -= FIXED_STEP;
steps += 1;
}
drawCanvas(accumulator / FIXED_STEP);
}
Zaman ölçekleme ve sunum hızı
Yavaş çekim veya hızlandırılmış demo için efektif delta
dt_eff = dt * timeScale kullanılır; timeScale = 0 duraklatma,
0.25 dörtte bir hız gibi. Canvas üzerinde dünya mantığı bu çarpanı paylaşır;
kullanıcı arayüzü animasyonlarının gerçek zamanlı kalıp kalmayacağı tasarım tercihidir — HUD
sayacı bazen ölçeklenmez.
Ease / tween kütüphaneleri kendi dahili süre değişkenlerini taşıyorsa, onları global
timeScale ile beslemek veya dışarıda durdurmak sözleşmeye bağlıdır; iki farklı
saat kaynağı çakışırsa nesneler biri geride biri önde görünür.
Kayıt / tekrar (
replay) senaryolarında deterministik sabit adım, wall-clock
dt’den ayrı tutulabilir — bu ileri konudur; canvas öğretici içeriği için
bilinçli
sınır çizgisi yeterlidir.
Anti-kalıplar: entegrasyon ve motor karışması
Çift entegrasyon: Hem konumu dt ile hem de hızı ayrıca
yanlışlıkla ikinci kez ölçeklemek — örneğin fizik motoruna dt verip dışarıda
yine
* dt çarpmak — nesneleri uçurur; her alt sistemde tek adımlık sözleşme yazın.
Kare sayacı = zaman: frameIdx / 60 saniye sanmak, gerçek
dt dalgalanmasını gizler; video export veya senkron müzikte sapma birikir.
setInterval dt’si ile rAF çizimi: İki farklı zaman kaynağını birleştirirken hangi saatin «hakem» olduğunu belirtmezseniz ara kareler çift veya eksik güncellenir ( rAF · API ).
Clamp’sız uzun duraklama: İlk karede dev sıçrama; özellikle mobilde arka plana atlayıp dönüşte kullanıcıyı cezalandırır.
Bu sayfanın sınırı
Çok gövdeli ( rigid body) fizik, sürekli çarpışma ve ileri entegratörler ( RK4 vb.) burada işlenmez; odak, Canvas 2D sahnesinde yaygın skaler delta kullanımıdır.
Çok oyunculu ve sunucu otoriteli senaryolarda oyun saati ağ katmanı ile ayrı yönetilir; istemci tarafı interpolation / öngörü bu sayfanın kapsamı dışındadır.
- Tüm kod tabanı aynı
dtbiriminde mi (saniye / ms)? - Ham delta mı yoksa clamp’lenmiş delta mı fizik çekirdeğine gidiyor?
- Sekme / duraklatma sonrası
prevsıfırlandı mı? - Sabit adımda birikim tavanı ve maksimum adım sayısı var mı?
- Hud veya tween ile dünya saati çakışıyor mu?