05 июля 2015

      Скриптование игры
     Строение скриптового движка игры
       на примере L7 script engine
SAM style, 2015 

  Ещё  в начале  2000-х, когда  я играл в
"Звёздное  наследие"на своём Скорпионе, я 
безнадёжно застрял, открывая нишу в пещере
острова. Вероятно, я просто был невнимате─
лен  и пропустил подсказку насчет кода, но
пришлось  лезть  в теневой отладчик, чтобы
преодолеть  это место. Там я обнаружил за─
нятную особеность - по крайней мере то ме─
сто в игре было выполнено в виде интерпре─
татора  некоего  байткода, в котором  были
описаны  меню, действия  при  выборе пунк─
тов...

   Тогда меня это заинтересовало,но не бо─
лее - игр в то время я ещё не писал.
   Однако потом начал,используя именно тот
подсмотренный  в "Звёздном наследии" приём
- по большей части  Anime Story и Nocturne
были  интерпретаторами  байткодовых скрип─
тов. Затем  я подался  в другую  сторону и
начал  развивать  другие скрипты, где были
описаны анимации. Подобные используются во
всех  частях  Viking Quest  и  частично  в
Karlos'е. 
   В начале 2014 года  я написал небольшой
тайловый  движок, поддерживающий  7  слоёв
графики - каждый  со своим набором тайлов,
с маской/без,с опциональным использованием
цвета.  Рабочим  названием  стало  7LT  (7
Layers of Tiles). Изначально он создавался 
для  другой игры, но идея быстро стухла, а
движок остался. Теперь настало время объе─
динить  всё, что  было  до этого - скрипты
игровой логики, скрипты анимации и новояв─
ленный  тайловый  движок. Это скопище кода
получило имя L7 script engine.

   Интерпретатор  скриптов  игровой логики
представляет  из  себя  обработчик некоего
набора команд,представленных 1-2 байтами с
параметрами. Одни команды изменяют поддер─
живаемые движком структуры,другие - отдают
команды  анимационной части движка, третьи
предназначены для ветвления и переходов по
каким-либо условиям. Т.к.движок наполнялся
для воспроизведения квеста/jRPG,то и набор
команд  и структур у него соответствующий.
Структуры  сгруппированы в таблицы, движку
передаются адреса этих таблиц.

   Движок  на  данный  момент поддерживает
следующие структуры:

 - NPC (non-player characters).Эти  эле─
менты имеют спрайты, анимации,с ними можно 
поговорить, отдать им что-нибудь. 
 - Активные элементы.Это  по  сути те же
NPC, но на них  можно воздействовать, если 
они это позволяют. 
 - Предметы.Могут находиться либо на ка─
рте, либо в сумке героя. 
 - Двери.Активируются, когда герой соби─
рается на них наступить, и переносят его в 
другое место карты. 
 - Зоны.Активируются, когда герой на них
наступает. В  отличие  от дверей, действие 
может быть любым. 
 - Магии.Применяются в битвах, расходуют
MP. Действие по применению - любое. 
 - Зелья.Имеют количество и длительность
действия. Само  действие - любое. По  сути 
зелья - это список налагаемых на героя эф─ 
фектов во время битвы. 
 - Снаряжение.На данный момент - 4 слота
(броня, щит, меч, амулет), до 8 наименова─ 
ний  в каждом. Броня и щит поглощают урон, 
меч наносит его, амулет оказывает задавае─ 
мый эффект. 
 - Таблица крафта. Из  2 предметов можно
создать третий. 
 - Таблица "говорить" -  с  кем  + адрес
скрипта. 
 - Таблица "отдать" -  что, кому + адрес
скрипта. 
 - Таблица "использовать" -  что + адрес
скрипта. 

   Многие  команды взаимодействуют с этими
структурами. Например,задают NPC анимацию,
ожидают её окончания, перемещают их в дру─
гие места,включают-отключают зоны и двери,
добавляют или убирают магию, зелья, снаря─
жение... Есть команды,оперирующие зашитыми
в движок  256  битами  и 256 переменными -
это  тянется ещё с Anime Story, только там
эти массивы были поменьше.
   Блок  команд  отвечает  за  ветвление -
определяется  условие и адрес, куда скрипт
переходит, если условие выполнено.

   Но обо всём по порядку:

   Вначале  замечу, что не хочу особо при─
вязываться к движку Wanderers - расскажу в
общих чертах,чтобы была ясна идея. Но при─
меры будут оттуда.

 -работа с флагами и переменными.
Здесь размещены такие команды, как устано─
вить/сбросить/инвертировать  бит  и  набор
бинарных операций над битами - OR,AND,XOR.
Кроме того,операции над переменными,прини─
мающими значения  0..255 - задать перемен─
ную, инкремент, декремент, сложение  и вы─
читание  с числом или с другой переменной.
Всё это надо для учета событий и условий в
командах перехода.

 -ветвление и переходы.
В этой группе сосредоточены команды,по ка─
кому-либо условию разветвляющие выполнение
скрипта.В параметрах задаётся само условие
и адрес,на который будет совершён переход.
Условия могут быть самыми разными. Станда─
ртный набор - если бит установлен/сброшен,
если  переменная больше/меньше/равна числу
или другой переменной,если случайное число
больше/меньше  какого-то  значения.  Кроме
этого, можно  придумать  более специфичные
условия - если у персонажа есть определён─
ный предмет/магия/зелье/снаряжение.

 -управление  музыкой и звуковыми эффек─
тами. 
Здесь немного команд - вкл/выкл проигрыва─
ния музыки, запуск трека,проигрывание зву─
ка.

 -служебные команды.
Тут собраны вспомогательные команды, кото─
рые  не воздействуют напрямую на структуры
данных. Такие,как - сделать паузу в задан─
ное кол-во прерываний;отсканировать клави─
атуру и выполнить закреплённый за клавишей
скрипт, когда  она  нажата;  сделать  call
скрипта или вызвать код.

 -управление структурами.
В эту группу включены команды, взаимодейс─
твующие  со структурами данных - активиро─
вать/деактивировать  зоны/двери, добавить/
удалить герою предмет/зелье/магию/снаряже─
ние. Плюс управление видимыми элементами -
задать NPC/элементу анимацию/спрайт, пере─
местить его куда-нибудь...Анимацией и ото─
бражением их на экране занимается аниматор
в движке, это всё происходит параллельно с
выполнением скрипта игры.

 -диалоговые окна и меню.
По сути здесь одна команда - начать работу
с меню. Задаётся  положение, размер окошка
меню, список пунктов и закреплённые за ним
адреса,на которые будет совершён переход в
случае выбора пункта.Любой печатный символ
заставляет движок открыть диалоговое окно,
если оно ещё не открыто, и начать выводить
строку.

  -табличные действия.
Это сканеры таблиц, в которых  указаны 1-2
id  и адрес  перехода. К примеру, действие
"говорить" имеет один параметр - id персо─
нажа, который стоит перед героем. Если при
сканировании  таблицы  встретился этот id,
вызывается закреплённый за ним скрипт.

   Из этих элементарных действий можно со─
брать нехитрый квест.В пример приведу кус─
ки из скрипта  Wanderers. Все эти незнако─
мыеt* - это макросы, создающие смесь db и
dw - сам байт-код для интерпретации.

       tSetMap 255    ;нарисовать экран,
               ;на котором находится герой
               ;(255 - спец.номер)
gsLoop  tHalt  ;HALT. Вызывается аниматор,
               ;экран обновляется
       tKeyScan mKeyTab;сканируем
                        ;клавиатуру
       tJump gsLoop    ;возвращаемся к
                        ;метке gsLoop


mKeyTab dw 0x01fd,gsDown  ; A
       dw 0x01fb,gsUp   ; Q
       dw 0x017f,gsMenu ; Space - меню
       dw OxOЧdf,gsEquip; I - экипировка
       ...
       db 0


gsDown  tNpcAni 0,cOOdn ;задать NPC 0
              ;(герой) анимацию, описанную
           ;по адресу cOOdn (это шаг вниз)
gsdOO   tWaitNPC 0      ;подождать, пока
                ;анимация NPC 0 закончится
       tZoneScan gsdOO;отсканировать
                        ;таблицу зон;
                ;если зона активировалась,
                ;выполнить скрипт зоны,
           ;потом вернуться к адресу gsdOO
       tEnd   ;конец. Эта часть была
                ;вызвана как подпрограмма,
                ;поэтому это действует как
                ;RET в вызывавший скрипт


gsUp    tNpcAni 0,cOOup ;задать NPC 0
              ;(герой) анимацию, описанную
          ;по адресу cOOup (это шаг вверх)
       tJump gsdOO;перейти к метке gsdOO


gsEquip tSelectEquip    ;это "объёмная"
              ;команда, которой занимается
              ;сам движок -
              ;работа с меню снаряжения
       tEnd     ;RET


gsMenu  tMenu 255,255,0,0,dMainMenu ;это
                  ;выводит меню действий.
                  ;На dMainMenu лежит
                  ;описание пунктов меню -
          ;что показывать, как называются,
                  ;какие скрипты
                  ;вызывать при выборе
       tEnd   ;RET после выполнения
                ;скрипта одного из пунктов


   Теперь  обратим  внимание  на аниматор.
Благодаря этой части экран у нас не стати─
чен. Аниматор каждый INT сканирует таблицы
NPC и активных элементов. Если встречаются
таковые  с действующей анимацией, аниматор
берётся за исполнение скрипта,описывающего
поведение спрайта. Эти скрипты очень схожи
с описанным выше, но имеют свою специфику,
т.к. заточены  только для манипуляции гра─
фикой. Из команд общей направлености - пе─
реместить  спрайт в указанное место, смес─
тить  спрайт  относительно текущей позиции
и, пожалуй,всё :) Есть специфические кома─
нды  и даже  ветвления - проверить текущие
координаты  спрайта, проверить возможность
сделать  шаг  в  определенном  направлении
(сквозь стены лучше не ходить) и т.д. Сама
последовательность  кадров задаётся струк─
турами вида<длительность>,<адрес спрайта>
Встретив  такую, аниматор обновляет спрайт
элемента и делает для него паузу  на<дли─
тельность> INT-ов.

   Вот  пример  анимации. В  Wanderers это
пилигрим у великого древа, иногда поглажи─
вающий свою бородку. Так же,a* - это мак─
росы:

ani13 DBW 30,npc13a     ;30 INT'ов, спрайт
                        ;npc13a
     aIfRndLess 200,ani13    ;если
           ;RND(255)<200, перейти к ani13.
           ;Этим обуславливается "иногда".
     DBW 20,npc13b;20 INT, спрайт npc13b
     DBW 20,npc13c;20 INT, спрайт npc13c
;Эти 2 спрайта - как раз сунулрукувбороду 
     aJump ani13 ;перейти к адресу ani13
                   ;(анимация зациклена)

макрос"DBW p1,p2" - это "DB p1; DW p2". Я
им часто пользуюсь в самых разных местах.

  Итак, для создания хоть какого-то скри─
птового движка  важно  определить для себя
несколько вещей:
 - с какими  структурами  придётся  рабо─
тать;
 - как можно изменять эти структуры;
 - какие  элементарные действия нужно бу─
дет выполнять;
  Когда  всё это будет разрисовано на бу─
маге, получится  некий мета-язык для игры.
Если им правильно пользоваться, можно соз─
дать настоящий шедевр.

(В приложении лежит полный список команд и 
дефайны.) 



Other articles:


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

Similar articles:
Interface - Overview of Windows like shells and systems for ZX Spectrum.

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