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

Бархӯрдҳо

Бе бархӯрд бозӣ нест

Тир ба душман расид, қаҳрамон ба платформа истод, тӯб аз ракетка баргашт, мор себро хӯрд — ҳамаи ин санҷиши бархӯрдҳо аст: оё ду шакл ҳозир якдигарро мебуранд. Ҳолст инро намедонад (дар он танҳо пикселҳо ҳастанд), бинобар ин бархӯрдҳоро аз рӯи ададҳои ҳолати бозӣ ҳисоб мекунанд.

Дар аксари бозиҳои 2D объектҳоро барои бархӯрд то ду шакл сода мекунанд: росткунҷа ва доира. Ҳатто агар дар экран персонажи мураккаб кашида шуда бошад, «хитбокс»-и он — росткунҷаи оддӣ аст.

Росткунҷа бо росткунҷа (AABB)

Росткунҷаҳоеро, ки тарафҳояшон ба канорҳои экран параллеланд, AABB (axis-aligned bounding box) меноманд. Санҷиш — аз баръакс: росткунҷаҳо намебуранд, агар яке пурра аз дигаре чаптар, ростар, болотар ё поёнтар бошад. Дар ҳамаи ҳолатҳои дигар — мебуранд.

function rectsOverlap(a, b) {
  return (
    a.x < b.x + b.w &&    // канори чапи a аз канори рости b чаптар
    a.x + a.w > b.x &&    // канори рости a аз канори чапи b ростар
    a.y < b.y + b.h &&    // болои a аз поёни b болотар
    a.y + a.h > b.y       // поёни a аз болои b поёнтар
  );
}

< ва >-и қатъӣ маънои онро доранд, ки ламс бо канорҳо ҳанӯз бархӯрд нест. Агар дар бозӣ дигар хел лозим бошад, ба <= ва >= иваз мекунанд.

Доира бо доира

Доираҳо вақте мебуранд, ки масофаи байни марказҳо аз суммаи радиусҳо хурд бошад:

function circlesOverlap(a, b) {
  const dist = Math.hypot(a.x - b.x, a.y - b.y);   // √(dx² + dy²)
  return dist < a.r + b.r;
}

Math.hypot(dx, dy) — дарозии гипотенуза, яъне масофа аз рӯи теоремаи Пифагор. Вақте ки объектҳо хеле зиёданд, решаро ҳисоб намекунанд ва квадратҳоро муқоиса мекунанд: dx * dx + dy * dy < (a.r + b.r) ** 2.

Доира бо росткунҷа

Тӯб ва хишт, танга ва платформа. Усули дақиқ — ёфтани нуқтаи росткунҷа, ки ба маркази доира наздиктарин аст, ва санҷиши масофа то он:

function circleRect(c, r) {
  const nearX = Math.max(r.x, Math.min(c.x, r.x + r.w));
  const nearY = Math.max(r.y, Math.min(c.y, r.y + r.h));
  return Math.hypot(c.x - nearX, c.y - nearY) < c.r;
}

Дар аркадаҳои оддӣ аксар вақт боз ҳам соддатар мекунанд: доираро квадрат бо тарафи 2r ҳисоб мекунанд ва rectsOverlap-ро истифода мебаранд. Хато танҳо дар кунҷҳо намоён аст.

Бозгашт аз деворҳо

Тӯб набояд аз майдон берун парад. Ҳар деворро месанҷем: агар тӯб ба он даромада бошад — онро ба ҳудуд бармегардонем ва суръатро тағйири самт медиҳем:

if (ball.x - ball.r < 0) {          // девори чап
  ball.x = ball.r;
  ball.vx = Math.abs(ball.vx);      // акнун бешубҳа ба рост парвоз мекунад
}
if (ball.x + ball.r > canvas.width) {   // девори рост
  ball.x = canvas.width - ball.r;
  ball.vx = -Math.abs(ball.vx);     // акнун бешубҳа ба чап парвоз мекунад
}

Чаро на ball.vx = -ball.vx? Дар як кадр тӯб метавонад ба девор чуқур дарояд. Агар танҳо суръатро баръакс кунем, дар кадри оянда вай метавонад ҳанӯз набарояд — ва суръат боз баръакс мешавад, тӯб «мечаспад» ва меларзад. Баргардондан ба ҳудуд ва Math.abs бозгаштро боэътимод мекунанд.

Пас аз бархӯрд чӣ кор кардан

Бархӯрд — танҳо «ҳа / не» аст. Минбаъд бозӣ ҳал мекунад:

for (const enemy of enemies) {
  if (rectsOverlap(bullet, enemy)) {
    enemy.alive = false;
    bullet.alive = false;
    score += 10;
  }
}
enemies = enemies.filter((e) => e.alive);

Ҳангоми гузаштан аз массив бевосита хориҷ кардан хатарнок аст (индексҳо ҷой иваз мекунанд), бинобар ин аввал alive = false қайд мекунанд, баъд тавассути filter хориҷ мекунанд.

Объектҳои аз ҳад тез

Агар тир дар як кадр 50 пиксел парвоз кунад, девор бошад 10 ғафсӣ дошта бошад, дар як кадр тир ҳанӯз пеши девор аст, дар кадри оянда — аллакай пушти он, ва буриш рух намедиҳад. Инро «туннелшавӣ» меноманд. Воситаҳои оддӣ: суръатро маҳдуд кардан, объектҳоро ғафстар кардан ё объектҳои тезро дар як кадр бо якчанд қадами хурд ҳаракат додан.

Хулоса

  • Хитбоксҳо — росткунҷаҳо ва доираҳо, ададҳои ҳолатро месанҷем, на пикселҳоро.
  • AABB: чор муқоисаи канорҳо; доираҳо: Math.hypot(dx, dy) < r1 + r2.
  • Бозгашт: ба ҳудуд баргардондан ва самтро тавассути Math.abs додан.
  • Пас аз бархӯрд объектҳоро қайд мекунем ва бо filter хориҷ мекунем.

Росткунҷаҳо мебуранд?

Осон+10 XP

Функсияи rectsOverlap(a, b)-ро нависед. Росткунҷаҳо ҳамчун { x, y, w, h } дода шудаанд (кунҷи чапи болоӣ ва андоза). Функсия true бармегардонад, агар росткунҷаҳо масоҳати умумӣ дошта бошанд. Агар онҳо танҳо бо канорҳо ламс кунанд — ин буриш нест.

rectsOverlap({x:0,y:0,w:10,h:10}, {x:5,y:5,w:10,h:10})    → true
rectsOverlap({x:0,y:0,w:10,h:10}, {x:10,y:0,w:5,h:5})     → false (ламс)

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

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

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

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

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