Подготовка ресурсов для игр
Alone Coder
Представьте,что вы написали почти гото─
вую игру, и тут выясняется, что в ней не
хватает одной анимации персонажа.
При традиционном (для Спектрума 90-х
годов) методе разработки вам придётся от─
дельно сконвертировать фазы этой анимации,
а потом приклеить их к существующим - воз─
можно, нарушив нумерацию спрайтов, то есть
всё придётся заново тестировать.
Представьте,что игра уже совсем готова,
но в процессе тестирования в некоторых ка─
ртах обнаружены косяки. При традиционном
способе вам придётся сконвертировать эти
карты и заново перепаковать диск с игрой,
из-за чего, возможно, поедут расположения
файлов - и опять полное тестирование.
Или другая типичная ситуация - спрайты
рисуете НЕ ВЫ, карты рисуете НЕ ВЫ, рисуют
это отдельные художники и левелдизайнеры,
и они хотят увидеть результат своей работы
в рабочей версии игры без вашей помощи.
Как быть?
Все эти проблемы решает автоматическая
сборка.
Автоматическая сборка
Сделаем оговорку, что некоторые авторы
спектрумовских игр отлаживают игры в снап─
шотах, а при сборке финальной версии (если
до неё доходит - ведь психологически игра
уже готова,и можно на покой) им приходится
заново отлаживать игру уже с загрузчиком.
Не надо так. Дальше в этой статье мы рас─
сматриваем с самого начала релизную сборку
игры. А отладочные функции? Их можно вклю─
чать и выключать условной компиляцией.
"Релизная сборка" означает,что игра ле─
гко может быть выпущена в любой момент, а
если не выпущена одним автором, то легко
может быть поднята из архивов другим (сра─
вните с "мёртвыми" исходниками на сайте
opensourcezx, которые уже никто не знает,
как собрать). Кроме того, можно легко и
непринуждённо делать багфиксы, версии на
всех языках и для всех форматов (tap, trd,
SD-карта...),хоть даже все одновременно по
одной кнопке.
Сборка - это последовательность дейст─
вий. И действия эти надо делать не руками,
а командами в батнике.Какие это могут быть
команды?
- компиляция ассемблерного кода со вхо─
дящими инклюдами (например, ассемблером
SjASMPlus ).В игре не обязательно один не─
зависимый кусок кода - бывает интро,аутро,
меню...
- упаковка кодового блока (например,ути─
литой mhmt )
- конверсия картинки во внутренний фор─
мат (например,под экран ATM-Turbo утилитой
convega - см. nedoos/src/games/barbaria/ )
- вытаскивание спрайтов во внутренний
формат (например, утилитой nedores )
- конверсия карт, скриптов и т.п.
- создание образа диска/ленты/SD-карты,
копирование файлов туда (например, утили─
тами trdtool, nedotrd, dmimg, bin2tap )
Как привязать спрайты к коду
Есть две типичные ситуации: а) блок
спрайтов содержит спрайты одного размера,с
доступом по номеру(таких блоков может быть
много); б) блок спрайтов содержит спрайты
разного размера с доступом по имени.
Несмотря на то,что первый вариант иног─
да выигрывает по размеру, я рекомендую ис─
пользовать второй.Дело в том,что в номерах
спрайтов очень легко запутаться, особенно
если вы (или продолжатель вашего проекта)
будете возвращаться к игре через долгое
время.
Имея доступ по имени, легко описать
структуры с анимацией. Идеально, конечно,
было бы анимировать спрайты в программах,
которые для этого предназначены (например,
Aseprite или Pixelorama ),но утилиты импо─
рта из них ещё не написаны. А старые спек─
трумовские редакторы спрайтов не поддержи─
вают слои, просвет анимации и цвет на точ─
ку. Поэтому для перспективных игр пока что
приходится вытаскивать спрайты из bmp.
К счастью, для вытаскивания из bmp есть
обкатанная утилита nedores (в составе
NedoOS ),которую несложно расширять новыми
форматами.
Что делает nedores?
Она открывает файл bmp (17-цветный -
для прозрачности при цвете на точку) из
первого параметра, скрипт-описатель спрай─
тов из второго параметра и имя выходного
ассемблерного файла из третьего параметра.
Скрипт-описатель выглядит, например, так:
;x,y,wid,hgt,defaultcolor (0..15 that will
;be used as ink in empty chr$)
;6912: color 0 in bmp is for mask
;16c: color 16 in bmp is for mask
;formats:
;B: colour tiles: wid, hgt, data
;s: b/w sprites:wid8,hgt,(antimsk,antipix)
;w: b/w sprites: antipixelsw, antimaskw...
;W: b/w image by columns
;T: colour tilepic 28xN (size 0xN00 bytes)
;x: 16c spr: wid/2,hgt,(column:and,or..),
;(0x4000-((hgt-1)*40))...,prsprqwid
;L: 16c 16x16 tiles (N of tiles in
;"defaultcolor"):
;N of tile for each square
;i: 16c image
;P: DDp palette
human0=x,0,0,16,16
human0step=x,16,0,16,16
human1=x,32,0,16,16
human1step=x,48,0,16,16
...
bulletright=x,16,16,8,8
bulletleft=x,24,16,8,8
Здесь для каждого вырезаемого спрайта
указано имя, формат ("x" - формат спрайта
для sprexamp/prspr.asm ), расположение на
картинке и размер. prspr по умолчанию под─
держивает любую чётную ширину и высоты
8, 16, 24, 32, но при желании этот список
нетрудно изменить или дополнить.
В результате выполнения nedores возни─
кает такой ассемблерный файл:
human0=$+4 ;ld iy,human0:call prspr
db 0x08 ;ширина (в двойных пикселях)
db 0x10 ;высота
db 0xff,0x00 ;маска,графика
db 0xff,0x00 ;...
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0x47,0x00
db 0x47,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
dw 0x3da8 ;смещ-е до след.столбца экрана
db 0xff,0x00 ;маска,графика
db 0xff,0x00 ;...
db 0xff,0x00
db 0xff,0x00
db 0x47,0x00
db 0x00,0x08
db 0x00,0x09
db 0x00,0x09
db 0x00,0x08
db 0x47,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
dw 0x3da8 ;смещ-е до след.столбца экрана
...
db 0xff,0x00 ;маска,графика
db 0xff,0x00 ;...
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xb8,0x00
db 0xb8,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
dw 0xffff ;невозможное смещение =признак
;конца спрайта
dw prsprqwid ;туда будем выходить
human0step=$+4 ;ld iy,этаметка:call prspr
db 0x08 ;ширина (в двойных пикселях)
db 0x10 ;высота
db 0xff,0x00 ;маска,графика
db 0xff,0x00 ;...
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0x47,0x00
db 0x47,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
db 0xff,0x00
dw 0x3da8 ;смещ-е до след.столбца экрана
...
Для режима "цвет на точку" можно также
импортировать картинку по столбцам ( "i" -
применимо и для шрифтов) и набор тайлов
16x16 с описанием, какой номер где стоит
на картинке (примеры см. в src/games/br/
images/W1LAND.dat и в src/games/sprexamp/
tiles.dat ).
Также nedores умеет импортировать чёр─
но-белые спрайты "s" и "w" и цветные тайлы
"T" для режима 6912 (используются в
nedolang/_sdk/sprite.i и в Dizzy SE ). Мо─
жно импортировать и отдельные цветные тай─
лы для этого режима ( "B" ).Можно импорти─
ровать ч/б картинку по столбцам ( "W" ).
Поскольку на выходе nedores получается
исходник,его можно компилировать под любой
адрес и при этом иметь доступ к спрайтам
по имени. Вот как описывается типичная
анимация:
heroanim_runright
dw HERORUNRIGHT0 ;спрайт фазы
db 4 ;задержка этой фазы
dw HERORUNRIGHT1 ;спрайт след.фазы
db 4 ;задержка этой фазы
dw HERORUNRIGHT2 ;спрайт след.фазы
db 4 ;задержка этой фазы
dw heroanim_runright ;адрес след.
;анимации
;(после окончания текущей)
Но если спрайты не помещаются в страни─
цу, то задача усложняется... В примере
sprexamp вместо адресов спрайтов всё-таки
используются номера (а точнее,адреса адре─
сов),которые пришлось там же (sprdata.asm)
описать как константы. Но никто не застав─
ляет делать именно так.Можно написать ути─
литу автоматической генерации номеров
спрайтов из их адресов, или можно при ком─
пиляции игры инклюдить страницы спрайтов и
самому следить за номерами страниц.
Разумеется,номера страниц спрайтов дол─
жны быть логическими, а не теми, которые
пишутся в порт, ведь компьютеры,на которых
будет запускаться ваша игра, могут быть
разными, а под NedoOS игра вообще может
быть загружена в случайные страницы.
Работа с картами
Некоторые игры требуют собственных ре─
дакторов карт (например,если карта строит─
ся из стен, как в Wolfenstein 2004, или из
объектов, как в Ball Quest и Dizzy ). Но
для большинства игр достаточно прямоуголь─
ной сетки и редактора MapWin. Этот редак─
тор позволяет написать собственный скрипт
сохранения в нужном формате, причём этот
скрипт может выгрузить более одного файла
(например, координаты врагов отдельно).
MapWin также поддерживает многослойные ка─
рты (расположение предметов,входов,выходов
логично делать на отдельном слое) и авто─
матическое разрезание картинок на тайлы.
Примеры работы с MapWin можно увидеть в
Unreal Project и sprexamp в NedoOS.
Иногда левелдизайнеру удобнее рисовать
карту в самой игре (так было в Space
Monsters meet THE HARDY ). В этом случае
лучше отказаться от внешнего редактора,
чтобы не делать конверторы в обе стороны.
А дальше есть два подхода:
1. Если сама игра умеет сохранять карты,
то нужно только написать в батнике сборки
чтение готового файла из образа в директо─
рию с исходниками.
2. Если игра не умеет сохранять, то надо
дать инструкцию левелдизайнеру, как делать
снапшот, а в отдельном батнике прописать
вызов утилиты, которая будет доставать ка─
рту из снапшота. Хорошо, если для этого
достаточно обкусить файл (например, утили─
той nedopad ).Можно прописать этот вызов и
в батнике сборки, но тогда снапшот станет
первоисточником карты, что негигиенично.
Работа с музыкой и звуками
Особенность музыки и звуков та же,что у
карт - редакторы ( Vortex Tracker , AY FX
Editor ) выгружают их уже в виде,пригодном
для использования в коде. Наша задача в
батнике - просто скомпилировать плейер с
этими файлами или учесть в загрузчике,
чтобы они грузились отдельно. Музыканту
достаточно знать, под какими именами их
надо сохранять.
Если же плейер нестандартный,а его ком─
пилятор не работает в командной строке, то
придётся пересобирать музыку в бинарники
вручную каждый раз, когда музыка измени─
лась. Это неудобно, и надеюсь, что авторы
компиляторов в будущем учтут эту проблему
и решат её, например, так:
- По умолчанию есть компилятор, который
просто запускается в командной строке с
именем файла.
- Если компилятор требует ручных настро─
ек,то можно сделать его интерфейс отдельно
от самого компилятора и передавать параме─
тры в командной строке с возможностью ко─
пирования к батник.
- Если компилятор генерирует ассемблер─
ный исходник,то части этого исходника дол─
жны инклюдиться,чтобы пользователь мог сам
подправить адрес, вход, выход и положение
модуля относительно плейера.
Работа со скриптами
Обычно удобнее всего редактировать
скрипты в текстовом виде. Чтобы не писать
для них отдельный парсер,язык скриптов лу─
чше взять готовый - ассемблер или Си. Они
позволяют с помощью макросов определить
нужные слова-команды, а если особых команд
нет, то можно писать просто через DB и DW.
Можно писать скрипты и на Nedolang, но по─
скольку там нет макросов, то скриптование
ограничено написанием однотипных структур
данных.
Другой вариант - если сама игра будет
искать управляющие последовательности в
тексте. Такая игра будет работать медлен─
нее. Если игра в основном строится на диа─
логах, то это терпимо. Нетерпимо, если под
эти диалоги в конце концов не хватит места
в памяти. Тогда придётся разрабатывать от─
дельную утилиту сжатия, а для этого отка─
заться от записи вида:
text1
db "text 1",0
text2
db "text 2",0
и перейти на таблицу адресов сообщений,
которую эта утилита тоже будет генериро─
вать. Хорошо, если она сгенерирует её в
виде ассемблерного текста:
text1=_+0
text2=_+5
Тогда не нужно место под таблицу, можно
инклюдить этот ассемблерный текст и ссы─
латься прямо на метки text1 и text2.
Понятно,что для этого структуры со ссы─
лками не должны паковаться в том же прохо─
де, что и тексты.
Тема скриптов очень обширна, вариантов
множество, некоторые мы уже обсуждали в
прошлых номерах Info Guide. Но непреодоли─
мых проблем для автоматизации нет.
* * *
Обратите внимание, что автоматическая
сборка не обязательно подразумевает Win─
dows. Её можно применять и на Спектруме,
например, в NedoOS. Даже в ALASM я долгое
время использовал автоматическую сборку из
двух шагов (компиляция и упаковка), это
сильно облегчало жизнь при написании сис─
темных программ. Там можно было ещё делать
произвольные вызовы во время компиляции
(директива RUN ) - например,для чтения си─
стемного времени. Но более сложные после─
довательности действий ALASM не поддержи─
вает.
Я писал на ALASM 18 лет подряд и до сих
пор иногда к нему возвращаюсь. Но всё реже
и реже.
Когда вы переходите на автоматическую
сборку,сначала она кажется сложной или ме─
дленной (ведь результат не возникает сразу
в памяти!). Но стоит вам как следует наст─
роить среду разработки и батники, и воз─
врат к ручной сборке кажется бессмысленным
и чреватым ошибками. Особенно вы её оцени─
те, если в проекте уже несколько человек
или планируется долговременная поддержка.
Other articles: