Давраи бозӣ
Расм чӣ тавр зинда мешавад
Мултфилм — ин бисёр расмҳо пай дар пай аст. Бозӣ ҳамин корро мекунад: тақрибан 60 маротиба дар як сония ҳолстро пок мекунад ва ҳама чизро дар ҳолати нав мекашад. Порчаи такроршавандаи коде, ки инро мекунад, давраи бозӣ (game loop) меноманд.
requestAnimationFrame
Аз браузер хоҳиш кардан, ки функсияро пеш аз аз нав кашидани навбатии экран даъват кунад — requestAnimationFrame:
function frame() {
// 1. мавқеи объектҳоро иваз кардан
// 2. кадрро кашидан
requestAnimationFrame(frame); // ва кадри навбатиро хоҳиш кардан
}
requestAnimationFrame(frame);
Чаро на setInterval(frame, 16)? requestAnimationFrame ба басомади экран мутобиқ мешавад
(60, 120, 144 Гс), вақте ки ҷадвал пинҳон аст беҳуда намекашад, ва кадрҳо ҳамвор, бе
ҷаҳишҳо мешаванд. Ин стандарти аниматсия дар браузер аст.
Давраи бозиро бо while (true) { ... } сохтан мумкин нест: чунин давра ҳеҷ гоҳ идоракуниро ба
браузер намедиҳад, саҳифа овезон мешавад ва ҳеҷ чиз намекашад.
Вақти кадр: dt
Кадрҳо нобаробар меоянд: дар компютери тез онҳо 144 дар як сония, дар суст — 30. Агар
тӯбро «2 пиксел дар як кадр» ҳаракат диҳем, дар компютерҳои гуногун он бо суръати гуногун парвоз мекунад. Бинобар ин суръатро
дар пиксел дар як сония медиҳанд, дар ҳар кадр бошад ба суръат × dt ҳаракат медиҳанд, ки dt — аз кадри пешина чанд
сония гузашт.
requestAnimationFrame ба функсия вақти ҷориро дар миллисонияҳо медиҳад:
let last = performance.now();
function frame(now) {
const dt = (now - last) / 1000; // миллисонияҳо → сонияҳо
last = now;
ball.x += ball.vx * dt; // vx — пиксел дар як сония
draw();
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
Агар тӯб бо суръати 120 px/с парвоз кунад, дар кадри 1/60 сония вай 2 пиксел ҳаракат мекунад, дар кадри 1/30 — 4. Дар як сония дар ҳарду ҳолат — маҳз 120.
Вақте ки ҷадвалро мепечонанд, кадрҳо қатъ мешаванд, ҳангоми баргаштан бошад dt хеле калон мешавад (дақиқаҳо!)
— объектҳо аз девор «телепорт» мешаванд. Бинобар ин dt-ро одатан маҳдуд мекунанд: Math.min(dt, 0.1).
Ҳолат, update ва draw
Ҳама чизе, ки бозиро дар лаҳзаи додашуда тавсиф мекунад — мавқеъҳо, суръатҳо, хол, ҷонҳо, — дар объектҳои ҳолат нигоҳ медоранд. Кадрро ба ду қисм ҷудо мекунанд:
const state = {
ball: { x: 50, y: 50, vx: 150, vy: 90, r: 10 },
score: 0,
};
function update(dt) { // танҳо ададҳоро иваз мекунад
state.ball.x += state.ball.vx * dt;
state.ball.y += state.ball.vy * dt;
}
function draw() { // танҳо он чиро, ки дар ҳолат аст, мекашад
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(state.ball.x, state.ball.y, state.ball.r, 0, Math.PI * 2);
ctx.fill();
ctx.fillText(`Хол: ${state.score}`, 10, 20);
}
let last = performance.now();
function frame(now) {
const dt = Math.min(0.1, (now - last) / 1000);
last = now;
update(dt);
draw();
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
Чаро ҷудо кардан? update-ро бе экран санҷидан мумкин аст — танҳо онро бо ададҳо даъват кунед ва
натиҷаро бинед (масъалаҳои курс ҳамин тавр сохта шудаанд). draw бошад дар бораи қоидаҳои бозӣ фикр намекунад, вай танҳо
ҳолатро нишон медиҳад. Ин ҳамон идеяи «маълумот → render» дар DOM аст.
Шитоб ва ҷозиба
Суръат ҳам метавонад бо мурури вақт иваз шавад. Ҷозиба — шитоби доимӣ ба поён: ҳар сония суръати афтидан ба ҳамон як адад меафзояд.
const GRAVITY = 300; // px/с дар як сония
ball.vy += GRAVITY * dt; // аввал суръатро иваз мекунем
ball.y += ball.vy * dt; // баъд бо суръати нав ҳаракат мекунем
Ҳамин тавр ҷаҳишҳо, афтиданҳо ва параболаҳои зебои шарораҳои мушакбозӣ ҳосил мешаванд.
Объектҳо пайдо ва нопадид мешаванд
Тирҳо, шарораҳо, душманон кӯтоҳ умр мебинанд. Онҳоро дар массив нигоҳ медоранд: навҳоро бо push илова мекунанд, зиёдатиҳоро
хориҷ мекунанд ва танҳо зиндаҳоро мемонанд:
bullets = bullets.filter((b) => b.y > 0); // онҳое, ки аз экран баромаданд — хориҷ кардан
Хулоса
- Давраи бозӣ:
requestAnimationFrame(frame)дар охири ҳар кадр; ҳеҷwhile (true). - Суръат — дар пиксел дар як сония, ҷойивазкунӣ дар кадр —
суръат × dt,dtдар сонияҳо ва на зиёда аз 0.1. - Ҳолати бозӣ — дар объектҳо;
update(dt)ададҳоро иваз мекунад,draw()мекашад. - Ҷозиба:
vy += g × dt, баъдy += vy × dt. Объектҳои муваққатӣ — дар массив +filter.