Отскок от стен

Это 3-й этап из 10 Gamedev Canvas tutorial (en-US). Вы можете найти исходный код как он должен выглядеть после завершения этого урока в Gamedev-Canvas-workshop/lesson3.html.

Приятно наблюдать за нашим мяч, но он быстро исчезает с экрана, удовольствие длится недолго! Чтобы продлить, мы реализуем некоторое очень простое обнаружение столкновений (о которых будет рассказано далее (en-US) более подробно), чтобы сделать отскок мяча от четырёх краёв холста.

Простое обнаружение столкновений

Для обнаружения столкновения мы будем проверять - касается ли мяч стены, и если это так, изменим направление его движения в нужную сторону.

Чтобы сделать расчёты проще, давайте определим переменную ballRadius, что задаст радиус нарисованного круга и будет использоваться для вычислений. Добавьте это в ваш код, где-то ниже существующих переменных:

js
var ballRadius = 10;

Теперь обновите строку, которая рисует шарик, внутри функции drawBall():

js
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);

Отскакивание от верхней и нижней стены

Есть четыре стены, от которых мяч будет отскакивать — давайте сначала сосредоточимся на верхней. При каждом кадре нужно проверять, коснулся ли мяч верхней границы — если да, то будет обратное движение мяча, поэтому он начнёт двигаться в противоположном направлении и остановится в пределах видимой границы. Вспомнив, что система координат начинается с левого верхнего угла, мы можем придумать что-то вроде этого:

js
if (y + dy < 0) {
  dy = -dy;
}

Если значение y положения шара ниже нуля, изменить направление движения по оси y установив его с тем же значением но с другим знаком. Если мяч движется вверх со скоростью 2 пикселя на кадр, теперь он будет двигаться "вверх" со скоростью -2 пикселя, что на самом деле означает движение вниз со скоростью 2 пикселя.

Приведённый выше код описывает отражение только от верхней границы, так что теперь давайте думать о нижнем крае:

js
if (y + dy > canvas.height) {
  dy = -dy;
}

Если положение мяча по оси y больше, чем высота полотна (помните, что мы рассчитываем значения y от верхнего левого, чтобы верхний край начинался с 0, а нижний край — 480 пикселей, высота нашего <canvas>), затем после отскока от нижней кромки обратное движение по оси y.

Мы можем объединить эти две конструкции в одну, чтобы уменьшить код:

js
if (y + dy > canvas.height || y + dy < 0) {
  dy = -dy;
}

Если одно из двух утверждений верно, тогда направление мяча меняется.

Отскоки влево и вправо

Мы сделали отражение от верхней и нижней границ, нельзя забывать и про боковины. Задача очень похожа на самом деле, все, что вам нужно сделать, это повторить конструкцию заменив Y на X:

js
if (x + dx > canvas.width || x + dx < 0) {
  dx = -dx;
}

if (y + dy > canvas.height || y + dy < 0) {
  dy = -dy;
}

На этом этапе вы должны вставить этот блок кода в функцию Draw (), непосредственно перед закрывающей фигурной скобкой.

Мяч продолжает исчезать в стене!

Проверьте сейчас свой код, и вы будете впечатлёны — теперь мяч, отскакивает от всех четырёх краёв нашего <canvas>! Однако есть некоторая проблема - когда мяч попадает в любую стену, он немного заходит за границы <canvas> перед отскоком:

Это происходит потому, что мы проверяем касание стены и центра мяча, а не его края. Мяч должен отскакивать сразу после касания, а не когда он уже на половину в стене, так что давайте корректировать наш код включив в него небольшое выражение. Обновите последний код добавив к нему:

js
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
  dx = -dx;
}
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
  dy = -dy;
}

Когда расстояние между центром шара и краем стены равно радиусу шарика, шарик изменит направление движения. Вычитая радиус при отскоке от одной стены и добавляя при отскоке от другой, мы получили простое обнаружение столкновений. Шарик отскакивает от стен как надо.

Сравните ваш код

Давайте ещё раз проверим готовый код для этой части, и код, что у вас есть, и играйте:

Примечание: попробуйте изменить цвет шарика на случайный цвет каждый раз, когда он попадает в стену.

Следующий шаг

Теперь мы добрались до стадии, где наш мяч одновременно двигается и остаётся на игровом поле. В четвёртой главе мы рассмотрим реализацию управления — см. Paddle and keyboard controls (en-US).