Пишем Pac-Man на чистом JavaScript: ностальгия, «Пиксели» и туман войны
- четверг, 19 марта 2026 г. в 00:00:05

Недавно, когда писал статью про «Тетрис», я поймал себя на мысли, что вспоминаю не только падающие блоки, но и другой культовый проект — жёлтый кругляш, вечно убегающий от призраков. А потом в памяти всплыл фильм «Пиксели» (2015). Там есть сцена, которая одновременно смешная — жутковатая: создатель Пакмана, Тору Иватани, выходит к гигантскому Пакмену и пытается с ним поговорить по-отечески:
«Пакман, я сделал тебя. Ты такой голодный, я знаю. Не надо больше есть. Хороший мальчик» — актёр Денис Акияма (Тору Иватани).
А Пакман в ответ... откусывает ему руку.
И вот я подумал: а почему бы не попробовать самому создать Пакмена? Не такого кровожадного, конечно, а просто для души. Тем более что с «Тетрисом» получилось удачно, захотелось закрепить успех.
Если вы не смотрели «Пиксели» — ничего страшного. Это лёгкая комедия с понятным сюжетом: шутки, спецэффекты и тоска по играм, на которых многие выросли. Но меня зацепило другое, когда смотришь этот фильм, ловишь себя на мысли, что старые игры — они как часть жизни.
Пакмен, пришельцы из Space Invaders, герои Donkey Kong — они никуда не уходят. Даже когда их персонажи исчезают с экранов, остаётся память. О том детстве, когда счастье измерялось количеством набранных очков. Хотя, если честно, с тех пор мало что изменилось — просто цели стали другими.
А теперь немного про сам проект и почему я решил не просто скопировать классику, а добавить что-то своё.

Всё началось в 1980 году. Японец Тору Иватани, которому тогда было 25 лет, создал игру, ставшую символом целой эпохи. Говорят, идея пришла к нему за обедом — когда он откусил кусок пиццы и увидел в оставшейся части знакомый образ. Так появился Пакмен — персонаж, который должен был привлечь в игровые залы не только подростков, но и девушек.
Кстати, про название. Сначала игру хотели назвать Puck Man — от японского «паку-паку» (звук, с которым открывается и закрывается рот). Но в Америке быстро смекнули: букву «P» в слове Puck легко подрисовать до неприличного слова на букву «F». Чтобы игровые автоматы не портили вандалы, название сменили на Pac-Man. Просто и прагматично.
Видите ли, разработка игр часто начинается со слов. Я начал играть со словом, делая наброски в своём блокноте. Все доступные в то время компьютерные игры были жестокими — военные игры и игры типа «Космический захватчик». Не было игр, которые могли бы понравиться всем, и особенно не было игр для женщин. Я хотел придумать «комическую» игру, которая бы понравилась женщинам.
История, которую я люблю рассказывать о происхождении Пакмана, такова: однажды в обеденное время я был очень голоден и заказал целую пиццу. Я взял себе кусочек, и то, что осталось, стало идеей для формы Пакмана, — вспоминал позже Иватани (источник).
И это сработало. Пакмен стал не просто игрой, а культурным феноменом. По мотивам выпускали мультсериалы, игрушки, одежду. А в 2010 году Google выпустил первый в истории интерактивный дудл к 30-летию игры.
Вдохновившись этой историей, я решил создать свою версию. Но просто скопировать классику — скучно. Нужно было придумать фишку, которая отличала бы мою игру от тысяч других клонов. И тут я вспомнил про туман войны из стратегий — почему бы не добавить его в Пакмена?
Главная задача — не создать идеальный код и не утверждать, что это нечто революционное. Всё проще: написать игру для души, вспомнить старые времена и поделиться результатом. А заодно спросить совета у сообщества — как лучше сделать призраков и что считать победой.
Нужно было добиться плавного движения, корректной физики столкновений и, конечно, того самого эффекта тумана, чтобы игрок не видел весь лабиринт целиком. Вроде получилось.
Весь код открыт и находится на GitHub (это не финальная часть проекта, будет вторая часть, где будет много новых функций). Пока можно просто смотреть, форкать и предлагать улучшения.
Как и в проекте с «Тетрисом», здесь ничего сверхсложного нет. Всё на том, что уже есть в любом браузере.
Что использовал:
HTML — чтобы разложить поле для игры, джойстик, счёт.
CSS — анимации, повороты спрайтов, све��ение.
JavaScript — ну куда без него, вся логика на нём.
Структура проекта:
├── index.html # Сама страница с игрой ├── style.css # Дизайн и анимации ├── game-constants.js # Константы: размеры карты, скорость, режимы ├── game.js # Основная логика Пакмена ├── ghosts.js # Поведение призраков └── controls.js # Управление (клавиши + джойстик)
Как и в «Тетрисе», всё построено на двумерном массиве. Карта — это массив строк, где каждый символ отвечает за тип клетки:
const MAZE = [ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "X...o..X................o......X", "XX.XX.XXX.XXX.XXX.XXXXXX.XXXX.XX", // и так далее... ];
Расшифровка простая:
X — стена.
. — точка (10 очков).
o — энерджайзер (50 очков + режим испуга для призраков).
B, P, I, C — домики призраков.
Размер клетки — 15 на 15 пикселей. Это позволяет легко рассчитывать позиции: просто умножаем номер колонки или строки на 15.
Как и в «Тетрисе», прежде чем подвинуть Пакмена или призрака, нужно проверить — а можно ли? Не врежется ли он в стену?
Для этого есть простая функция, которая смотрит, что находится в соседней клетке:
function canMoveInDirection(dir, row, col) { if (dir === 0) return col + 1 < MAZE_COLS && MAZE[row][col + 1] !== 'X'; if (dir === 1) return col - 1 >= 0 && MAZE[row][col - 1] !== 'X'; if (dir === 2) return row - 1 >= 0 && MAZE[row - 1][col] !== 'X'; if (dir === 3) return row + 1 < MAZE_ROWS && MAZE[row + 1][col] !== 'X'; return false; }
На этой простой проверке держится всё движение. Хочешь идти вправо? Проверь, что справа не стена. Всё честно.
А вот здесь самое интересное. В классическом Пакмене видно весь лабиринт. В моей версии — только то, что вокруг Пакмена в радиусе 6 клеток. Всё остальное скрыто полупрозрачным туманом.
Работает это так: после каждого движения мы проходим по всем стенам, точкам и энерджайзерам, считаем расстояние до Пакмена и меняем прозрачность:
function updateVisibility() { const allCells = [walls, dots, energizers]; for (let t = 0; t < allCells.length; t++) { for (let i = 0; i < allCells[t].length; i++) { const cell = allCells[t][i]; const row = parseInt(cell.dataset.row); const col = parseInt(cell.dataset.col); const distance = Math.max(Math.abs(row - gridPosition.row), Math.abs(col - gridPosition.col)); if (distance <= VISIBLE_RADIUS) { cell.style.opacity = '1'; cell.style.filter = 'none'; } else { const opacity = Math.max(0.1, 1 - (distance - VISIBLE_RADIUS) * 0.2); cell.style.opacity = opacity; cell.style.filter = 'brightness(0.5)'; } } } }
Формула подобрана так, что на границе видимости клетки ещё различимы, а дальше плавно исчезают. Создаёт эффект неизвестности — а вдруг там призрак?
Движение сделано через requestAnimationFrame — это стандартный способ для анимаций в браузере.
position.x += MOVE_SPEED * deltaTime; if (position.x >= targetX) { position.x = targetX; // дошли до цели } pacman.style.left = position.x + 'px';
А направление поворота задаётся через data-атрибут, а CSS уже доворачивает спрайт:
[data-direction="0"] { transform: scaleX(1) rotate(0deg); } // вправо [data-direction="1"] { transform: scaleX(-1) rotate(0deg); } // влево [data-direction="2"] { transform: rotate(-90deg); } // вверх [data-direction="3"] { transform: rotate(90deg); } // вниз
Это самая сложная часть. В оригинале у каждого призрака своя логика поведения. Я попытался её воспроизвести:
Blinky (красный) — просто преследует Пакмена.
Pinky (розовый) — целится на 4 клетки вперёд по направлению движения.
Inky (голубой) — использует позицию Blinky и направление Пакмена для сложных манёвров.
Clyde (оранжевый) — если далеко бежит к Пакмену, если близко убегает в свой угол.
Плюс есть режимы SCATTER (разбегание по углам) и CHASE (преследование), которые чередуются по таймеру:
const MODE_TIMINGS = [ { mode: 'scatter', duration: 7 }, { mode: 'chase', duration: 20 }, { mode: 'scatter', duration: 7 }, { mode: 'chase', duration: 20 }, { mode: 'scatter', duration: 5 }, { mode: 'chase', duration: 20 }, { mode: 'scatter', duration: 5 }, { mode: 'chase', duration: Infinity } ];
И когда Пакмен съедает энерджайзер, призраки пугаются, синеют и начинают убегать — тогда их можно съесть за дополнительные очки.
Сделал два варианта: для компьютера (клавиши WASD и стрелки) и для телефонов (виртуальный джойстик). Маппинг простой:
const keyMap = { 'w': 2, 's': 3, 'a': 1, 'd': 0, 'arrowup': 2, 'arrowdown': 3, 'arrowleft': 1, 'arrowright': 0 };
Джойстик — это крестовина, при нажатии на кнопки меняется положение центрального кружка и направление Пакмена.

В результате разработки я сделал версию Pac-Man — проект, в который можно играть прямо в браузере.
Игра доступна онлайн — вы можете испытать её сами.
Начало игры — Пакмен в левом углу, вокруг знакомый лабиринт, но края теряются во тьме. Призраки появляются из своих домиков и начинают охоту.
Проект пока в разработке, и я хочу сделать его лучше. Исходный код опубликован на GitHub — забирайте, экспериментируйте, делайте свои версии.
Сейчас проект уже приобрёл очертания, однако много чего ещё нет, например: условия победы или хотя бы появления точек заново для бесконечного режима: лабиринт, точки, призраки, туман. Механика работает, Пакмен бегает, призраки пугаются. Но я думаю, что после пятого уровня становится немного грустно — а что дальше? Бесконечно собирать точки, пока не поймают? В оригинале это работало из-за того, что уровни просто повторялись с повышением скорости. Но хочется чего-то большего.
Может, сделать так, чтобы с каждым уровнем лабиринт менялся сам? Или добавлять новые типы врагов — например, призраков, которые не боятся энерджайзеров?
Идей пока не хватает, поэтому буду рад, если подкинете что-то в комментариях.
Если заметили баги или есть мысли, как сделать игру интереснее — пишите. Лучшие предложения точно реализую в следующих версиях. А если идея с машинками вместо призраков из «Пикселей» зайдёт — сделаю дополнительную пасхалку.
© 2026 ООО «МТ ФИНАНС»