Как я создал «Обратную змейку» на чистом Canvas

Как я создал «Обратную змейку» на чистом Canvas
Змейка

Начну с небольшой предыстории: пару недель назад, ожидая друга в кафе, я оказался в ситуации «рабочего ноутбука». Игр на устройстве нет, а время нужно было чем-то убить. В поисках развлечения я открыл браузер и вбил в поиск «змейка». Google тут же предложил свою версию игры.

Я запустил её на пару минут, но в итоге завис на полчаса. В какой-то момент, после очередной неудачной попытки, я поймал себя на философском вопросе: почему яблоко всегда выступает в роли пассивной жертвы, а змейка — в роли доминирующего хищника?

Когда приятель наконец пришел, ноутбук был закрыт, но идея уже прочно засела в голове. Вечером того же дня я открыл редактор кода. Игровое поле, яблоко, пара змей — процесс пошел. Моя цель заключалась в том, чтобы доказать: яблоко — не просто объект для поедания, а полноценный участник геймплея, пытающийся выжить.

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

Эволюция классики: от Blockade до Nokia

История «Змейки» началась в 1976 году с аркадного автомата Blockade от Gremlin Industries. Что удивительно, в оригинале не было ни яблок, ни роста персонажа — двое игроков пытались загнать друг друга в тупик, оставляя за собой «стену». Позже эта механика ярко проявилась в фильме «Трон». Лишь к 1978 году в игре Surround на Atari 2600 добавили цвета, но суть оставалась прежней. Настоящий же культурный феномен случился в 1997-м, когда предустановленная на Nokia 6110 «Snake» превратила мобильный телефон в портативную игровую консоль для миллионов пользователей (подробный исторический экскурс).

Blockade
Blockade

Технически классика работает примитивно: сетка, смещение головы в каждом кадре и манипуляции с массивом сегментов. Если яблоко «съедено», хвост не удаляется, провоцируя рост.

let head = { x: snake[0].x + dx, y: snake[0].y + dy };
snake.unshift(head);
if (!ateApple) snake.pop();

Вся «Змейка» держится на трех строчках кода и базовой проверке коллизий. Именно эта простота и доступность сделали её легендарной.

Переворот правил: яблоко против системы

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

Змеи здесь больше не растут. Они появляются из-за краев экрана и стремятся перехватить «героя». Я решил усложнить процесс, добавив три типа поведения, соответствующих цветам «светофора»:

Зелёные
Зелёные: линейные и предсказуемые

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

Жёлтые
Жёлтые: непредсказуемые спринтеры

Желтые враги быстры и способны менять курс каждые десять ходов, пытаясь предугадать ваши действия.

Красные
Красные: хитрые преследователи

Красные — самые опасные. Первые тридцать ходов они агрессивно охотятся за вами, после чего ретируются к краю карты.

Баланс сложности строится на динамическом спавне: чем дольше вы живете, тем короче интервалы появления новых змей.

Структура и логика

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

reverse-snake/
├── index.html
├── style.css
├── snake.js
├── renderer.js
└── game.js

В основе лежат классы. Snake управляет логикой движения, Renderer отвечает за графику (никаких спрайтов — только чистый Canvas и отрисовка примитивов), а Game координирует процесс и считает очки.

Мобильная адаптация и «фишка» с паузой

Для комфортной игры на телефонах я добавил экранный контроллер, который активируется автоматически на узких экранах. Сетка также масштабируется: 20×20 для смартфонов и до 24×24 для больших мониторов.

Интересной находкой стало управление паузой. Поскольку кнопки Esc на мобильных нет, я задействовал API акселерометра. Резкий взмах телефоном (встряска) срабатывает как триггер паузы через событие devicemotion.

const magnitude = Math.sqrt(
    acceleration.x ** 2 + 
    acceleration.y ** 2 + 
    acceleration.z ** 2
);
if (magnitude > 25) pauseGame();

Итог

Проект «Обратная змейка» — это пример того, как обычная скука в кафе может вылиться в увлекательную разработку. Попытка переосмыслить легендарную классику удалась: баланс получился напряженным, а геймплей — минималистичным и цепляющим.

Весь исходный код доступен здесь, а опробовать игру в действии можно по этой ссылке. Буду рад вашим отзывам, баг-репортам и хвастовству результатами в комментариях!

© 2026 ООО «МТ ФИНАНС»

 

Источник

Читайте также