Как написать игру Змейка на JavaScript

Как написать змейку на javascript

Как написать змейку на javascript

Змейка – это динамическая игра, в которой игрок управляет последовательностью элементов, растущих при сборе еды. Вместо использования Canvas можно построить логику с помощью обычных HTML-элементов: поле игры создаётся в виде таблицы или набора div-блоков, которые обновляются через изменения их классов.

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

Управление реализуется через обработку событий keydown. Важно сразу исключить возможность разворота в противоположную сторону, чтобы змейка не врезалась сама в себя. Для хранения текущего направления удобно использовать переменную с одним из четырёх значений: up, down, left, right.

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

Создание HTML-структуры и настройка canvas

Создание HTML-структуры и настройка canvas

Для игры требуется минимальная разметка: контейнер с тегом , где будет происходить отрисовка. Зададим ему уникальный идентификатор, чтобы получить доступ из JavaScript.

Пример:

<canvas id="game" width="400" height="400"></canvas>

Размеры указываются атрибутами width и height, так как изменение через CSS искажает координатную сетку. Для классической версии игры удобен квадрат 400×400 пикселей, который делится на клетки размером 20×20.

После вставки тега необходимо получить доступ к элементу через JavaScript с помощью document.getElementById("game"). Это позволит работать с методами отрисовки и задать сетку для движения змейки.

Инициализация игрового поля и переменных

Инициализация игрового поля и переменных

Игровое поле можно реализовать с помощью обычной таблицы <table>. Размер задаётся константами, например: rows = 20, cols = 20. Каждая ячейка создаётся в цикле и сохраняется в двумерный массив для быстрого доступа по индексам.

Змейка представляется массивом координат, где первый элемент – голова. Пример начального значения: snake = [{x: 10, y: 10}]. Направление движения хранится в отдельной переменной, например direction = ‘right’.

Для генерации еды используется объект с координатами: food = {x: 5, y: 5}. Эти значения обновляются при каждом появлении новой еды в случайной ячейке, которая не пересекается с телом змейки.

Счёт очков можно хранить в переменной score = 0. Она увеличивается при каждом поедании еды и используется для отображения прогресса.

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

Реализация движения змейки с помощью клавиатуры

Реализация движения змейки с помощью клавиатуры

Для управления достаточно отлавливать событие keydown. Клавиши со стрелками имеют коды: 37 (влево), 38 (вверх), 39 (вправо), 40 (вниз). Для надёжности следует использовать свойство event.key, так как оно более читаемо.

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

Пример структуры с координатами и направлением:

let snake = [{x: 5, y: 5}];
let direction = "right";
document.addEventListener("keydown", function(e) {
if (e.key === "ArrowUp" && direction !== "down") direction = "up";
if (e.key === "ArrowDown" && direction !== "up") direction = "down";
if (e.key === "ArrowLeft" && direction !== "right") direction = "left";
if (e.key === "ArrowRight" && direction !== "left") direction = "right";
});

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

Сопоставление направлений со смещениями удобно хранить в объекте:

Направление Смещение по X Смещение по Y
up 0 -1
down 0 1
left -1 0
right 1 0

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

Добавление еды и проверка столкновений

Добавление еды и проверка столкновений

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

  1. Создать функцию генерации случайных координат в пределах игрового поля.
  2. Проверить, что выбранная клетка не занята змейкой.
  3. Если клетка свободна – вставить div с классом «food» в DOM.

Пример функции для генерации еды:

function createFood(snake) {
let x, y;
do {
x = Math.floor(Math.random() * 20);
y = Math.floor(Math.random() * 20);
} while (snake.some(segment => segment.x === x && segment.y === y));
const food = document.createElement('div');
food.id = 'food';
food.style.gridRowStart = y + 1;
food.style.gridColumnStart = x + 1;
document.getElementById('board').appendChild(food);
return { x, y };
}

Чтобы проверить столкновение головы змейки с едой:

  • Сравнить координаты головы и еды.
  • Если совпали – удалить элемент еды из DOM.
  • Увеличить массив змейки на один сегмент.
  • Сгенерировать новую еду вызовом createFood().

Проверка столкновений со стенами и телом змейки:

  • Голова выходит за границы игрового поля – игра завершается.
  • Голова совпадает с любым сегментом тела – также конец игры.
function checkCollision(snake, boardSize) {
const head = snake[0];
if (
head.x < 0 || head.y < 0 ||
head.x >= boardSize || head.y >= boardSize
) return true;
for (let i = 1; i < snake.length; i++) {
if (head.x === snake[i].x && head.y === snake[i].y) {
return true;
}
}
return false;
}

Для хранения текущего счета создайте переменную score и увеличивайте её при каждом «съедании» еды. Например: score++;.

Чтобы отображать счет, заранее подготовьте элемент в разметке, например: <div id="score">0</div>. После изменения значения используйте document.getElementById("score").textContent = score;.

Для итогового результата при окончании игры добавьте отдельный блок, например: <div id="game-over"></div>. В момент остановки цикла присвойте ему текст: document.getElementById("game-over").textContent = "Игра окончена! Ваш результат: " + score;.

Организация игрового цикла с requestAnimationFrame

В игре Змейка игровой цикл управляет обновлением состояния змейки и отрисовкой элементов на экране. В JavaScript для этого используется requestAnimationFrame, обеспечивающий синхронизацию с частотой обновления экрана.

Для реализации цикла следует учитывать:

  • Время между кадрами. requestAnimationFrame вызывает функцию примерно 60 раз в секунду, поэтому необходимо контролировать скорость змейки отдельно, чтобы движение не было слишком быстрым.
  • Состояние игры. Каждый кадр нужно проверять текущее положение змейки, столкновения с границами и самопересечения.
  • Обновление позиции. Логика движения змейки должна выполняться на основе последнего состояния и выбранного направления.

Пример структуры цикла:

  1. Определяем переменные lastRenderTime и gameSpeed.
  2. Создаем функцию main(currentTime), где currentTime приходит от requestAnimationFrame.
  3. Вычисляем разницу времени: const delta = (currentTime - lastRenderTime) / 1000;
  4. Если delta превышает 1 / gameSpeed, вызываем функции update() и draw(), обновляем lastRenderTime.
  5. Рекурсивно вызываем requestAnimationFrame(main) для следующего кадра.

Рекомендации по оптимизации:

  • Избегать тяжелых вычислений внутри цикла. Переменные для состояния змейки и еды лучше хранить в массивах и объектах.
  • Разделять логику update и draw, чтобы можно было менять частоту обновления и отрисовки независимо.
  • Использовать deltaTime для точного контроля движения при нестабильной частоте кадров.
  • Следить за корректным отменением анимации при паузе или окончании игры через cancelAnimationFrame.

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

Вопрос-ответ:

Как правильно организовать игровое поле для змейки на JavaScript?

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

Как реализовать движение змейки по экрану?

Движение змейки создают с помощью обновления координат головы змейки в заданном направлении и смещения всех сегментов хвоста на позиции предыдущего сегмента. Часто используют функцию setInterval или requestAnimationFrame для регулярного обновления положения змейки, что позволяет контролировать скорость движения.

Каким образом можно обработать столкновение змейки с границами или с самой собой?

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

Как добавить «яблоки» для змейки и увеличить её длину при поедании?

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

Какие способы есть для управления змейкой с клавиатуры?

Наиболее распространённый способ — использовать событие keydown для отслеживания нажатий стрелок или клавиш WASD. В обработчике события нужно менять направление движения змейки, проверяя, чтобы новая ось движения не была противоположна текущей, иначе змейка может столкнуться сама с собой мгновенно.

Как задать движение змейки в разные стороны с помощью клавиатуры?

Для управления змейкой обычно используют события клавиатуры. В JavaScript это делается через обработчик события ‘keydown’. Внутри него можно проверять, какая клавиша была нажата, используя свойство event.key или event.code, и в зависимости от этого менять направление движения. Например, при нажатии стрелки вверх меняется вертикальная скорость на отрицательное значение, при стрелке вниз — на положительное. Также важно предусмотреть запрет на разворот змейки на 180 градусов, чтобы она не «съела» сама себя за один ход.

Как правильно обновлять положение змейки и отображать её на экране?

Обновление положения змейки обычно реализуется через цикл, который повторяется с определённым интервалом. В JavaScript для этого используют функцию setInterval или requestAnimationFrame. В каждом цикле к массиву сегментов змейки добавляется новая координата головы, а последняя точка убирается, если змейка не съела еду. После обновления координат необходимо очистить холст (canvas) и отрисовать каждый сегмент змейки заново, используя методы fillRect или аналогичные. Такой подход позволяет плавно перемещать змейку и одновременно контролировать столкновения с границами и самой собой.

Ссылка на основную публикацию