Эта статья представляет собой фрагмент моей книги «Bug Voyage: A Tour of Classic Game Glitches». В книге также содержится информация о генерировании псевдослучайных чисел, выполнении низкоуровневых вычислений с двоичными и десятеричными числами, а также о том, как вызвать сбой в любом автомате Galaga, даже не опуская туда монеты.

Если рядом с вами есть аркадный автомат Pac-Man, Ms. Pac-Man или что-то подобное, то вам повезло, сегодня они в дефиците. Даже очень распространённые в прошлом автоматы «20 Year Reunion», в которых установлены вместе Ms. Pac-Man и Galaga, сейчас встречаются не так часто.

Но чтобы понять, о чём будет идти речь, достаточно загрузить видео с YouTube про одну из этих игр и посмотреть его буквально одну минуту:


Вы заметили. как плавно перемещаются Pac-Man и призраки по лабиринту? Они скользят так уверенно и чётко.

Эта плавность, как мы увидим, является иллюзией, и это ещё не всё. Вот ещё одно видео с YouTube:


Оно загружено Джейми Питтмэном (Jamey Pittman), автором статьи Досье на Pac-Man, ставшей источником значительной части информации о Pac-Man для моей книги. Видео немного перемотано, чтобы сэкономить вам время. Посмотрите его. В особенности следите за Pac-Man и красным призраком (в руководстве написано, что его зовут Blinky). Заметьте, что происходит примерно на сороковой секунде!

Видели? Pac-Man без проблем прошёл сквозь красного призрака! Как это произошло? Можно ли добиться того, чтобы это происходило постоянно?

Успокойтесь, сейчас я всё объясню, и да, это постоянное поведение. Если точно выполнить инструкции Питтмэна на первом уровне, такое будет происходить всегда.


Pac-Man

Что такое «спрайт»?


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

Но раньше значение термина было иным: им обозначали независимо двигающийся графический объект, который можно было расположить в любом месте экрана, или поверх остальной части графики, называемой фоном, или под ней. Спрайту задаются координаты X и Y, изображение и его цвет. Часто их использовали для игровых персонажей, но также применяли и в качестве дополнений к фону и для других целей.

Большинство систем поддерживало несколько или (в случае Galaga) множество спрайтов. У них были и другие названия: Atari сначала называла их «графикой снарядов игроков» (Player-Missile Graphics), а в ранней документации Commodore они обозначались как «блоки подвижных объектов» (M.O.B., Movable Object Blocks). Однако постепенно почти все стали называть их спрайтами.

Оборудование аркадного автомата Pac-Man поддерживает спрайтовую графику. Оно может отображать на экране до восьми спрайтов одновременно, и это без использования трюков со строками развёртки. Один из спрайтов — изображение самого Pac-Man, плюс ещё четыре используются призраками. Когда Pac-Man съедает призрака, его глаза, возвращающиеся домой, используют спрайт призрака.

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

Точки в игре Pac-Man — это тайлы (плитки) фона, стираемые, когда Pac-Man их съедает. Мерцание «энерджайзеров» (Energizer), придающих Pac-Man силу, выполняется окрашиванием этих ячеек в чёрный цвет, а затем в белый через каждые несколько кадров. Но эти объекты не двигаются, их можно только удалить или заменить.

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

Ну да, это интересно. Но что с того?

Основы мира Pac-Man


В детстве я писал небольшие игры на Microsoft BASIC для своего Commodore 64. Эта реализация BASIC имела проблемы. Программы выполнялись медленно и почти не использовали потрясающие для своего времени звуковые и графические ресурсы компьютера. Если вы хотели сделать что-нибудь с графикой и звуком, надо было изучить загадочные технические команды прямого доступа к памяти, называвшиеся POKE, или учиться писать в машинном коде.

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

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

Наверно, вы уже догадались, к чему я веду. Потому что именно так и была запрограммирована игра Pac-Man.

В действительности и Pac-Man, и призраки имели по два положения. Это положение спрайтовой графики, плавно перемещающейся по экрану, которое видит игрок. Такую информацию дают игроку, когда он играет в игру, но это всего лишь тень, иллюзия. Если вы хотите разобраться, как на самом деле работает Pac-Man, то нужно смотреть глубже.

«За кулисами» игры программа Pac-Man также учитывает, какие ячейки персонажей занимают Pac-Man и призраки. Следы этих координат на экране отсутствуют. Подозреваю, что на ранних этапах разработки Pac-Man, когда проводились эксперименты над геймплеем, разработчики могли отрисовывать тайлы непосредственно на экране. Джейми Питтмэн обнаружил, что эти координаты используются для искусственного интеллекта всех призраков, и они также используются для распознавания всех столкновений в игре.

Чтобы поддерживать эту иллюзию, игре приходится идти на ухищрения. Она отслеживает, насколько далеко Pac-Man и призраки переместились от их текущей ячейки на подпискельном уровне, и переключает их в новое положение, когда они отдалились достаточно далеко. Немного более быстрый объект будет иметь скорость, заставляющую менять ячейки немного чаще.

Эти элементы — координаты сетки, отслеживание между ячейками и положение спрайта на экране — создают иллюзию плавного перемещения. Но с точки зрения игры движение выполняется точно так же, как в моём случае, когда я программировал ячеечную графику персонажей на Commodore 64.

Расплата


Теперь у нас есть вся информация, необходимая для понимания того, как Pac-Man может проходить сквозь призраков.

Столкновения Pac-Man распознаются сравнением его координат сетки с координатами призраков. Если они одинаковы, то происходит столкновение и один съедает другого. Если они отличаются, то столкновение отсутствует. Вот и всё, ни больше, ни меньше.

Можно увидеть, что причина такого решения заключается в скорости распознавания столкновений в циклах процессора. Каждый кадр он сравнивает числа X и Y персонажа Pac-Man с числами каждого из четырёх призраков. Благодаря этому ему не нужно заботиться о расстояниях и рискованных ситуациях. Столкновениями считаются точные совпадения координат в системе сетки.


Эта сетка (примерно) соответствует системе координат тайлов, представляющей подлинные положения игровых персонажей. Распознавание столкновений использует эту сетку. Игра регистрирует столкновение только тогда, когда координаты тайлов обоих персонажей совпадают. Это значит, что они должны занимать одну ячейку сетки.

Проблема возникает, когда положения Pac-Man и призрака, движущихся друг к другу, переключаются на следующую ячейку в одном и том же кадре. Проверка столкновений выполняется после того, как все объекты переместились в текущем кадре. Если Pac-Man переходит в ячейку Blinky, а Blinky переходит в предыдущую ячейку Pac-Man в том же кадре, то возникает ошибка при распознавании столкновений. Они поменялись местами!

Поскольку это единственный уровень реальности, который действительно что-то значит в игре, то видимое игроком не важно. Pac-Man и призрак просто проходят насквозь, «расходятся, как в море корабли».

Искусственный интеллект (AI) в игре имеет детерминированную природу, поэтому можно выявить шаблон для повторения поведения. Несмотря на то, что время для проявления ошибки с прохождением насквозь должно быть точным до кадра, игроку не обязательно быть точным до кадра, если он следует правилам выполнения шаблонов движения Pac-Man. Именно так было записано видео Джейми Питтмэна.

Я привёл такое подробное описание, чтобы подчеркнуть важный факт. Очень легко воспринимать объекты в игре как реальные. Pac-Man — это такой объект на экране, призраки — тоже объекты, как и космический корабль, Марио, Соник, Солид Снейк, солдат из Call of Duty. Все они объекты. Но это иллюзия.

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

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

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

Дополнительная информация


Вставьте монетку в аркадный автомат «20 Year Reunion» и джойстиком первого игрока введите: вверх, вверх, вверх, вниз, вниз, вниз, влево, вправо, влево, вправо, влево. Если призрак на экране Game Select станет розовым и вы услышите звук, то всё сделано правильно. Теперь, если вы выберете игру Ms. Pac-Man, то вместо неё будете играть в оригинальную Pac-Man.

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

В этом отношении наиболее примечательна консоль Atari VCS/2600, потому что бoльшая часть системной графики там создавалась с помощью трюков со строками развёртки. Подробнее об этих техниках можно прочитать в книге Racing The Beam.

Источники:
Досье на Pac-Man: http://www.gamasutra.com/view/feature/3938/the_pacman_dossier.php?print=1
YouTube-канал Джейми Питтмэна: https://www.youtube.com/user/jameypittman/videos
Поделиться с друзьями
-->

Комментарии (12)


  1. saboteur_kiev
    13.04.2017 11:59

    Вот именно такие штуки называются фичами, а не багами!


    1. kosmos89
      13.04.2017 13:38
      +1

      Это known issue.


      1. AllexIn
        13.04.2017 22:13

        глитчинг


  1. rstepanov
    13.04.2017 12:12
    +18

    Сколько воды! Суть можно было бы изложить в 1 абзаце.


    1. dmitry_ch
      14.04.2017 09:02

      И одной картинке, к нему — для понятности.


    1. trapwalker
      14.04.2017 11:31

      Согласен, но для наглядности вам стоило эти два абзаца написать, сударь, прямо здесь. Это был бы шах и мат.


      1. rstepanov
        14.04.2017 11:46
        +1

        Предпочитаю работать за деньги.


  1. Noa69
    13.04.2017 12:37
    +3

    В современных играх есть нечто подобное: хитбокс не всегда точно совпадает с видимыми границами объекта


    1. rkfg
      13.04.2017 12:59

      В современных играх термин «хитбокс» вообще несколько неверно использовать, вроде, в Doom 3 впервые заменили именно бокс на что-то более сложное, помню, возможность пустить ракету между ног большого монстра и не задеть его подавалась как технологический прорыв, и так оно и было. Например, в Quake 3 использовались AABB (Axis-Aligned Bounding Boxes), грани которых параллельны глобальным осям. Хотя при этом можно было попасть в «пустоту» около персонажа или между его ног и тем не менее нанести ему повреждения, точность попадания не зависела от выбранной модельки (поэтому часто модель противника принудительно заменяли на крупного и заметного Tank'а, покрашенного в кислотные тона).


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


  1. MotttoR
    13.04.2017 13:34
    -7

    я дико извиняюсь за оффтоп!
    последнее время такая беда с ютубом (и с гуглосервисами вообще), если в домене .com, написать с .ru и всё в порядке.

    image


  1. Sadler
    13.04.2017 13:42

    Я когда-то в kde-шной реализации pacman'а (kapman) вполне успешно ходил сквозь стены. Никаких хаков, просто правильная последовательность нажатий.


  1. SilverDrakon
    14.04.2017 16:47

    У меня был Commodore 64, были какие-то игры, загружаемые с магнитофона, потом появился дисковод к нему, с 5'' дискет было гораздо удобнее. Изучил бейсик (я тогда учился в школе, это был конец 80-х), начал программировать собственные игры. И, да, со спрайтами, с командами PEEK и POKE (без них там никуда, не было никаких специальных команд работы с графикой). Даже удалось его «русифицировать», то есть нарисовать русские буквы и научить их вводить/выводить. Эх, были времена… даже на ассемблере на нём немного удалось попрограммировать, были некоторые подпрограммы, которые работали гораздо шустрее бейсика (но это надо было написать на бумажке программу на ассемблере, потом перевести её в коды, эти коды забить в память и потом запустить исполнение с нужной ячейки памяти, а потом чесать репу, почему не работает. Никаких редакторов кода, компиляторов и т.п.)