01 апреля 2021

Подготовка ресурсов для игр 
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:


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Similar articles:
pearls - column telling about the statements of famous people.
Inferno - Intro.

В этот день...   23 November