Shu paytgacha sizning o'yinlaringiz tugma bosishdan iborat edi: klik → hisob oshadi. Bu o'yin emas, bu forma. Haqiqiy o'yinda ekran sekundiga 60 marta qaytadan chiziladi, qahramon tezlik va gravitatsiyaga ega, to'qnashuvlar esa matematik hisoblanadi. Bugun siz o'sha dvigatelni ichidan ko'rasiz.
div — sekin. 1000 tasi — slayd-shou.DOM — bu magnit doska: har bir magnitni alohida surasiz, brauzer ularni eslab turadi. Canvas — bu oddiy doska: har kadrda o'chirib, hammasini qaytadan chizasiz. Aynan shuning uchun tez — brauzer hech narsani eslab turmaydi.
// 1. HTML da maydon
<canvas id="cv" width="800" height="400"></canvas>
// 2. JS da "qalam" olish
var cv = document.getElementById('cv');
var ctx = cv.getContext('2d');
// 3. Chizish
ctx.fillStyle = '#FF1100';
ctx.fillRect(100, 50, 40, 40); // x, y, w, h
fillRect(x,y,w,h) — to'ldirilgan to'rtburchak.clearRect(0,0,W,H) — butun ekranni o'chirish.fillStyle — keyingi chiziqlar rangi.fillText(s,x,y) — matn (hisob, FPS).arc(x,y,r,0,7) — doira (o'q, to'p, zarra).Canvas da (0,0) yuqori chap burchakda, va Y pastga o'sadi. Ya'ni y = 300 — bu y = 100 dan pastroq. Shuning uchun sakrash y ni kamaytiradi: vy = -13. Bu eng ko'p uchraydigan chalkashlik.
Ekranni butunlay o'chirish. Agar bu qadamni tashlab ketsangiz, qahramon o'zidan iz qoldiradi — ba'zan bu qasddan effekt, lekin odatda xato.
Hech narsa chizilmaydi! Faqat raqamlar o'zgaradi: pozitsiya, tezlik, hisob, dushman holati. Bu — o'yinning miyasi.
Hech narsa hisoblanmaydi! Faqat joriy holat chiziladi. Bu — o'yinning ko'zi. Ikkovini aralashtirmaslik — professional kodning asosiy qoidasi.
function loop(time){
ctx.clearRect(0, 0, W, H); // 1 CLEAR
update(); // 2 UPDATE — faqat raqamlar
draw(); // 3 DRAW — faqat chizish
requestAnimationFrame(loop); // o'zini qayta chaqiradi
}
requestAnimationFrame(loop); // birinchi kadr
Agar RAF turli kompyuterda turli tezlikda ishlasa — demak o'yin ham turli tezlikda ketadi! Kuchli kompyuterda qahramon uchadi, zaifida sudraladi. Keyingi slayd shu muammoni yechadi.
hero.x += 5; // har KADRDA 5 piksel // 60 FPS -> 300 piksel/sek // 30 FPS -> 150 piksel/sek (2x sekin!) // 144 FPS -> 720 piksel/sek (2.4x tez!) // Bir xil kod, uch xil o'yin.
hero.x += 300 * dt; // har SONIYADA 300 piksel // dt = o'tgan kadrdan beri o'tgan vaqt // 60 FPS -> dt = 0.016 -> 4.8 px/kadr // 30 FPS -> dt = 0.033 -> 10 px/kadr // 144 FPS -> dt = 0.007 -> 2.1 px/kadr // Turli kadr, BIR XIL tezlik.
var oldingi = 0;
function loop(vaqt){ // RAF vaqtni o'zi beradi (ms)
var dt = (vaqt - oldingi) / 1000; // soniyaga o'tkazish
oldingi = vaqt;
if (dt > 0.1) dt = 0.1; // vkladka qaytganda sakrashni cheklash
update(dt);
requestAnimationFrame(loop);
}
// 1. Tezlanish tezlikni o'zgartiradi
hero.vy += GRAVITY * dt;
// 2. Tezlik pozitsiyani o'zgartiradi
hero.y += hero.vy * dt;
// 3. Yer to'xtatadi
if (hero.y > FLOOR) {
hero.y = FLOOR;
hero.vy = 0;
hero.onGround = true;
}
a → v.v → s.vy = -JUMP, ya'ni bir zumlik yuqoriga tezlik. Qolganini gravitatsiya qiladi.JUMP ni emas, GRAVITY ni kamaytirish ham mumkin — oy effekti.Axis-Aligned Bounding Box — "o'qlarga parallel chegaraviy to'rtburchak". Kompyuter qahramonni va dushmanni rasm sifatida ko'rmaydi — u ikkita ko'rinmas to'rtburchakning koordinatalarini taqqoslaydi.
function toqnashdi(a, b){
return a.x < b.x + b.w &&
a.x + a.w > b.x &&
a.y < b.y + b.h &&
a.y + a.h > b.y;
}
// Bittasi ham false bo'lsa — to'qnashuv YO'Q
Hitbox tugmasini bosing — ekranda ko'rinmas to'rtburchaklar chiziladi. Siz darhol tushunasiz: o'yinda "tegmaganday tuyuldi, lekin jon ketdi" holati hitbox rasmdan kattaroq bo'lgani uchun sodir bo'ladi.
Sekundni 60 ga bo'lsangiz — 16.6 ms chiqadi. Update va Draw shu vaqtga ikkovi birga sig'ishi kerak.
Har kadrda yangi obyekt yaratish, fillText ni yuzlab marta chaqirish, kerak bo'lmagan narsalarni chizish (ekrandan tashqarida).
Stendda kadr vaqti grafigi bor. Yashil zona — 16 ms ichida. Qizil chiziqlar — kechikkan kadrlar. Zarralar sonini oshirib, grafik qizarishini ko'ring.
FPS ni 15 ga tushiring. dt: O'CHIQ da qahramon sekinlashadi. dt: YONIQ da — tezlik o'zgarmaydi. Ikkala o'lchovni yozing.
Hitbox ni yoqing. Qahramonni to'pga sekin yaqinlashtiring va to'qnashuv aynan qachon qayd etilishini kuzating.
Gravitatsiya ni 300 gacha tushiring, Sakrash ni o'zgartirmang. Sakrash balandligi qanday o'zgardi? Sababini yozing.
Zarralar slayderini oshiring. Kadr vaqti 16 ms dan oshgan nuqtadagi zarralar sonini toping va yozing.
1) Объясни разницу между setInterval и requestAnimationFrame для игрового цикла. Приведи пример, когда setInterval ломает игру. 2) У меня hero.x += 5 в игровом цикле. Перепиши через delta time так, чтобы скорость была 300 пикселей в секунду. Объясни каждую строку. 3) Напиши функцию AABB-столкновения двух прямоугольников на JavaScript и объясни, почему нужны именно 4 сравнения.
dt kodini stenddagi qiymatlar bilan solishtiring — raqamlar mos kelishi kerak.dt ni millisekundda qoldiradi (1000 ga bo'lishni unutadi) — bu klassik xato. Tekshiring!