Перейти к содержимому
Тема 3 из 5
Теория

Управление

Два способа слушать клавиатуру

В прошлой теме DOM мы реагировали на keydown сразу: нажал стрелку — шарик прыгнул на клетку. Для игры это плохо: при зажатой клавише keydown повторяется с задержкой (как буквы в текстовом поле), и движение получается рывками. А две клавиши одновременно (вправо + прыжок) так вообще не поймать.

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

Множество зажатых клавиш

Set — коллекция без повторов с быстрыми add, delete и has. Идеально подходит:

const keys = new Set();

document.addEventListener("keydown", (e) => keys.add(e.key));
document.addEventListener("keyup", (e) => keys.delete(e.key));

// в update:
if (keys.has("ArrowLeft")) player.x -= 200 * dt;
if (keys.has("ArrowRight")) player.x += 200 * dt;

Повторные keydown при удержании не мешают: добавить в Set то, что там уже есть, — ничего не меняет.

Стрелки и пробел по умолчанию прокручивают страницу. Чтобы этого не было во время игры:

document.addEventListener("keydown", (e) => {
  keys.add(e.key);
  if (e.key.startsWith("Arrow") || e.key === " ") e.preventDefault();
});

Ещё одна мелочь: если окно потеряло фокус с зажатой клавишей, keyup не придёт, и герой будет бежать сам. Лечится так: window.addEventListener("blur", () => keys.clear());.

Направление и скорость

Удобно сначала посчитать направление −1, 0 или 1, а потом умножить на скорость:

let dx = 0;
if (keys.has("ArrowLeft")) dx -= 1;
if (keys.has("ArrowRight")) dx += 1;   // обе зажаты → 0, стоим
player.x += dx * SPEED * dt;

Если двигаться по диагонали, получается быстрее (√2 ≈ 1.41 раза), потому что складываются два движения. В аркадах это часто прощают, а в точных играх направление нормализуют — делят dx и dy на длину вектора.

Не выйти за край

Чтобы герой не убежал с экрана, его координату зажимают между минимумом и максимумом:

const clamp = (v, min, max) => Math.max(min, Math.min(max, v));

player.x = clamp(player.x, 0, canvas.width - player.w);
player.y = clamp(player.y, 0, canvas.height - player.h);

Максимум — ширина холста − ширина героя, потому что x — это левый край, а правый край у героя на w пикселей дальше.

Прыжок

Прыжок — это мгновенная скорость вверх (отрицательная vy, ведь y растёт вниз), которую дальше гасит гравитация:

if (keys.has(" ") && player.onGround) {
  player.vy = -400;
  player.onGround = false;
}
player.vy += GRAVITY * dt;
player.y += player.vy * dt;

if (player.y >= GROUND) {      // упал на землю
  player.y = GROUND;
  player.vy = 0;
  player.onGround = true;
}

Флаг onGround запрещает прыгать в воздухе. Высота прыжка зависит от начальной скорости и гравитации: больше гравитация — прыжок ниже и «тяжелее». Подбирать эти числа — часть геймдизайна.

Мышь

Мышь на холсте работает так же, через события. Только координаты мыши — относительно окна, а нам нужны координаты внутри холста:

canvas.addEventListener("click", (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
  console.log("клик в точке холста", x, y);
});

Итог

  • События клавиатуры только записывают состояние: keys.add / keys.delete; решения — в update.
  • preventDefault() для стрелок и пробела, keys.clear() при потере фокуса.
  • Направление −1/0/1 × скорость × dt; координаты зажимаем Math.max / Math.min.
  • Прыжок: отрицательная vy + гравитация + флаг onGround.

Какие клавиши зажаты

Лёгкая+10 XP

Заведи множество keys (new Set()) и поддерживай его: при keydown на document добавляй в него e.key, при keyup — удаляй. Напиши функцию isDown(key), которая отвечает, зажата ли клавиша сейчас.

нажали →          isDown("ArrowRight") → true
отпустили →       isDown("ArrowRight") → false

Подключи коннектор, чтобы решать задачи

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

Ищем коннектор на этом компьютере…

  1. 1
    Скачай коннектор для своей системы (Windows, macOS или Linux).Скачать коннекторНа странице загрузки выбери файл со своей системой в названии, например windows-amd64.
  2. 2Запусти его и выбери папку, где будут лежать твои решения. Python и Node.js он поставит туда сам, когда понадобится.
  3. 3
    Введи ниже код из 6 цифр — он написан в окне коннектора («Код для сайта CodeWithMe»). Если браузер спросит про доступ к локальной сети — разреши.

Коннектор открытый (исходный код на GitHub), работает только на твоём компьютере и выполняет код лишь после ввода кода сопряжения.