Ракетка и управление клавиатурой

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

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

Определение ракетки, чтобы ударить по мячу

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

js
var paddleHeight = 10;
var paddleWidth = 75;
var paddleX = (canvas.width - paddleWidth) / 2;

Здесь мы определяем высоту и ширину ракетки, и его начальную точку на оси X, для дальнейшего использования в расчётах. Давайте создадим функцию, которая будет рисовать ракетку на экране. Добавьте следующий блок после функции drawBall():

js
function drawPaddle() {
  ctx.beginPath();
  ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
  ctx.fillStyle = "#0095DD";
  ctx.fill();
  ctx.closePath();
}

Позволяем пользователю управлять ракеткой

Мы можем отобразить ракетку там, где мы хотим, но она должна реагировать на действия пользователя — настало время реализовать управление с помощью кнопок. Нам понадобится:

  • Две переменные для хранения информации о том, левая или правая кнопка управления нажата.
  • Два обработчика для событий keydown и keyup — мы хотим запустить некоторый код для обработки движения ракетки при нажатии кнопок.
  • Две функции обработки события keydown и keyup код, который будет выполняться при нажатии кнопок.
  • Возможность перемещения ракетки влево и вправо

Нажатые кнопки могут быть определены и инициализированы булевыми переменными. Добавьте эти строки рядом с остальными вашими переменными:

js
var rightPressed = false;
var leftPressed = false;

Значением по умолчанию для обоих является false, так как изначально кнопки не нажаты. Для обработки нажатий клавиш, мы создадим два обработчика событий. Добавьте следующие строки чуть выше функции setInterval() в нижней части JavaScript:

js
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);

Когда keydown событие вызывается любой клавишей клавиатуры (нажатием клавиши), функция keyDownHandler() будет выполняться. Та же картина верна для второго обработчика: keyup событие запустит функцию keyUpHandler () (когда будет отпущена). Добавьте следующий блок в ваш код ниже addEventListener():

js
function keyDownHandler(e) {
  if (e.keyCode == 39) {
    rightPressed = true;
  } else if (e.keyCode == 37) {
    leftPressed = true;
  }
}

function keyUpHandler(e) {
  if (e.keyCode == 39) {
    rightPressed = false;
  } else if (e.keyCode == 37) {
    leftPressed = false;
  }
}

Когда мы нажимаем клавишу, эта информация хранится в переменной. Соответствующая переменная в каждом конкретном случае устанавливается в true. Когда клавиша отпущена, переменная устанавливается обратно в false.

Обе функции принимают параметр, представленный переменной e. Из неё вы можете получить полезную информацию: key содержит информацию о нажатой клавише. Например, код 37 — это клавиша стрелка влево и 39 — стрелка вправо. Если стрелка влево нажата, то переменная leftPressed имеет значение true, когда кнопка отпущена, то переменная leftPressed имеет значение false. Та же схема со стрелкой вправо и переменной rightPressed.

Логика перемещения ракетки

Теперь у нас есть переменные для хранения информации о нажатых клавишах, обработчики событий и соответствующие функции. Теперь мы допишем код, чтобы перемещать ракетку на экране. Внутри функции draw(), мы будем проверять, нажата левая или правая клавиша, когда каждый кадр отображается. Наш код будет выглядеть следующим образом:

js
if (rightPressed) {
  paddleX += 7;
} else if (leftPressed) {
  paddleX -= 7;
}

Если нажата стрелка влево, то ракетка будет двигаться на 7 пикселей влево, а если нажата стрелка вправо то на 7 пикселей вправо. Все хорошо, но, если держать клавишу слишком долго, ракетка уходит за границы холста. Улучшим ситуацию, будем перемещать ракетку только в пределах холста, изменив код следующим образом:

js
if (rightPressed && paddleX < canvas.width - paddleWidth) {
  paddleX += 7;
} else if (leftPressed && paddleX > 0) {
  paddleX -= 7;
}

Позиция paddleX будет двигаться от 0 на левой стороне холста и canvas.width-paddleWidth на правой стороне. Это будет работать именно так, как нам нужно.

Добавьте вышеприведённый блок кода в функцию draw() в самый конец, чуть выше закрывающей фигурной скобки.

Единственное, что осталось сделать сейчас, это вызвать drawPaddle() функцию внутри функции draw(), чтобы нарисовать ракетку на экране. Добавьте следующую строку внутрь функции draw(), чуть ниже строки, которая вызывает drawBall():

js
drawPaddle();

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

Вот работающий код для вас, чтобы сравнить со своим:

Примечание: Сделайте скорость движения ракетки быстрее или медленнее, или измените её размер.

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

Теперь у нас есть что-то похожее на игру. Беда только в том, что пока вы можете лишь бесконечно бить мяч ракеткой. Это все изменится в пятой главе, Game over (en-US), когда мы начнём добавлять конечное состояние для нашей игры.