[Перевод] Хитрости разработки Street Fighter II
Часть 1: бумажный след
В конце 90-х в мир аркадных автоматов пришла Capcom. Эта компания из Осаки, казалось, создавала один хит за другим: Ghouls’n Ghosts (1988 год), Final Fight (1989 год), Street Fighter II (1991 год), не говоря уже о множестве других превосходных игр.
В эту эпоху невозможно было зайти в зал аркадных игр и не встретить множество автоматов Capcom, что являлось доказательством их популярности и среди игроков, и среди владельцев.
Последние шесть месяцев я тратил своё свободное время на изучение историй успеха Capcom и, в частности, истории происхождения Street Fighter II. Инженерные решения, ставшие основой CPS-1 были потрясающими, но не менее интересной мне показалась история о том, как разработчики планировали заполненность ROM при помощи бумаги и ножниц.
CP-System 101
Появившаяся в 1988 году CPS-1 (в то время называвшаяся CP-System) стала унифицированной аркадной платформой Capcom. Среди множества её инноваций был и мощный конвейер рендеринга графики.
Хотя концепция слоёв по-прежнему использовалась, в CPS-1 отказались от ограничения в виде прямоугольных спрайтов. Слой OBJ создавался из элементов 16×16, называемых «тайлами». В Street Fighter II из тайлов создаются позы персонажей. Такой подход обеспечивал большую степень свободы для художников, которые могли проектировать «объекты» произвольных размеров и форм.
Победная поза Рю (29 тайлов), поза Tiger Uppercut Сагата (30 тайлов), Поза прыжка Хонды (45 тайлов), боевая поза Чун-Ли (25 тайлов)
За исключением нескольких простейших операций типа горизонтального и вертикального переворота CPS-1 не может изменять файлы. У неё нет функций поворота или масштабирования. Выделяло эту машину на фоне остальных исключительно возможность манипулирования большим объёмом спрайтов за один кадр (сообщается, что примерно 256).
В то время такое количество движения на экране было настоящим высшим пилотажем. Успеху игры в значительной степени способствовал «вау-фактор». В играх наподобие «The Punisher» количество тайлов в позах финального босса Кингпина составляло до 80 штук.
Экран «The Punisher» мог быть почти полностью заполнен спрайтами (источник: rq87.flyingomelette.com).
Планирование объёма, занятого на ROM
Возможности CPS-1 стали благословением для художников, но оказались проблемой для менеджеров проектов. В эпоху, когда чипы ROM были очень дорогими, разработчики заранее планировали объём ROM, который нельзя было превышать.
До CPS-1 оставаться в рамках ограничений позволяло простое деление. Количество спрайтов, которое позволялось создавать команде художников, равнялось размеру ROM, поделённому на размер прямоугольного спрайта. Но из-за свободного формата возникла проблема планирования.
Система листов
Решением стали листы бумаги и ножницы.
Чтобы оптимально использовать имеющийся объём, мы записали на доску ёмкость ROM, а затем вырезали и наклеили на неё пиксельных персонажей.Если на доске оставалось место, значит, в ROM оставалась свободная ёмкость. Поэтому дальше мы начали заполнять пробелы как пазл.
У нас случился интересный момент — мы оставили создание концовки на потом, и ко времени, когда добрались до неё, свободная ёмкость закончилась. Мы гадали, что же делать, но потом обнаружили доску, которая просто завалилась под стол.
Мы назвали это «чудом с памятью».
— Акира Ниситани, интервью о разработке SF2
Пустой лист
Так как в CP-S используется 16 индексированных цветов (4 бита на пиксель), лист из тайлов 16×16 занимает 16×16x16×16 / 2 = 32 КиБ. Например, для игры Street Fighter II: World Warrior команда разработчиков выделила под спрайты 4,6 МиБ из 6 МиБ ROM, а поэтому распечатала 144 бумажных листа.
Бумажная археология
Эта система оказалась золотой возможностью для археолога ПО. Среди прочего можно было увидеть, какие фрагменты были добавлены позже (они встраивались в оставшееся место, а поэтому выглядели менее изящно).
К сожалению, мне удалось найти только два листа. Дхалсима (Dhalsim) я обнаружил в статье «Final Fight Developer’s Interview» [1], а Рю (Ryu) — в книге «How To Make Capcom Fighting Characters» [2]
Лист 0×3300
Лист 0×4500
Обратите внимание на систему адресации файлов в левом верхнем углу каждого листа (Дхалсим 0x3300
и Рю 0x4500
). Первые два шестнадцатеричных символа дают значение [0–255], являющееся ID листа, а два других — это ID тайла на этом листе.
Также обратите внимание, что тайлы на листах не квадратные, а прямоугольные. CP-System использует разрешение 384×224, соотношение сторон которого отличается от соотношения 4:3 ЭЛТ-дисплея. Если бы дизайнеры рисовали по квадратам, то результат выглядел бы на экране сжатым. Рисуя по прямоугольникам, они, по сути, выполнили обратное растягивание графических ресурсов, чтобы тайлы отображались так, как были нарисованы. Эта система неквадратных пикселей стала кошмаром для команды художников.
Работая над Forgotten Worlds, я заметил проблему с соотношением сторон. «Пиксели не квадратные!», — сказал я своему начальнику.«Это невозможно, я приказал, чтобы они были квадратными!», — ответил он и сразу же позвонил в отдел оборудования.
«Пиксели квадратные!», — сказал он.
Позже я снова запротестовал, на что начальник ответил, что это была ошибка в расчётах.
— Акира Ясуда, продюсер SF2 [3]
Ужасно разочаровывает то, что удалось найти только два листа, но мы можем воссоздать их при помощи сохранённого на ROM образа. Благодаря mame и sf2platinium, опубликовавшим формат GFX-ROM, был написан инструмент, автоматизирующий процесс. После воссоздания всех листов настало время анализа и гипотез.
Изучение листов
CPS1 работает с четырьмя листами. Слой OBJ игры Street Fighter II составлен из 144 листов общим размером 4,6 МиБ. Оставшиеся 1,4 МиБ использованы для слоёв фона и переднего плана, называвшихся SCROL1 (16 листов), SCROL2 (8 листов) и SCROL3 (23 листа).
Самые объёмные по байтам персонажи — это Зангиеф (19), за которым идут Хонда (15), Дхалсим (14, он худой, но сильно растягивается!), Бланка (15), Рю (13,5), Гайл (11), Чун-Ли (10), Диктатор (9, его плащ занимает целый лист!), Сагат (6), Боксёр (6), Коготь (6) и Кен (3).
На первом листе представлен главный герой Рю, и это неудивительно.
Обратите внимание, что верхняя часть волос Рю 0x69
/0x6A
была помещена в 0x6F
/0x9F
, чтобы не путать разбивку. Непонятно, почему смещены волосы левой верхней позы. Возможно, дело в том, что адрес 0x0000
GFX ROM невозможно использовать? Анализ других игр тоже показал, что тайл 0x0000
никогда не использовался.
Кен состоит из заплаток
Посмотрев на круговую диаграмму, мы видим, что персонаж Кен занимает невозможно малое количество листов, всего три.
Палитра Рю
Палитра Кена
Так получилось, потому что Кен — это заплатки поверх тайлов Рю. Палитра Рю специально спроектирована так, чтобы быть совместимой по оттенку кожи с Кеном. Отличаются только цвета одежды и лиц.
Фрагментарность заметна на листе 0x0100
, где победная поза Рю 0x76
находится с заплаткой Кена размером 2×2 в 0x70
.
Победная поза Кена начинается с позы Рю. Палитра меняется и используются только отличающиеся тайлы. Обратите внимание, что белый цвет зубов Рю взять с его одежды. У Кена художникам пришлось использовать часть цвета кожи, потому что кимоно Кена красного цвета.
Поиск фрагментов
На листе 0x4700
(в предыдущем разделе) мы видим в 0xC0
портрет размером 2×2 человека, который не является бойцом. На самом деле, это фотография команды разработки. Они перечислены в титрах в конце игры. Обратите внимание, что ни точных фотографий, ни реальных имён там нет. Возможно, так сделано, чтобы разработчиков не хантили другие компании.
Любопытный факт: «NIN» — это псевдоним продюсера Capcom Акиры Ниситани. Он использовался во всех списках рекордов во всех играх, над которыми он работал, включая Forgotten Worlds, Final Fight и Street Fighter 2.
Экономить на всём
Похоже, разработчики испытывали такой дефицит ROM, что использовали симметрию частей поз. В листе 0x4E00
левая нога Сагата отсутствует в 0xBA
. Для её отрисовки CPS-1 использовала отзеркаленные по горизонтали тайлы правой ноги.
Различия в листе Дхалсима (0×3300)
Воссозданный лист Дхалсима совпадает почти идеально. Однако мы видим, что выделенная красным поза не попала в игру. Ею пожертвовали ради приёма Чун-Ли «Hundred Rending Legs», что может свидетельствовать о том, что его добавили позже. В 0x4C
мы видим фрагменты, выделенные Бланке.
Различия в листе Рю (0×4500)
Похожие различия мы видим и на листе Рю. Перед выпуском игры были удалены две позы (в 0xC2
и 0xCC
), чтобы уместить приём Чун-Ли «Spinning Bird Kick» (его тоже добавили в конце разработки?) и портреты команды для титров.
Как долго использовалась система листов?
Учитывая наличие в то время мощных рабочих станций наподобие X68000, мне всегда было любопытно, как долго использовалась система листов до того, как написали инструмент для сборки ресурсов GFX. Благодаря возможности изучения листов других игр это можно было приблизительно прикинуть.
Первым делом стоило посмотреть на все игры, созданные той же командой, начав с проектов, выпущенных до SF2, Forgotten World и Final Fight. Хотя у меня не было времени искать палитры и я использовал стандартные градации серого, всё равно можно чётко увидеть формы.
Листы Forgotten World (1988 год) и Final Fight (1989 год)
Неудивительно, что используется та же структура. Позже я проверил и другие игры, например, Street Fighter 2: Champion Edition и Street Fighter 2: Hyper Fighting. GFX минимально усовершенствовался [4], а структура листов осталась неизменной.
Листы Street Fighter 2: Champion Edition (1992 год) и Street Fighter 2: Hyper Fighting (1992 год)
Другие команды Capcom
В Capcom разными командами параллельно разрабатывалось множество игр. Посмотрев на работу других команд, отвечавших за Ghouls 'n Ghosts и Strider, я снова увидел тот же процесс.
Листы Ghouls 'n Ghosts (1988 год) и Strider (1989 год)
Игры, созданные не Capcom
Некоторые игры для CPS-1 были созданы не Capcom. Например, Pang-3 компании Mitchell Corporation. Тут тоже нет никаких изменений.
CPS-2 и Super Street Fighter 2
Похоже, система листов использовалась в большинстве, если не во всех играх для CPS-1. Изучать игры для CPS-2 было чуть сложнее, потому что Capcom добавила множество механизмов защиты. Хотя команды 68000 и команды Z-80 были зашифрованы, GFX ROM были просто перемешаны и их легко можно просмотреть.
В первой игре для CPS-2, Super Street Fighter 2 (1993 год) к имевшимся двенадцати персонажам были добавлены ещё четыре новых. Листы старых персонажей не изменились.
Листы Рю и Кэмми из Super Street Fighter 2 (1993 год)
Но если посмотреть на листы Кэмми (0x9000
), то видно, что структура создана не вручную. Похоже, вместо этого была использована система размещения, движущаяся сверху вниз и слева направо. Наверно, примерно в 1992 году Capcom начала использовать инструменты для создания новых GFX ROM в SSF2. Неизвестно, применялись ли рабочие станции x68000.
Street Fighter Alpha
Другие игры для CPS-2, Street Fighter Alpha (1995 год) и Street Fighter Alpha 3 (1998 год) тоже имеют такую же структуру, то есть применялся тот же инструмент. Все листы выглядят как пюре, в котором нет ни одного свободного тайла. С большой вероятностью, ни одна из игр для CPS-2 не использовала систему листов.
Просьба об интервью
Я предпринял множество попыток поговорить с разработчиками, работавшими над системами CPS-1/CPS-2. Но все они пока завершились провалом. Я хочу задокументировать и сохранить информацию о том, как программировали эти машины. Особенно любопытно мне то, как использовалась X68000. Если вы сами или ваши знакомые работали со всем этим, то напишите мне!
Ссылки
[1] Final Fight Developer’s Interview
[2] How To Make Capcom Fighting Characters
[3] Twitter-аккаунт Akiman
[4] Differences Between SF2 World Warrior and SF2 Champion Edition
Часть 2: невозможное вращение
Как мы узнали в предыдущей части, оборудование, на котором работал Street Fighter 2 — это тайловый движок, способный отражать тайл по вертикали или горизонтали и не имеющий возможности смешивания. Для игры наподобие Street Fighter II это было проблемой, потому что режим привлечения игроков содержал вращающийся логотип с отображением под ним просвечивающего текста «World Warrior».
Если вы видели автомат в 1991 году, то можете помнить, что эффект выглядел странно, но было трудно сказать, в чём дело, потому что логотип вращался очень быстро, а ЭЛТ-дисплей немного всё размазывал.
Воссозданный режим привлечения игроков «вращение и зум».
При помощи программы просмотра листов мы можем взглянуть на GFXROM. Использованные в логотипе тайлы можно найти в листе 0x8200
.
Как и ожидалось, мы видим две версии графики, маленькую и увеличенную. Но как их использовали?
MAME спешит на помощь
Благодаря современным технологиям мы можем замедлить анимацию. MAME может записывать попиксельно чёткую последовательность изображений в формате mng, чтобы мы могли изучить каждый кадр по отдельности.
$ mame sf2 -mngwrite sf2.mng
Внимательно изучив каждый кадр, мы можем определить следующее:
- Маленький логотип движется вниз, чтобы оставить достаточно места под большой.
- Логотип вращается дважды.
- После первого вращения маленький логотип заменяется большим.
- Тайлы не отражаются по горизонтали или вертикали. Их позиции просто вращаются вокруг центра логотипа.
- Просвечивание достигается отрисовкой текста через кадр.
- При достаточно быстром движении эффект визуально «приемлем».
Другие вращения и масштабирования в Street Fighter II
Если выиграть турнир, не проиграв ни в одном раунде, игрока награждают особой последовательностью экранов титров, где тоже происходит масштабирование и вращение. Снова с помощью MAME мы можем посмотреть на происходящее в замедленном движении.
Экран 1:
Здесь масштабирование выполняется «накладыванием» тайлов один поверх другого с постепенным раздвижением.
Экран 2:
Любопытный факт: обратите внимание, что спрайты бойцов возникают на один кадр после фона. Так получилось потому, что CPS-1 использует кадровый буфер спрайтов, откладывающий обновление слоя спрайтов на один кадр.
Экран 3:
Экран 4:
Эффект в Street Fighter 2: Champion Edition
Годом позже, в марте 1992 года, Capcom выпустила сильно улучшенную версию под названием «Champion Edition». По этому случаю режим привлечения игроков был переделан.
Логотип больше не вращается, и вместо этого имитирует уменьшение и увеличение масштаба.
Переход от маленького логотипа к большому происходит, когда все тайлы собраны в одной точке. Это гораздо более реалистично, чем эффект в SF2: WW.
Street Fighter 2 Hyper Fighting
Последняя игра, выпущенная на CPS-1 (после которой Capcom перешла на CPS-2) — это Street Fighter 2 Hyper-Fighting (декабрь 1992 года).
Режим привлечения игроков за исключением текста не особо изменился. От анимации текста полностью избавились и осталось только масштабирование логотипа.
Взгляд на другие платформы
Спустя год после выпуска на аркадных автоматах Capcom издала 15 июля 1992 года порт для Super Nintendo. Компания проделала отличную работу, ей удалось сохранить всех персонажей, движения и красивые графические эффекты, несмотря на то, что консоль имела гораздо меньшую ёмкость памяти и разрешение.
Как ни удивительно, но благодаря Mode 7 + HDMAA консоли SNES ей удалось отрендерить более красивый эффект вращения.
Для небольшого просвечивания был использован простой дизеринг с колебаниями.
И снова благодаря MAME мы можем просмотреть всю анимацию кадр за кадром.
$ mame snes -cart "sf2.zip" -mngwrite sf2snes.mng
Часть 3: Досадная опечатка
Одна из моих любимых историй о Street Fighter II — это рассказ Akiman о проблеме, обнаруженной незадолго до выпуска.
Всего за три дня до дедлайна я обнаружил нечто ужасное. Я сделал ошибку в подзаголовке «World Warrior», написав его «World Warrier».— Akiman, ведущий графический дизайнер SF2 (перевод Shmuplation)
Воссоздание проблемы. Ой!
Чтобы полностью понять проблему, нам нужно разобраться, как работает оборудование аркадного автомата. CPS-1 — это супермашина для отрисовки тайлов. Она может отрисовывать кучу тайлов, но не способна их изменять. Они берутся из GFX ROM в неизменном виде и отправляются на экран (хотя их можно отражать по горизонтали или вертикали).
GFX ROM и ROM с командами процессора 68000 прожигаются по отдельности. Описанная Akiman проблема заключалась в том, что GFX ROM уже был записан, но он всё ещё мог вносить изменения в команды.
Но как устранить ошибку, если графика уже останется неизменной?
Теперь я могу спокойно рассказывать эту историю, но на самом деле мы обнаружили только через много месяцев после того, как вся работа над спрайтами была завершена. Так как логотип уже был создан, я не мог просто изменить в нём букву.«Возможно, я смогу заставить её выглядеть как «o», — подумал я; начал пробовать накладывать разные другие спрайты, пока наконец она не стала похожа на «o». Какое облегчение!
— Akiman, ведущий графический дизайнер SF2 (перевод Shmuplation)
Всё дело в деталях
Это описание решения заставило меня поискать подробности. Как он превратил «e» в «o»? Так как у меня был инструмент извлечения листов, я поискал текст; логотип и опечатка нашлись на листе 0x7B00
.
Логотип отрисовывался при помощи 16 вызовов отрисовки, использующих тайлы 0xC8
, 0xC9
, 0xCA
, 0xCB
, 0xCC
, 0xCD
, 0xCE
, 0xCF
, 0xD8
, 0xD9
, 0xDA
, 0xDB
, 0xDC
, 0xDD
, 0xDE
и 0xDF
.
Akiman решил эту проблему, подойдя к делу практично. Он заметил, что в слове «World» есть слог «or», который должен поместиться вместо «ier». Поэтому от отбросил последние три тайла 0xDD
, 0xDE
и 0xDF
, заменив их на 0xCD
и 0xCE
.
Ситуация улучшилась, но таким образом он перенёс проблему в другое место, потому что позаимствованная правая палка «W» выглядела как «l», а не как«i». На логотипе теперь было написано «The World Warrlor».
На этом этапе ему нужно было найти способ разрезать верхнюю часть «l», чтобы она выглядела как точка буквы «i», но как это сделать, если 68000 не может выполнять запись в тайл?
Гайл спешит на помощь
Последним куском пазла стали икры ног Гайла. Если приглядеться к тайлу 0x96
, то можно заметить, что у него виден только один пиксель в левом нижнем углу.
Ранее я не упоминал кое-какую особенность: управление палитрами полностью находится под контролем 68000. Процессор может отправить команду отрисовки тайлов, использовав для этого любую нужную палитру.
Палитра Гайла
Палитра World Warrier
Зелёная палитра Гайла бесполезна, так как в логотипе используются синие цвета. Но если сравнить их, то можно заметить, что индекс 14
в палитре Гайла тёмно-зелёный, а в палитре логотипа — тёмно-синий.
Использование тайла 0x96
с палитрой логотипа позволяет процессору 68000 создать систему (очень затратную) в которой 255 пикселей тратятся на прозрачность, зато 256-й можно использовать в качестве карандаша.
Этот тайл-карандаш используется для отправки трёх команд отрисовки с координатами, накладывающимися на «l». По сути, это создаёт линию, перерезающую верхнюю часть и превращающую её в точку буквы «i».
Так что если вы всё это время задавались вопросом, почему «i» в слове «Warrior» выглядит странно, то теперь знаете ответ.
Эпилог
Опечатку исправили в последующих версиях Street Fighter 2, где в наборе тайлов «World Warrior» появилось правильное сочетание «IOR».
Забавно, что их не использовали, потому что подзаголовок сменился с «World Warrior» на «Champion Edition», а потом на «Hyper-fighting».
Часть 4: точная анимация полосы здоровья
Проблема
Если вы прочитали предыдущие части, то вам совершенно ясно, что машина, на которой работал Street Fighter II, могла обрабатывать только тайлы, составленные из 16×16 пикселей. Помня об этом, посмотрите короткий фрагмент геймплея. Вы обратите внимание на нечто странное, невозможное.
«Полоска здоровья» противника анимирована плавно и попиксельно. Как такое возможно? Если бы разработчик работал с тремя тайлами (один для «края», один для «полного здоровья» и один для «пустого здоровья»), то полоски здоровья из двенадцати тайлов менялись бы только с инкрементом в 16 пикселей.
Такая реализация не только делает анимацию неуклюжей, но и создаёт ощущение неточности, представляющей механику игры в дурном свете. Нужно использовать систему получше.
Точное отслеживание здоровья
Изучение листов игры показывает, как программистам Capcom удалось заставить систему работать плавно. Тайлы полоски здоровья находятся в листе 0x81
.
Мы видим здесь не три, а двенадцать тайлов, что доказывает, что многие проблемы можно решить добавлением ОЗУ или места на накопителе.
Промежуточные состояния тайла заранее отрендерены в строке OxF0
. Эти дополнительные тайлы обеспечивают попиксельно точную анимацию полоски здоровья.