Гузариш ба мундариҷа
Мавзӯи 2 аз 5
Назария

Давраи бозӣ

Расм чӣ тавр зинда мешавад

Мултфилм — ин бисёр расмҳо пай дар пай аст. Бозӣ ҳамин корро мекунад: тақрибан 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.

Қадами тӯб

Осон+10 XP

Тӯб — объекти { x, y, vx, vy }: координатаҳои марказ ва суръат дар пиксел дар як сония. Функсияи moveBall(ball, dt)-ро нависед, ки тӯбро барои вақти dt сония ҳаракат медиҳад: x ба vx * dt, y — ба vy * dt иваз мешавад. Функсия худи объекти ball-ро иваз мекунад ва ҳеҷ чиз барнамегардонад.

Дар поён дар коди тайёр аллакай давраи бозӣ ҳаст, ки тӯбро мекашад, — «Иҷро кардан»-ро пахш кунед ва бинед, ки он чӣ тавр парвоз мекунад.

ball = { x: 10, y: 20, vx: 100, vy: -50 }
moveBall(ball, 0.5)  →  ball.x = 60, ball.y = -5

Барои ҳал кардани масъалаҳо коннекторро пайваст кун

Коди масъалаҳо дар компютери худат иҷро мешавад — ин аз браузер тезтар ва боэътимодтар аст. Барои ин барномаи ройгони коннектори CodeWithMe лозим аст. Онро як бор пайваст кардан кифоя аст.

Коннекторро дар ин компютер ҷустуҷӯ мекунем…

  1. 1
    Коннекторро барои системаи худ (Windows, macOS ё Linux) зеркашӣ кун.Зеркашии коннекторДар саҳифаи зеркашӣ файлеро интихоб кун, ки дар номаш системаи ту ҳаст, масалан windows-amd64.
  2. 2Онро иҷро кун ва ҷузвдонеро интихоб кун, ки ҳалҳоят дар он ҷо меистанд. Python ва Node.js-ро ӯ худаш ҳангоми зарурат ба он ҷо мегузорад.
  3. 3
    Дар поён рамзи 6-рақамаро ворид кун — он дар равзанаи коннектор навишта шудааст («Рамз барои сайти CodeWithMe»). Агар браузер дар бораи дастрасӣ ба шабакаи маҳаллӣ пурсад — иҷозат деҳ.

Коннектор кушода аст (рамзи манбаъ дар GitHub), танҳо дар компютери ту кор мекунад ва кодро танҳо пас аз ворид кардани рамзи пайвастшавӣ иҷро мекунад.