
Начнём с небольшой предыстории: пару недель назад я ждал друга в кафе. Как обычно, он опаздывал примерно минут на сорок. Ноутбук с собой, интернет есть, а игр нет — чисто рабочая машина, ничего лишнего, хотя нужно будет что-то скачать, чтобы играть на работе xd. От скуки я открыл браузер и набрал в поиске «змейка». Google выдал свою фирменную змейку прямо в результатах поиска.
Я кликнул, и пошла игра. Потом прошло пять минут, десять, пятнадцать, и я не мог оторваться, так как немного азартный и, пока не выиграю, не захочу заканчивать. После многих поражений, примерно на двадцать пятой минуте игры, я поймал себя на мысли: а почему яблоко всегда жертва и почему вообще змейка — наш главный герой?
Друг пришёл на тридцать пятой минуте. Я закрыл ноутбук, но мысль засела. И тем же вечером я уже начал писать код: вот поле, вот красное яблоко, вот змейка, вот ещё одна, и все они пытаются съесть яблоко.
Так моё желание доказать, что яблоко не просто ждун, а тоже личность, пошло дальше, и я решил написать минимально простую игру: просто посмотреть логику и подумать, может, поменять правила или как-то усложнить игру.
За два плотных вечера проект вырос из прототипа в полноценную игру с тремя типами змей, интерфейсом для телефонов и компьютеров. В этой статье я расскажу обо всех этапах: от зелёного квадрата на чёрном фоне (отсылка на прошлую статью) до пиксельного яблока с листиком, которое отчаянно пытается выжить.
Как устроена обычная змейка
Начнём, думаю, с классики — как устроена обычная змейка и с чего все началось. Если говорить кратко про историю то, первая версия появилась аж в 1976 году под названием Blockade — её запилили ребята из Gremlin Industries для игровых автоматов. И самое удивительное, что для меня стало новостью: там никаких яблок вообще не было, и змея была не одна и вообще не росла.
Смысл игры был таким, что два игрока управляли змеями, которые оставляли за собой стену, и условием победы было просто загнать соперника в тупик. Если вспоминать аналоги, то мне сразу же напомнили эту игру события из фильма и одноимённой игры Tron Light Cycles. В конце концов всё оказалось ещё проще, чем в той игре, которую все знают: никакой еды и очков, просто стены и змейки. Потом, в 1978-м, игра перебралась на Atari 2600 под названием Surround — там уже добавили цвета и разные режимы, но суть та же: стены и тупики.
А настоящий бум случился в 1997-м, когда Nokia взяла и предустановила Snake на свой 6110, и здесь понеслось — сотни миллионов телефонов, и змейка стала народной игрой, в которую рубились вообще все — от школьников до банкиров. В 2013-м Nokia переродилась под Microsoft, игру переписали под смартфоны, но та самая чёрно-белая версия уже навсегда в истории как символ мобильных игр девяностых (статья, в которой хорошо прописана история).

Теперь разберём, как работает классическая змейка. В этой игре простое поле, которое поделено на клетки, где в каждом кадре голова сдвигается в текущем направлении, новый сегмент добавляется в начало массива, а последний удаляется. Если змея съела яблоко, последний сегмент не удаляется, и змея растёт.
let head = { x: snake[0].x + dx, y: snake[0].y + dy }; snake.unshift(head); if (!ateApple) snake.pop();
Вся магия — в трёх строчках. Направление меняется по нажатию клавиши. Как в теории, так и во всех играх мы проверяем коллизию простым сравнением координат головы и остального тела: находятся ли они в границах поля. Яблоко появляется в случайной свободной клетке.
Если подумать, «Змейка» — очень понятная и простая игра, которая стала мировым феноменом благодаря своей универсальной доступности в те годы и увлекательному геймплею. Будучи предустановленной на миллионах легендарных телефонов Nokia, она предложила людям простой способ скоротать время и превратила мобильный телефон из аппарата для звонков в персональное игровое устройство, что было новинкой для того времени.
Как я перевернул правила
Первое, что я сделал, — поменял роли. Игрок управляет не змеёй, а яблоком. Цель — не собрать очки, а просто выжить как можно дольше. Счёт растёт сам по себе, каждое мгновение жизни — уже победа.
Второе — змеи больше не растут. Они появляются из-за краёв поля, проходят сквозь экран и исчезают с другой стороны, если игрок сумел от них уйти. Никакого поедания, никакого увеличения — только преследование. Вот тут, кстати, я думаю, можно поразмышлять, т. к. если, например, игра будет начинаться с маленьких змей, а потом, чем больше у тебя будет очков, тем больше будут становиться змейки (не пробовал, но эта идея пришла уже при написании статьи).
Третье — змеи бывают разные. Почти как пелось в песне: чёрные, белые, красные. Ладно, тут обычные зелёные, жёлтые и красные, как светофор. И это не просто внешний вид, а различия в их поведении в игре. Я хотел, чтобы игрок постоянно адаптировался, и поэтому их три вида, а появляются они случайным образом (почти). Так родились три типа:

Зелёные — обычные линейные крипы, которые идут прямо по линии без поворотов или каких-нибудь усложнений. Главное только то, что они ходят поочерёдно: то по горизонтали, то по вертикали.

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

Красные — толстые и хитрые. Первые тридцать ходов агрессивно преследуют игрока, а потом внезапно разворачиваются и уходят к ближайшему краю. Игрок расслабляется — и тут появляется новая красная змея.
Четвёртое — сложность самой игры. Здесь были проблемы: баланс с нуля всегда сложно придумать, и поэтому его нужно будет, скорее всего, менять. Сейчас змеи появляются по таймерам, и чем дольше живёшь, тем короче становятся интервалы между спавнами. Тем самым на экране просто становится больше змей, и выжить почти невозможно.
Структура проекта
Я решил не сваливать всё в один файл, а разбить проект на модули. А так как проект простой, можно было и в один, но это некрасиво. Никаких сборщиков, никаких import и export — просто четыре файла, которые подключаются в правильном порядке через теги <script>. Открываешь index.html — и всё работает.
Вот как выглядит структура:
reverse-snake/ ├── index.html ├── style.css ├── snake.js ├── renderer.js └── game.js
Как игра работает внутри
Я решил не мудрить с архитектурой и написал всё на классах. Как обычно, и в прошлых статьях, я не использую никаких фреймворков, сборщиков или готовых решений из интернета. Главное, чтобы я мог открывать веб-программу и спокойно поиграть.
Теперь пойдём по классам. Например, класс Snake отвечает за одну змею. Он хранит массив сегментов тела, текущее направление, тип и коэффициент скорости. Главный метод update() получает позицию игрока и решает, куда двигаться дальше. Логика разная для каждого типа:
if (this.type === 'yellow' && this.state === 'normal' && this.timer === 10) { this.state = 'turned'; if (this.dx !== 0) { this.dx = 0; this.dy = player.y > head.y ? 1 : -1; } else { this.dy = 0; this.dx = player.x > head.x ? 1 : -1; } }
Класс Renderer занимается отрисовкой и ничем больше, использует только fillRect() и никаких спрайтов. Сетка рисуется как шахматная доска: чётные клетки темнее, нечётные светлее. Змеи отрисовываются как квадраты с внутренней текстурой и каждой змеи свой внешний вид: сначала внешний цвет, потом тёмный прямоугольник внутри, потом два чёрных квадратика-глаза у головы, чтобы у человека появлялось чувство антропоморфизма. Такое же действие делаем с яблоком, которое состоит из восьми пикселей на клетку: красное тело, белый блик, коричневый черешок и зелёный листик.
Класс Game управляет всем: запускает игровой цикл, обрабатывает коллизии, считает очки, спавнит змей по таймерам. Отдельно я вынес логику интервалов спавна в метод updateSpawnTimers(), который пересчитывает частоту появления змей в зависимости от текущего счёта.
Разделение на три файла (snake.js, renderer.js, game.js) спасло меня от хаоса. Когда жёлтая змея странно поворачивала, я знал, что копать нужно в Snake. Когда пиксели съезжали — проблема была в Renderer. Когда интервалы спавна работали не по плану — в Game. И так можно перечислять до бесконечности.
Адаптация под телефоны
Я люблю, когда проект можно открыть с любого устройства — и на компе, и на телефоне. Но с телефонами всегда морока. А, т. к. многие смотрят с телефона, то лучше придумать решение этих проблем.
С клавиатурой всё просто: её нет — значит, сделаем свою. Я добавил четыре кнопки-стрелки прямо на экране, под игровым полем. Они расположены крестом: верх, низ, лево, право. Выглядят как обычные серые квадраты с треугольниками внутри, ничего лишнего. На компе эти кнопки спрятаны, они появляются только на узких экранах, где ширина меньше 768 пикселей.
С размером экрана было сложнее всего, т. к. я привык, что на десктопе сетка 24×24 клетки смотрится нормально, но на телефоне она превращается в мелкую мозаику — пальцем не попасть, глаза сломаешь. Поэтому я сделал так, чтобы игра сама подстраивалась под ширину экрана. Если экран узкий, как у телефона, сетка становится 20×20 клеток — каждая клетка крупнее, и играть удобнее. Если планшет — 22×22. А если нормальный монитор — классические 24×24.
Ещё одна фишка — пауза. На компе я, как и обычно в играх, нажимаю Esc и спокойно ставлю игру на паузу, но вот здесь и появляется проблема, на телефоне Escape просто нет. Сначала аналогично мобильным играм, я хотел сделать отдельную кнопку паузы, но потом подумал и нашёл в интернете решение: а что, если просто встряхнуть телефон? Оказалось, в браузере есть событие devicemotion — оно считывает показания акселерометра. Я беру ускорение по трём осям, считаю общую величину, и если она больше 25 (это значит, что телефон хорошо тряхнули), игра встаёт на паузу. Работает как магия: тряхнул — меню вылезло. Интересное решение, которое нашёл в интернете. До этого проекта не знал, что так можно.
const magnitude = Math.sqrt( acceleration.x ** 2 + acceleration.y ** 2 + acceleration.z ** 2 ); if (magnitude > 25) pauseGame();
Балансировка и тестирование
Самым сложным оказался баланс, что, конечно, логично, но всё же было тяжело. Первая версия спавнила слишком мало змей — можно было бегать минутами без всякой угрозы, тем самым игра была прям очень скучной. Потом я решил увеличил частоту — игра превратилась в хаос и уже было невозможно просто уворачиваться от змей на двадцатом очке, когда поле заполнялось десятком змей одновременно, яблоко съедалось моментально, и ты проигрывал.
Решение нашлось не сразу, но благодаря методу проб и ошибок. Я ввёл лимиты на максимальное количество змей каждого типа: не больше шести зелёных, пяти жёлтых и трёх красных, затем подогнал интервалы спавна под разные этапы игры, чтобы чем дольше ты играешь, тем была сложнее игра. Первые пятьдесят очков — расслабленный режим, только зелёные, к ста двадцати очкам появляются жёлтые и уже к двумстам пятидесяти — красные не отстают, и зелёные сыплются каждые восемнадцать ходов.
Итог
Могу сказать одно: это было неожиданно весело, я всего лишь хотел убить время в кафе, а в итоге получил великолепную идею, которую я смог реализовать и поиграть. Яблоко убегает, змеи наступают, счёт тикает — всё, как я задумал, и больше считаю, что добавлять ничего не надо.


Моё мнение о результате и размышления
Я доволен результатом, проект напомнил мне, что не всегда нужны сложные технологии, чтобы сделать что-то интересное. Иногда достаточно перевернуть старую идею с ног на голову — и получить новую игру.
Из минусов пока не знаю, что делать дальше. Надо подумать, за что браться следующим. Есть мысль сделать что-то вроде тамагочи: пиксельного питомца на чистом Canvas, которого нужно кормить и укладывать спать. Звучит как вызов, но после змейки как раз есть силы и интерес.
Если же возвращаться к «Обратной змейке», проект мне понравился, идея простая, но цепляет. Реализация вышла минималистичной и стильной, как я и хотел. Но, конечно, есть что улучшить, хотя ничего критичного я пока не вижу.
Код проекта находится здесь, поиграть в мою версию «Змейки» можно здесь.
P.S. Если у вас есть идеи по улучшению, вы нашли баг или просто хотите похвастаться своим рекордом — пишите в комментариях.
© 2026 ООО «МТ ФИНАНС»
Комментарии (27)

danilovmy
16.06.2026 13:42Меня съела зеленая змея. Но вайб все равно от pac-man. Особенно когда яблоко начнёт собирать жемчужины....

Laborant_Code Автор
16.06.2026 13:42Спасибо за отзыв! Но если так подумать, смысл Pac-Man как раз в жемчужинах, а тут скорее надо выживать, как в Galaga только без уничтожений своих противников.

gerbert_MX
16.06.2026 13:42прикольно

мой рекорд, я хз как автор на скрине за 600 ушел не хватает только регулировки скорости (и что бы результат высчитывался как скорость*время, а не просто время) и колизий меж змейками а то за 300 уже начинается каша когда может быть три вида змеек в одной клетке и если "не повезет" с генерацией то никакая ловкость пальцев не поможет так как змейки могут создавать закрытые обьемы, проходя свозь друг друга

Laborant_Code Автор
16.06.2026 13:42Вот, как и писал раньше, скорость и баланс появления надо продумать. А про рекорд 645 — это мастерство, которое не пропьешь (xd, я даже не заметил, что он был на скрине). Это, скорее всего, просто до усложнения появления был, а потом уже стало сложно и до 400+ очков дойти.
Спасибо за ваше мнение!

jouilk23
16.06.2026 13:42Правильная идея считать очки с учетом множителя скорости. Это будет мотивировать игроков рисковать ради больших результатов, а не просто прятаться в углах на минималке

iShrimp
16.06.2026 13:42Эту игру можно улучшать и модифицировать бесконечно :)
Змейка в 3D? - уже где-то было...
Змейка на фрактале (ковре Серпинского)? Поле с дефектами.
Змейка на сфере? Поле без границ, но конечной площади. Две параллельно идущие змейки обязательно пересекутся.
Змейка на гиперболической плоскости (как в HyperRogue)? Места предостаточно. Параллельные прямые расходятся. Замучаешься искать яблоко. Зато хвост не будет мешать.
Змейка, поворачивающая только в одну сторону? Или поочередно влево-вправо, с управлением одной кнопкой типа Snek Left в Fancade.
Змейка, постоянно растущая, укорачивающаяся при съедании яблока?
Змейка с квантовой механикой и суперпозицией кучи состояний? Почти как квантовые шахматы, только змейка.

evgenstf
16.06.2026 13:42Еще можно сделать игру, где ты типа грибок, и прыгаешь на супер Марио

Laborant_Code Автор
16.06.2026 13:42Тогда скорее Боузер и пытаешь похитить принцессу, а не спасти, как марио

Metotron0
16.06.2026 13:42Не честно, что змеи проходят друг сквозь друга. А ещё странно, что игрок появляется неподвижным, но потом нельзя остановиться.

Laborant_Code Автор
16.06.2026 13:42Про не неподвижность, скорее как в оригинале ты же вначале стоишь на месте, а потом нельзя остановиться. А про змей посмотрю, что можно сделать

Sfekss
16.06.2026 13:42В оригинале скорость увеличивается пропорционально съеденым вкусняшкам. Тут старт сразу с реактивной скорости, что добавляет сложности на старте.
Какое среднее время игры? Начинается сразу с хардкора, 10 или 20 секунд? Вряд ли будет прям очень сильно затягивать, нужно больше времени для фиксации.

Wesha
16.06.2026 13:42Яблоко б на лягушку заменили, а то яблоко, которое само по себе ездит...

Laborant_Code Автор
16.06.2026 13:42Если рассуждать со стороны логики, то вы правы, но тогда пропадает шарм игры змейка, как будто

san4ez_gig
16.06.2026 13:42Прикольно, довольно затягивает. Я бы сделал кнопки на телефоне побольше и добавил коллизию между змеями

Deosis
16.06.2026 13:42Описание напоминает жанр Bullet Hell: надо уворачиваться от разных видов снарядов, заполняющих большую часть поля.

sogonov
16.06.2026 13:42Идея классная, можно по мотивам Марио добавить какие-то ГМО появляющиеся на пути яблока, чтобы оно на время могло выживать от одного укуса, или крушить змей собой. Однозначно добавит экшена)

Laborant_Code Автор
16.06.2026 13:42Хорошая идея, мне нравится, но надо подумать, что будет канонично — чтобы яблоко съело что-то и повысило себе защиту от змей.

manyakRus
16.06.2026 13:42а где кнопка остановиться на месте ?
ато как бешенный принтер гоняет туда сюда

jouilk23
16.06.2026 13:42Очередное переизобретение пакмана, только без лабиринта и возможности съесть привидений
Зато на чистом джс, это мы уважаем

Yarus23
16.06.2026 13:42плюс минус 200 и все. хорошо бы чтобы дальше продолжать играть а) выкидывать на поле что то - жизни там например или невидимость б) например уровни - 200 шт от легких к сложным. и вконце каждого десятого уровня например босс.
razvivausI_flag_I
Идея и вправду оригинальная, как по мне. Поиграл с телефона. Рекорд 208. На телефоне иногда попадал не на кнопки управления. В целом играл на инстинктах и просто кликал. Конечно, и здесь можно натренироваться, но все же хардкор из-за постоянной генерации змей, маленького пространства самого поля и его ещё большего уменьшения из-за красных змей присутствует
Laborant_Code Автор
Спасибо за отзыв! И отдельный респект за то, что не просто прошли мимо, а поиграли и даже написали свой рекорд — 208 очков.
Вы точно подметили ту проблему, которую я и сам заметил, — это баланс. Сейчас на 200-300+ очках баланс уходит в перекос: змей слишком много, а высокая скорость и маленькое поле почти не оставляют шансов на бесконечную игру, как это принято в подобных жанрах.
Пока думаю, как можно улучшить или сбалансировать хардкор и саму игру, чтобы сохранить гармонию, поэтому, если есть идеи, рад буду услышать, может даже добавлю со временем.
Owyn
Поиграл с ПК-лисы:
яблоко при движении мерцает будто пытается убивать вас эпилепсией
куча змей которые по ощущениям движутся просто хаотично (если б они появлялись постепенной усложняя игру со временем - я б ещё понял)
всё довольно быстро происходит, по ощущениям куда быстрее классической змейки (и яблоко будто скользит по льду - моглиб хоть ноги ему приделать :-) )