Гид по технологиям

Как создать игру «Змейка» на HTML/CSS/JavaScript

6 min read Web‑разработка Обновлено 24 Nov 2025
Змейка на HTML/CSS/JavaScript — руководство
Змейка на HTML/CSS/JavaScript — руководство

Человек держит Game Boy — иллюстрация ретро-игры

Классическая игра «Змейка» — отличный учебный проект для улучшения навыков программирования и решения задач. В этой статье показано, как собрать рабочую версию в браузере, используя HTML, CSS и JavaScript с canvas.

В игре вы управляете змейкой, которая перемещается по полю, растёт при поедании еды и проигрывает при столкновении со стеной или своим хвостом.

Что будет в этом руководстве

  • Быстрое создание UI с canvas
  • Отрисовка и представление сегментов змейки
  • Управление клавишами, движение и игровой цикл
  • Появление еды и механизм поедания
  • Логика роста и завершения игры
  • Дополнения: тестовые сценарии, критерии приёмки, чеклисты и подсказки по улучшению

Важно: все размеры в примерах выражены в пикселях (px). Для адаптивности можно масштабировать поле и размеры сегментов по отношению к ширине окна.

Как создать интерфейс canvas

Используйте HTML и CSS для размещения canvas, на котором будет происходить игра. Ниже — базовые шаги и минимальная структура файлов. Для полного исходного кода можно завести репозиторий на GitHub.

  1. Создайте файл index.html.

  2. Добавьте базовую структуру HTML. Пример:



  
    
    Snake Game
    
  
  

  
  1. Внутри body добавьте заголовок и элемент canvas:

Snake Game

  1. Создайте файл styles.css рядом с index.html и добавьте простые стили для поля. Пример:
#game {
  width: 400px;
  height: 400px;
  margin: 0 auto;
  background-color: #eee;
}
h2 {
  text-align: center;
  font-family: Arial, sans-serif;
  font-size: 36px;
}
canvas {
  display: block;
}
  1. Откройте index.html в браузере, чтобы увидеть пустой canvas.

Пустой холст canvas для игры «Змейка»

Как отрисовать змейку

Змейка состоит из квадратных сегментов. В самом начале длина — один сегмент.

  1. Подключите JavaScript-файл в конец body:



  
  1. В script.js получите элемент canvas и контекст 2D:
var canvas = document.getElementById('snake');
var canvas2d = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 400;
  1. Объявите игровые переменные:
var gameEnded = false;
var snakeSegments = [];
var snakeLength = 1;
var snakeX = 0;
var snakeY = 0;
  1. Функция, добавляющая текущую позицию головы в массив сегментов:
function moveSnake() {
  snakeSegments.unshift({ x: snakeX, y: snakeY });
}
  1. Функция отрисовки змейки. Мы используем цвет чёрный и квадрат 10px на 10px для каждого сегмента:
function drawSnake() {
  canvas2d.fillStyle = '#000';
  canvas2d.clearRect(0, 0, canvas.width, canvas.height);
  for (var i = 0; i < snakeSegments.length; i++) {
    canvas2d.fillRect(snakeSegments[i].x, snakeSegments[i].y, 10, 10);
  }
}
  1. Игровой цикл, который обновляет состояние каждые 100 мс:
function gameLoop() {
  moveSnake();
  drawSnake();
  // здесь позже добавим spawnDots(), checkCollision() и т.д.
  if (!gameEnded) {
    setTimeout(gameLoop, 100);
  }
}

// запуск
gameLoop();

Откройте страницу — вы увидите один маленький чёрный квадратик в начальной позиции.

Пример змейки из одного сегмента

Как заставить змейку двигаться

Добавьте логику для смены направления и обновления координат.

  1. Инициализируйте направление движения (в пикселях на кадр):
var directionX = 10;
var directionY = 0;
  1. Обработчик клавиш для стрелок:
document.onkeydown = function(event) {
  switch (event.keyCode) {
    case 37: // Left
      directionX = -10; directionY = 0; break;
    case 38: // Up
      directionX = 0; directionY = -10; break;
    case 39: // Right
      directionX = 10; directionY = 0; break;
    case 40: // Down
      directionX = 0; directionY = 10; break;
  }
};
  1. Обновите функцию moveSnake, чтобы голова смещалась по направлению, и чтобы хвост обрезался до текущей длины:
function moveSnake() {
  snakeSegments.unshift({ x: snakeX, y: snakeY });
  snakeX += directionX;
  snakeY += directionY;
  while (snakeSegments.length > snakeLength) {
    snakeSegments.pop();
  }
}

Если не очищать canvas в drawSnake, то при каждом кадре останутся следы (старые прямоугольники). Поэтому мы делаем clearRect в начале отрисовки.

Одиночный сегмент, движущийся по полю

Как добавить еду на поле

Еда — массив точек (dots). При поедании змейка увеличивается.

  1. Объявите массив точек:
var dots = [];
  1. Функция спавна точек случайно на поле, ограничивая максимум 10 точек:
function spawnDots() {
  if (dots.length < 10) {
    var dotX = Math.floor(Math.random() * canvas.width / 10) * 10;
    var dotY = Math.floor(Math.random() * canvas.height / 10) * 10;
    dots.push({ x: dotX, y: dotY });
  }
}

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

  1. Отрисовка точек в drawSnake или в отдельной функции:
function drawDots() {
  for (var i = 0; i < dots.length; i++) {
    canvas2d.fillStyle = 'red';
    canvas2d.fillRect(dots[i].x, dots[i].y, 10, 10);
  }
}
  1. В gameLoop вызывайте spawnDots() и drawDots():
function gameLoop() {
  moveSnake();
  drawSnake();
  drawDots();
  spawnDots();
  checkCollision();
  if (!gameEnded) setTimeout(gameLoop, 100);
}

Поле с едой — красные квадраты

Как сделать, чтобы змейка росла

При пересечении головы и еды увеличиваем длину и удаляем точку из массива.

function checkCollision() {
  // проверка столкновения с едой
  for (var i = 0; i < dots.length; i++) {
    if (snakeX === dots[i].x && snakeY === dots[i].y) {
      snakeLength++;
      dots.splice(i, 1);
      i--; // корректируем индекс после удаления
    }
  }
  // позже здесь добавим проверку стен и хвоста
}

Откройте страницу и двигайтесь так, чтобы голова проходила по координатам точек — змейка будет расти.

Игровое поле с финальной компоновкой змейки и еды

Как завершить игру

Игра завершается при столкновении с границами поля или при пересечении головы с любым сегментом хвоста.

  1. Функция окончания игры с простым уведомлением:
function gameOver() {
  setTimeout(function() {
    alert('Game over!');
  }, 500);
  gameEnded = true;
}
  1. Проверка выхода за пределы canvas (с запасом 0 px или по вашему шагу):
if (snakeX < 0 || snakeY < 0 || snakeX >= canvas.width || snakeY >= canvas.height) {
  gameOver();
}
  1. Проверка пересечения головы с хвостом:
for (var i = 1; i < snakeSegments.length; i++) {
  if (snakeX === snakeSegments[i].x && snakeY === snakeSegments[i].y) {
    gameOver();
  }
}

Пример alert при окончании игры.

Окно «Game over» в игре

Улучшения и варианты реализации

Ниже — идеи для дальнейшего развития и альтернативные подходы.

  • Альтернативы движку
    • Использовать requestAnimationFrame для плавности и адаптации к частоте кадра.
    • Ввести масштабируемую сетку и относительные единицы вместо фиксированных 10px.
  • Графика
    • Заменить квадраты на изображения или градиенты.
    • Добавить эффекты при поедании еды.
  • Управление
    • Поддержка WASD и сенсорных свайпов для мобильных устройств.
  • ИИ
    • Добавить бота, который играет автоматически, для демонстрации алгоритмов поиска пути.
  • Сохранение
    • Локальное сохранение рекордов в LocalStorage.

Когда подход из статьи может не подойти

  • Если требуется высокая производительность и сложная физика — canvas 2D прост, но для сложной графики лучше WebGL.
  • Для сетевой многопользовательской игры нужен сервер и синхронизация состояния.
  • Если игра должна быть доступна на малых экранах, надо переработать управление и размеры сетки.

Мини-методология: шаги разработки

  1. Скелет: HTML + canvas + базовый CSS.
  2. Отрисовка и базовый игровой цикл без логики столкновений.
  3. Управление клавишами и движение.
  4. Еда и рост.
  5. Логика завершения игры и обработка состояний.
  6. Рефакторинг: вынести константы, улучшить масштабирование, написать тесты.

Чек-листы по ролям

Разработчик

  • Создать структуру файлов.
  • Реализовать игровой цикл и отрисовку.
  • Обработать ввод и столкновения.
  • Убедиться в отсутствии утечек памяти (массивы не растут бесконечно).

QA

  • Проверить движение во всех направлениях.
  • Проверить поедание еды и правильное увеличение длины.
  • Тест на столкновение с границами и хвостом.
  • Граничные сценарии: быстрая смена направления, многократное нажатие клавиш.

Дизайнер

  • Проверить читаемость на разных размерах экрана.
  • Задать цвета и контраст для доступности.

Критерии приёмки

  • Игра запускается в современных браузерах.
  • Змейка корректно движется, управляется стрелками и/или WASD.
  • Еда появляется и исчезает при поедании, длина увеличивается.
  • Игра заканчивается при столкновении со стеной или хвостом.
  • Нет очевидных багов при быстрой смене направлений.

Тестовые сценарии (кратко)

  • Старт игры: canvas видим, один сегмент в позиции (0,0).
  • Движение вправо: после N шагов X увеличивается на N*10px.
  • Поедание еды: при совпадении координат длина увеличивается на 1.
  • Столкновение со стеной: alert показывается, цикл останавливается.
  • Столкновение с хвостом: alert показывается, игра останавливается.

Подсказки и частые ошибки

  • Не забудьте выравнивать координаты еды по шагу движения (например, 10px), иначе совпадение будет редким.
  • Обрабатывайте нажатие противоположной стрелки: если двигались вправо, нельзя сразу принять направление влево — это мгновенно завершит игру.
  • При генерации случайных точек проверяйте, чтобы точка не появилась внутри змейки.

Шпаргалка — часто используемые фрагменты

  • Получить canvas и 2D-контекст:
var canvas = document.getElementById('snake');
var canvas2d = canvas.getContext('2d');
  • Очистить холст:
canvas2d.clearRect(0, 0, canvas.width, canvas.height);
  • Рисовать квадрат 10px:
canvas2d.fillRect(x, y, 10, 10);

Короткий словарь

  • canvas — HTML-элемент для рисования растровой графики.
  • сегмент — один квадратный фрагмент змейки.
  • step/шаг — размер перемещения за кадр, в примерах 10px.

Итог

Создание «Змейки» — отличный проект для закрепления основ DOM, canvas и базовой логики игр. Начните с минимальной версии, затем постепенно добавляйте улучшения: плавность, анимацию, мобильное управление и сохранение рекордов.

Краткие выводы и чек-лист есть выше — используйте их как план релиза минимально жизнеспособного продукта.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство