1090 lines
78 KiB
TeX
1090 lines
78 KiB
TeX
%На будущее даю инструкции по стилю кода.
|
||
%Использовать \verb вместо \texttt,где это возможно.
|
||
%Пробелы ДО и ПОСЛЕ таблиц. Только при помощи \medskip.
|
||
\documentclass[a4paper,12pt]{article}
|
||
\usepackage[utf8]{inputenc}
|
||
\usepackage[russian]{babel}
|
||
\usepackage[a4paper]{geometry}
|
||
\usepackage[pdftex,colorlinks,linkcolor = blue,urlcolor = blue,unicode]{hyperref}
|
||
\usepackage{xcolor}
|
||
\usepackage{graphicx}
|
||
\usepackage{wrapfig}%обтекание текстом
|
||
\geometry{verbose,tmargin=1cm,bmargin=1cm,lmargin=1cm,rmargin=1cm,headheight=1cm,headsep=1cm,footskip=0.7cm}
|
||
\usepackage{indentfirst}
|
||
\begin{document}
|
||
\title{Справочное пособие по INSTEAD}
|
||
\author{Александр Яковлев\\oreolek@jabber.ru \and \textit{при участии Петра Косых}\\\textit{gl00my@jabber.ru}}
|
||
\maketitle
|
||
\tableofcontents
|
||
\clearpage
|
||
\section{Введение}
|
||
Данный справочник написан в предположении,что читатель знаком с объектно-ориентированным программированием.
|
||
|
||
Игры для движка STEAD пишутся на языке \href{http://www.lua.org}{Lua} версии 5.1 (то есть, последней на данный момент). Знание этого языка будет очень полезным при написании игр, но я постараюсь сделать описание настолько подробным, что даже новичок в этом языке смог создавать игры для INSTEAD без проблем. Между прочим, знающим Lua будет небезынтересно посмотреть код движка.
|
||
|
||
\begin{wrapfigure}{l}{0.55\linewidth}
|
||
\includegraphics[scale=0.7]{1.jpg}
|
||
\caption{INSTEAD с запущенной игрой}
|
||
\label{INSTEAD-running}
|
||
\end{wrapfigure}
|
||
|
||
\textbf{Главное окно} игры содержит информацию о статической и динамической части сцены, активные события и картинку сцены с возможными переходами в другие сцены (в графическом интерпретаторе).
|
||
|
||
\textbf{Динамическая часть} сцены составлена из описаний объектов сцены, она отображается всегда. Она может выглядеть так: <<Стоит стол. Рядом стоит стул>>. Если динамическая часть пуста, то игроку не с чем контактировать в сцене.
|
||
|
||
\textbf{Статическая часть} сцены описывает саму сцену, её <<декорации>>. Она отображается при показе сцены (единожды или каждый раз -- решает автор игры), или при повторении команды look (в графическом интерпретаторе при щелчке на названии сцены).
|
||
|
||
Игрок имеет собственный \textbf{инвентарь}. В нём лежат объекты, доступные на любой сцене. Чаще всего инвентарь рассматривают как некую <<котомку>>, в которой лежат объекты; в этом случае каждый объект считают предметом. Такая трактовка практична, обыденна и интуитивна; но не единственна. Понятие инвентаря является условным, ведь это лишь контейнер. В нём могут находиться такие объекты, как <<открыть>>, <<потрогать>>, <<лизнуть>>. Можно наполнить его объектами <<нога>>, <<рука>>, <<мозг>>. Автор игры свободен в определении этих понятий, но он также должен определить действия игрока над ними.
|
||
|
||
На рисунке \ref{INSTEAD-running} очень чётко видны границы между этими областями. Главное окно имеет бежевый фон\footnote{Поправьте меня,если я неправ; в описании главного окна нет инвентаря}, инвентарь - чёрный.Динамическая часть идёт сразу после ссылок перехода и выделена курсивом; статическая часть отпечатана обычным шрифтом.
|
||
|
||
Действиями игрока могут быть:
|
||
|
||
\begin{itemize}
|
||
\item {осмотр сцены}
|
||
\item {действие на объект сцены}
|
||
\item {действие на объект инвентаря}
|
||
\item {действие объектом инвентаря на объект сцены}
|
||
\item {действие объектом инвентаря на объект инвентаря}
|
||
\end{itemize}
|
||
|
||
Осмотр сцены - это чаще всего неявное действие. Игрок входит в комнату, он автоматически осматривает её.
|
||
|
||
Действие на объект сцены обычно понимается как изучение объекта, или использование его. Например, если в сцене существует объект <<чашка кофе>>, то действием на него может быть выпивание кофе, тщательный осмотр чашки, разбивание чашки или перемещение чашки в инвентарь. Это определяется только автором и никем другим.
|
||
|
||
Действие на объект инвентаря понимается аналогично. Например, если в инвентаре лежит объект <<яблоко>>, его можно съесть или осмотреть. С другой стороны, если в инвентаре лежит объект <<осмотреть>>, то действие над ним будет трудно описать логически.
|
||
|
||
Действие объектом инвентаря на объект сцены -- это чаще всего использование или передача объекта. Например, действие объектом <<нож>> на объект <<бармен>> может означать передачу ножа бармену, угрозу ножом бармену, убийство ножом бармена и многое другое.
|
||
|
||
Действие объектом инвентаря на объект инвентаря понимается так же свободно. Это может быть соединение предметов (<<сарделька>> + <<кетчуп>>) в одно (<<сарделька с кетчупом>>), либо использование (<<открыть>> + <<ящик>>).
|
||
|
||
Эти примеры подробно показывают первую из идей STEAD - гибкость. Автор свободен в своей фантазии и может трактовать все понятия движка как хочет.
|
||
|
||
Игра представляет из себя каталог, в котором должен находиться скрипт main.lua. Другие ресурсы игры (скрипты на lua, графика и музыка) должны находиться в рамках этого каталога. Все ссылки на ресурсы делаются относительно текущего каталога -- каталога игры.
|
||
|
||
Игра начинается именно с main.lua. В начале файла main.lua может быть определён заголовок, состоящий из тегов. Теги должны начинаться с символов комментария \verb/--/. На данный момент существует один тег: \verb/$Name:,/ который должен содержать название игры. Пример использования тега:
|
||
|
||
\begin{verbatim}
|
||
-- $Name: Самая интересная игра!$
|
||
\end{verbatim}
|
||
|
||
Интерпретатор ищет доступные игры в следующих каталогах:
|
||
|
||
Unix версия интерпретатора просматривает \verb;/usr/local/share/instead/games; (по умолчанию), а также \verb,~/.instead/games,.
|
||
|
||
Windows сборка использует каталог \verb/куда-вы-установили-INSTEAD\games/; каталоги пользовательских игр немного меняются в зависимости от вашей версии Windows. В Windows XP это \texttt{Documents and Settings/USER/Local Settings/Application Data/instead/games}, когда как в Windows Vista это \verb;Users\USER\AppData\Local\instead\games;.
|
||
|
||
На данный момент активно развивается только графическая ветка интерпретатора -- INSTEAD-SDL. Поэтому справочник в б\'{о}льшей мере описывает её возможности.
|
||
|
||
\section{Сцена}
|
||
|
||
Сцена -- это единица игры, в рамках которой игрок может изучать все объекты сцены и взаимодействовать с ними. В игре должна быть хотя бы одна сцена с именем main.
|
||
|
||
\begin{verbatim}
|
||
main = room {
|
||
nam = 'главная комната',
|
||
dsc = 'Вы в большой комнате.',
|
||
};
|
||
\end{verbatim}
|
||
|
||
Отмечу, что пример выше является минимальной игрой для INSTEAD. Это некий <<Hello, World>>, который я рекомендую сохранить под именем main.lua и поместить в отдельную папку в каталоге для игр.
|
||
|
||
Атрибут \verb/nam/ (имя) является необходимым для любого объекта. Для сцены это -- то, что будет заголовком сцены при её отображении. Имя сцены также используется для её идентификации при переходах.
|
||
|
||
Атрибут \verb/dsc/ -- это описание статической части сцены, которое выводится при входе в сцену или выполнении команды look.
|
||
|
||
\textbf{\textcolor{red}{Внимание!!!}} Если для вашего творческого замысла необходимо, чтобы описание статической части сцены выводилось на каждом ходу (а не только при первом входе в сцену), вы можете определить для своей игры параметр forcedsc (в начале игры).
|
||
|
||
\begin{verbatim}
|
||
game.forcedsc = true;
|
||
\end{verbatim}
|
||
|
||
Или, аналогично, задать атрибут forcedsc для конкретных сцен.
|
||
|
||
Для длинных описаний удобно использовать запись вида:
|
||
|
||
\begin{verbatim}
|
||
dsc = [[ Очень длинное описание... ]],
|
||
\end{verbatim}
|
||
|
||
При этом переводы строк игнорируются. Если вы хотите, чтобы в выводе описания сцены присутствовали абзацы -- используйте символ \verb/^/.
|
||
|
||
\begin{verbatim}
|
||
dsc = [[ Первый абзац. ^^
|
||
Второй Абзац.^^
|
||
|
||
Третий абзац.^
|
||
На новой строке.]],
|
||
\end{verbatim}
|
||
|
||
К текущей сцене можно обратиться через функцию \verb/here()/.
|
||
|
||
\section{Объект}
|
||
\subsection{Нормальные объекты}
|
||
Объекты -- это единицы сцены, с которыми взаимодействует игрок.
|
||
|
||
\begin{verbatim}
|
||
table = obj {
|
||
nam = 'стол',
|
||
dsc = 'В комнате стоит {стол}.',
|
||
act = 'Гм... Просто стол...',
|
||
};
|
||
\end{verbatim}
|
||
|
||
Имя объекта \verb/nam/ используется для адресации объекта.
|
||
|
||
\verb/dsc/ -- описатель объекта. Он будет выведен в динамической части сцены. Фигурными скобками отображается фрагмент текста, который будет являться ссылкой в графическом интерпретаторе. Если вы забудете сделать ссылку, то интерпретатор не выдаст ошибки, но игроки не смогут взаимодействовать с объектом.
|
||
|
||
\verb/act/ -- это обработчик, который вызывается при действии пользователя на объект сцены. Если объект находится в инвентаре, то действие с ним будет передаваться другому обработчику -- \verb/inv/.
|
||
|
||
Настало время сделать небольшое отступление. До сих пор в примерах приводились примитивные обработчики, которые всего лишь возвращают определённую строку. В примере выше обращение к объекту вызовет банальную реакцию: интерпретатор напечатает строку <<Гм... Просто стол...>>. Хуже того: он будет отвечать тем же образом каждый раз при обращении к объекту. Это не совсем гибкий подход, поэтому STEAD позволяет определить любой атрибут объекта как функцию. Так, возможно построить такую конструкцию:
|
||
|
||
\begin{verbatim}
|
||
apple = obj {
|
||
nam = 'яблоко',
|
||
dsc = function(s)
|
||
if not s._seen then
|
||
return 'На столе {что-то} лежит.';
|
||
else
|
||
return 'На столе лежит {яблоко}.';
|
||
end
|
||
end,
|
||
act = function(s)
|
||
if s._seen then
|
||
return 'Это яблоко!';
|
||
else
|
||
s._seen = true;
|
||
return 'Я присматриваюсь и понимаю,что это - яблоко.!';
|
||
end
|
||
end,
|
||
};
|
||
\end{verbatim}
|
||
|
||
Если атрибут или обработчик оформлен как функция, то обычно первый аргумент функции \verb/(s)/ есть сам объект. В данном примере, при показе сцены будет в динамической части сцены будет текст: <<На столе что-то лежит>>. При взаимодействии с <<что-то>>, переменная \verb/_seen/ объекта \verb/apple/ будет установлена в \verb/true/, и мы увидим, что это было яблоко.
|
||
|
||
Если аргумент у функции единственен, то скобки вокруг аргумента можно опускать. Так, например, \verb/return/ -- это функция, но здесь она написана без скобок. Дальнейшие примеры будут часто использовать эту возможность. Вы можете и не опускать скобки, если это не нравится вам по стилю.
|
||
|
||
Запись \verb/s._seen/ означает, что переменная \verb/_seen/ размещена в объекте \verb/s/ (то есть, \verb/apple/). В языке Lua переменные необязательно объявлять заранее, при первом обращении к ней переменная \verb/apple._seen/ появится сама; но хорошим тоном будет заранее \textbf{проинициализировать} переменную со значением \verb/false/.
|
||
|
||
Подчёркивание в имени переменной означает, что она \textbf{попадёт} в файл сохранения игры. Сохраняются все переменные, название которых начинается с большой буквы или с подчёркивания. Вы можете переопределить функцию \verb/isForSave(k)/, если вас это не устраивает.
|
||
|
||
\textbf{\textcolor{red}{Внимание!!!}} Переменные в любом случае не записываются в файл сохранения, если они не размещены в одном из перечисленных типов объектов: комната, объект, диалог, игра, игрок.
|
||
|
||
\subsection{Облегчённые объекты}
|
||
|
||
Иногда, сцену нужно наполнить декорациями, которые обладают ограниченной функциональностью, но делают игру разнообразней. Для этого можно использовать облегчённый объект. Например:
|
||
|
||
\begin{verbatim}
|
||
sside = room {
|
||
nam = 'южная сторона',
|
||
dsc = [[Я нахожусь у южной стены здания института. ]],
|
||
act = function(s, w)
|
||
if w == 1 then
|
||
ways():add('stolcorridor');
|
||
return "Я подошёл к подъезду. Хм -- зайти внутрь?";
|
||
end
|
||
end,
|
||
obj = {vobj(1, "подъезд", "У восточного угла находится небольшой {подъезд}.")},
|
||
};
|
||
\end{verbatim}
|
||
|
||
Как видим, \verb/vobj/ позволяет сделать лёгкую версию статического объекта, с которым тем не менее можно взаимодействовать (за счёт определения обработчика \verb/act/ в сцене и анализа ключа объекта). \verb/vobj/ также вызывает метод \verb/used/, при этом в качестве третьего параметра передаётся объект, воздействующий на виртуальный объект.
|
||
|
||
Синтаксис \verb/vobj/ таков: \verb/vobj(ключ, имя, описатель);,/ где ключ -- это цифра, которая будет передана обработчикам \verb.act/used. сцены как второй параметр.
|
||
|
||
Существует модификация объекта \verb/vobj/ под именем \verb/vway/. \verb/vway/ реализует ссылку. Синтаксис и пример:
|
||
|
||
\begin{verbatim}
|
||
vway(имя, описание, сцена назначения);
|
||
obj = { vway("дальше", "Нажмите {здесь}.", 'nextroom') }
|
||
\end{verbatim}
|
||
|
||
Вы можете динамически заполнять сцену объектами \verb/vobj/ или \verb/vway/ с помощью методов \verb/add/ и \verb/del/.
|
||
|
||
В довершение, определена также упрощённая сцена \verb/vroom/. Синтаксис:
|
||
|
||
\begin{verbatim}
|
||
vroom(имя перехода, сцена назначения)
|
||
\end{verbatim}
|
||
|
||
Ниже приводится несколько примеров и трюков с подобными объектами:
|
||
|
||
\begin{verbatim}
|
||
home.objs:add(vway("next", "{Дальше}.", 'next_room');
|
||
home.objs:del("next");
|
||
home.objs:add(vroom("идти на запад", 'mountains');
|
||
if not home.obj:srch('Дорога') then
|
||
home.obj:add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
|
||
end
|
||
obj = {vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'):disable()},
|
||
objs()[1]:disable();
|
||
objs()[1]:enable();
|
||
\end{verbatim}
|
||
|
||
\subsection{Динамическое создание объектов}
|
||
|
||
Вы можете использовать аллокаторы \verb/new/ и \verb/delete/ для создания и удаление динамических объектов:
|
||
|
||
\begin{verbatim}
|
||
new("obj { nam = 'a' ..... }")
|
||
put(new [[obj {nam = 'test' } ]]);
|
||
put(new('myconstructor()');
|
||
\end{verbatim}
|
||
|
||
Созданный объект будет попадать в файл сохранения. \verb/new()/ возвращает реальный объект; чтобы получить его имя,если это нужно, используйте функцию \verb/deref()./
|
||
|
||
\section{Некоторые манипуляции с объектами}
|
||
|
||
\subsection{Объект и сцена}
|
||
|
||
Ссылкой на объект называется текстовая строка, содержащая имя объекта при его создании. Например: \verb/'table'/ -- ссылка на объект \verb/table/.
|
||
|
||
Для того, чтобы поместить в сцену объекты, нужно определить массив \verb/obj/, состоящий из ссылок на объекты:
|
||
|
||
\begin{verbatim}
|
||
main = room {
|
||
nam = 'главная комната',
|
||
dsc = 'Вы в большой комнате.',
|
||
obj = { 'tabl' },
|
||
};
|
||
\end{verbatim}
|
||
|
||
\subsection{Объекты, связанные с объектами}
|
||
|
||
Объекты тоже могут содержать атрибут \verb/obj./ При этом, список будет последовательно разворачиваться. Например, поместим на стол яблоко:
|
||
|
||
\begin{verbatim}
|
||
apple = obj {
|
||
nam = 'яблоко',
|
||
dsc = 'На столе лежит {яблоко}.',
|
||
};
|
||
|
||
table = obj {
|
||
nam = 'стол',
|
||
dsc = 'В комнате стоит {стол}.',
|
||
obj = { 'apple' },
|
||
};
|
||
\end{verbatim}
|
||
|
||
При этом, в описании сцены мы увидим описание объектов <<стол>> и <<яблоко>>, так как \verb/apple/ -- связанный с \verb/table/ объект.
|
||
|
||
\subsection{Действия объектов друг на друга}
|
||
|
||
Игрок может действовать объектом инвентаря на другие объекты. При этом вызывается обработчик \verb/use/ у объекта которым действуют и \verb/used/ -- на которого действуют.
|
||
|
||
Например:
|
||
|
||
\begin{verbatim}
|
||
knife = obj {
|
||
nam = 'нож',
|
||
dsc = 'На столе лежит {нож}',
|
||
inv = 'Острый!',
|
||
tak = 'Я взял нож!',
|
||
use = 'Вы пытаетесь использовать нож.',
|
||
};
|
||
|
||
tabl = obj {
|
||
nam = 'стол',
|
||
dsc = 'В комнате стоит {стол}.',
|
||
act = 'Гм... Просто стол...',
|
||
obj = { 'apple', 'knife' },
|
||
used = 'Вы пытаетесь сделать что-то со столом...',
|
||
};
|
||
\end{verbatim}
|
||
|
||
Если игрок возьмёт нож и использует его на стол -- то увидит текст обработчиков \verb/knife.use/ и \verb/tabl.used/.
|
||
|
||
\verb/use/ и \verb/used/ могут быть функциями. Тогда первый параметр это сам объект, а второй -- ссылка на объект, на который направлено действие в случае \verb/use/ и объект, которым действие осуществляется в случае \verb/used/.
|
||
|
||
\verb/use/ может вернуть статус \verb/false/, в этом случае обработчик \verb/used/ не вызывается (если он вообще был). Статус обработчика \verb/used/ -- игнорируется. Это будет выглядеть как:
|
||
|
||
\begin{verbatim}
|
||
return 'Строка реакции', false;
|
||
\end{verbatim}
|
||
|
||
Возможно также действовать объектами сцены на объекты сцены; для этого нужно установить переменную \verb/game.scene_use = true/ или поставить \verb/scene.use=true/ в нужной комнате. В этом случае использование объектов сцены будет аналогично использованию объектов инвентаря.
|
||
|
||
\subsection{Скрытие объектов}
|
||
|
||
При помощи методов \verb/enable/ и \verb/disable/ становится возможным управлять появлением и исчезновением объектов.
|
||
|
||
Скрытый объект -- это объект, который находится в сцене, но на данный момент словно бы ,,выключен``. Он присутствует для движка, но не существует для игрока. Его описание не выводится и с ним невозможно контактировать. Это можно использовать, например, вместо динамического создания объектов.
|
||
|
||
Чтобы создать заведомо выключенный объект, необходимо воспользоваться конструкцией вида \verb/knife = {<...>}:disable()./
|
||
Объект \verb/knife/ будет создан и тут же выключен.
|
||
|
||
Методы \verb/enable()/ и \verb/disable()/ возвращают сам объект. Они присутствуют у любого объекта и списка объектов.
|
||
|
||
\section{Смена сцен}
|
||
|
||
Как только главный герой уходит со сцены, декорации меняются. Но чтобы игрок ушёл из нашей сцены, он должен знать, куда идти.
|
||
|
||
Для перехода между сценами используется атрибут сцены -- список \verb/way/.
|
||
|
||
\begin{verbatim}
|
||
room2 = room {
|
||
nam = 'зал',
|
||
dsc = 'Вы в огромном зале.',
|
||
way = { 'main' },
|
||
};
|
||
|
||
main = room {
|
||
nam = 'главная комната',
|
||
dsc = 'Вы в большой комнате.',
|
||
obj = { 'tabl' },
|
||
way = { 'room2' },
|
||
};
|
||
\end{verbatim}
|
||
|
||
При этом, вы сможете переходить между сценами \verb/main/ и \verb/room2/. Как вы помните, \verb/nam/ может быть функцией, и вы можете генерировать имена сцен на лету, например, если вы хотите, чтобы игрок не знал название сцены, пока не попал на неё.
|
||
|
||
При переходе между сценами движок вызывает обработчик \verb/exit/ из текущей сцены и \verb/enter/ той сцены, куда идёт игрок. \verb/exit/ и \verb/enter/ могут быть функциями -- тогда первый параметр это сам объект, а второй -- ссылка на комнату куда игрок хочет идти (для \verb/exit/) или из которой уходит (для \verb/enter/). Например:
|
||
|
||
\begin{verbatim}
|
||
room2 = room {
|
||
enter = function(s, f)
|
||
if f == 'main' then
|
||
return 'Вы пришли из комнаты.';
|
||
end
|
||
end,
|
||
nam = 'зал',
|
||
dsc = 'Вы в огромном зале.',
|
||
way = { 'main' },
|
||
exit = function(s, t)
|
||
if t == 'main' then
|
||
return 'Я не хочу назад!', false
|
||
end
|
||
end,
|
||
};
|
||
\end{verbatim}
|
||
|
||
Как видим, обработчики могут возвращать два значения: строку и статус. В нашем примере функция \verb/exit/ вернёт \verb/false/, если игрок попытается уйти из зала в \verb/main/. \verb/false/ блокирует переход. Такая же логика работает и для \verb/enter/. Кроме того, она работает и для обработчика \verb/tak/ (о нём чуть позже).
|
||
|
||
\textbf{\textcolor{red}{Важное замечание:}} обработчик enter вызывается не при входе в комнату, а чуть раньше. Когда игрок хочет уйти в комнату, движок вызывает её обработчик enter, чтобы убедиться в том,что тот не возвращает false и переход возможен. Поэтому если вы используете \verb/here()/ в \verb/enter/, она будет указывать прежде всего -- на предыдущую комнату. Если вы передаёте enter параметр сцены, то он будет указывать всегда на текущую сцену.
|
||
|
||
Если требуется перейти на другую сцену автоматически, можно использовать функцию \verb/goto/ со ссылкой на сцену как параметром:
|
||
|
||
\begin{verbatim}
|
||
return goto('main');
|
||
\end{verbatim}
|
||
|
||
Почему здесь написано \verb/return/? Дело в том,что функция \verb/goto()/ не является безусловным переходом,как можно подумать. Она возвращает описание новой сцены, поэтому почти всегда должна завершать работу обработчика таким нехитрым способом.
|
||
|
||
\textbf{\textcolor{red}{НО: }}Если вы выполните goto из обработчика exit, то получите переполнение стека, так как goto снова и снова будет вызывать метод exit. Вы можете избавиться от этого, если вставите проверку, разрушающую рекурсию. Например:
|
||
|
||
\begin{verbatim}
|
||
exit = function(s, t)
|
||
if t == 'dialog' then return; end
|
||
return goto('dialog');
|
||
\end{verbatim}
|
||
|
||
Обычно движок сам пытается разорвать рекурсию. Тем не менее, автор должен понимать, что он делает и не надеяться на автоматику.
|
||
|
||
\section{Специальные типы объектов}
|
||
|
||
\subsection{Инвентарь}
|
||
|
||
Инвентарь проще всего возвращается функцией inv(). Он представлен списком, поэтому для него справедливы все их трюки (см. соответствующий раздел).
|
||
|
||
Простейший вариант сделать объект, который можно брать -- определить у него обработчик tak.
|
||
|
||
Если предмет сцены имеет обработчик \verb/tak/ и НЕ имеет обработчика \verb/act/ \footnote{Пользуясь случаем: я считаю,что tak - немного неудобное имя. Именно так. - А.Я.}, то при действии на нём вызывается не \verb/act/, а \verb/tak/; после этого предмет перемещается в инвентарь. Это происходит вот так:
|
||
|
||
\begin{verbatim}
|
||
apple = obj {
|
||
nam = 'яблоко',
|
||
dsc = 'На столе лежит {яблоко}.',
|
||
tak = 'Вы взяли яблоко.',
|
||
};
|
||
\end{verbatim}
|
||
|
||
\subsection{Игрок}
|
||
|
||
Игрок в STEAD представлен объектом \verb/pl/. Тип объекта -- \verb/player/.
|
||
|
||
Атрибут \verb/obj/ представляет собой инвентарь игрока.
|
||
|
||
Объекты игрока можно воспринимать как объекты инвентаря, в этом случае верны следующие конструкции:
|
||
|
||
\begin{verbatim}
|
||
remove('knife', me());
|
||
put('knife', me());
|
||
take('knife', me());
|
||
where('knife');
|
||
\end{verbatim}
|
||
|
||
Необходимо отметить, что это верно не в каждой игре.
|
||
|
||
\subsection{Игра}
|
||
|
||
Игра представлена объектом \verb/game/. Он хранит в себе указатель на текущего игрока (\verb/'pl'/) и некоторые параметры. Например, вы можете указать в начале своей игры кодировку текста следующим образом:
|
||
|
||
\begin{verbatim}
|
||
game.codepage="UTF-8";
|
||
\end{verbatim}
|
||
|
||
Кроме того, объект \verb/game/ может содержать обработчики по умолчанию \verb/act/, \verb/inv/, \verb/use/, которые будут вызваны, если в результате действий пользователя не будут найдены никакие другие обработчики. Например, вы можете написать в начале игры:
|
||
|
||
\begin{verbatim}
|
||
game.act = 'Не получается.';
|
||
game.inv = 'Гм.. Странная штука..';
|
||
game.use = 'Не сработает...';
|
||
\end{verbatim}
|
||
|
||
На практике полезно что-то вроде:
|
||
|
||
\begin{verbatim}
|
||
game.inv = function()
|
||
local a = rnd(7);
|
||
local reaction = {
|
||
[1] = 'Либо я ошибся карманом, либо мне нужно что-то другое.',
|
||
[2] = 'Откуда у меня в кармане ЭТО?!',
|
||
[3] = 'Сам не понял,что достал. Положу обратно.',
|
||
[4] = 'Это что-то неправильное.',
|
||
[5] = 'В моих карманах что только не залёживается...',
|
||
[6] = 'Я не представляю, как я могу тащить ЭТО с собою.',
|
||
[7] = 'Мне показалось или оно на меня смотрит?',
|
||
};
|
||
return reaction[a];
|
||
end;
|
||
\end{verbatim}
|
||
|
||
\section{Диалоги}
|
||
|
||
Третьим важным типом в движке являются диалоги. Диалоги -- это особый подвид сцен, содержащий только фразы. Например, диалог может выглядеть следующим образом:
|
||
|
||
\begin{verbatim}
|
||
povardlg = dlg {
|
||
nam = 'на кухне',
|
||
dsc = 'Передо мной полное лицо повара...',
|
||
obj = {
|
||
[1] = phr('Мне вот-этих зелёненьких... Ага -- и бобов!', 'На здоровье!'),
|
||
[2] = phr('Картошку с салом, пожалуйста!', 'Приятного аппетита!'),
|
||
[3] = phr('Две порции чесночного супа!!!', 'Прекрасный выбор!'),
|
||
[4] = phr('Мне что-нибудь лёгонькое, у меня язва...', 'Овсянка!'),
|
||
},
|
||
};
|
||
\end{verbatim}
|
||
|
||
\verb/phr/ -- создание фразы. Фраза содержит вопрос, ответ и реакцию (реакция в данном примере отсутствует). Когда игрок выбирает одну из фраз, фраза отключается. Когда все фразы отключатся диалог заканчивается. Реакция -- это строка кода на lua который выполнится после отключения фразы.
|
||
|
||
\verb/_phr/ -- создание выключенной фразы. Она не видна изначально, но её можно включить с помощью функции \verb/pon()/ (см. ниже). По смыслу это эквивалентно \verb/phr(<...>):disable()./
|
||
|
||
Вот как создаётся фраза:
|
||
|
||
\begin{verbatim}
|
||
[1] = phr('Мне вот-этих зелёненьких... Ага -- и бобов!', 'На здоровье!', [[pon(1);]]),
|
||
\end{verbatim}
|
||
|
||
В реакции может быть любой lua код (простейшей реакцией является возвращение строки), но в STEAD определены наиболее часто используемые функции:
|
||
|
||
\begin{description}
|
||
\item[pon(n...)] включить фразы диалога с номерами n... (в нашем примере -- чтобы игрок мог повторно взять еду того-же вида).
|
||
\item[poff(n...)] выключить фразы диалога с номерами n...
|
||
\item[prem(n...)] удалить (заблокировать) фразы диалога с номерами n... (удаление означает невозможность включения фраз. pon(n..) не приведёт к включению фраз).
|
||
\end{description}
|
||
|
||
Как ответ,так и реакция могут быть функциями.
|
||
|
||
Переход в диалог осуществляется как переход на сцену:
|
||
|
||
\begin{verbatim}
|
||
return goto('povardlg');
|
||
\end{verbatim}
|
||
|
||
Вы можете переходить из одного диалога в другой диалог -- организовывая иерархические диалоги.
|
||
|
||
Также, вы можете прятать некоторые фразы при инициализации диалога и показывать их при некоторых условиях.
|
||
|
||
Вы можете включать/выключать фразы не только текущего, но и произвольного диалога, с помощью методов объекта диалог \verb,pon/poff,. Например:
|
||
|
||
\begin{verbatim}
|
||
shopman:pon(5);
|
||
\end{verbatim}
|
||
|
||
Если номер фразы не указан,то это означает,что действие относится к текущей фразе:
|
||
|
||
\begin{verbatim}
|
||
phr('a', 'b', [[ pon() ]]);
|
||
\end{verbatim}
|
||
|
||
\section{О списках}
|
||
|
||
Каждый атрибут-список имеет методы:
|
||
|
||
\begin{description}
|
||
\item[add] Добавление элемента в список. Необязательным вторым параметром является позиция в списке.
|
||
\item[del] Удаление элемента из списка.
|
||
\item[look] Получение индекса элемента в списке по идентификатору
|
||
\item[srch] Проверка на наличие объекта в списке по его nam. Возвращает 2 значения: идентификатор и позицию; если объекта нет, вернёт nil. Например: \begin{verbatim}objs():srch('Ножик')\end{verbatim}
|
||
\item[set] Изменение объекта по номеру. Например, этот пример присвоит заменит первый объект списка: \begin{verbatim}objs():set('knife',1);\end{verbatim}
|
||
\item[disable] Скрытие объекта в списке; отличается от удаления тем, что может быть возвращён к жизни через метод enable
|
||
\item[enable] Показ скрытого объекта
|
||
\item[zap] Обнуление списка
|
||
\item[cat(b)] Склеивает список со списком b
|
||
\item[cat(b,pos)] Добавляет в список список b на позицию pos
|
||
\item[disable\_all] Аналогично disable, но массово
|
||
\item[enable\_all] Смысл понятен.
|
||
\end{description}
|
||
|
||
Параметрами методов могут быть объекты, их идентификаторы и имена.
|
||
|
||
\section{Функции}
|
||
\begin{description}
|
||
\item[inv()] возвращает список инвентаря
|
||
\item[objs()] возвращает список объектов указанной сцены; если сцена не указана, то возвращает список объектов текущей сцены.
|
||
\item[ways()] возвращает список возможных переходов из указанной сцены; если сцена не указана, то возвращает список возможных переходов из текущей сцены.
|
||
\item[me()] возвращает объект pl (объект игрока)
|
||
\item[here()] возвращает текущую сцену
|
||
\item[where()] возвращает текущую сцену как строку-имя объекта, а не сам объект
|
||
\item[from()] возвращает объект прошлой сцены
|
||
\item[ref(nam)] возвращает ссылку на указанный объект: \begin{verbatim}ref('home') == home\end{verbatim}
|
||
\item[deref(object)] возвращает ссылку строкой для объекта: \begin{verbatim}deref(knife) == 'knife'\end{verbatim}
|
||
\item[have(object)] проверяет, есть ли объект в инвентаре по имени объекта или по его nam
|
||
\item[move(from, where)] переносит объект из текущей сцены в другую
|
||
\item[movef(from, where)] действует так же, но добавляет объект в начало списка
|
||
\item[seen(object,scene)] проверяет, есть ли объект в указанной сцене (в текущей, если сцена не указана)
|
||
\item[drop(object,scene)] выбрасывает объект из инвентаря в указанную сцену (в текущую, если сцена не указана)
|
||
\item[dropf(object,scene)] то же, что drop, но объект появляется в начале списка
|
||
\item[put(object,scene)] кладёт предмет в указанную сцену; в текущую, если сцена не указана
|
||
\item[remove(object,scene)] удаляет предмет из указанной сцены; из текущей, если сцена не указана
|
||
\item[take(object,scene)] перемещает объект из указанной(текущей) сцены в инвентарь
|
||
\item[taken(object)] проверяет, взят ли уже объект
|
||
\item[rnd(m)] возвращает случайное целое значение от 1 до m
|
||
\item[goto(destination)] переносит в сцену w; используется в конструкции вида \verb/return goto('inmycar');/
|
||
\item[change\_pl(player)] переключает на другого игрока (со своим инвентарём и позицией), также используется в \verb/return/. Может использоваться для переключения между разными инвентарями.
|
||
\item[back()] переносит в предыдущую сцену (аналогично goto)
|
||
\item[time()] возвращает текущее время игры в активных действиях.
|
||
\item[cat(...)] возвращает строку -- склейку строк-аргументов. Если первый аргумент nil, то функция возвращает nil.\footnote{Функция легко и просто заменяется обычным оператором склейки строк Lua: \texttt{строка1 .. строка2}. Тем не менее, этот оператор выдаст ошибку при склейке nil}
|
||
\item[par(...)] возвращает строку -- склейку строк-аргументов, разбитых строкой-первым параметром.
|
||
\end{description}
|
||
|
||
Следующие записи эквивалентны:
|
||
|
||
\begin{verbatim}
|
||
ref('home').obj:add('chair');
|
||
home.obj:add('chair');
|
||
objs('home'):add('chair');
|
||
put('chair', 'home');
|
||
\end{verbatim}
|
||
|
||
Если вы хотите перенести объект из произвольной сцены, вам придётся удалить его из старой сцены с помощью метода del. Для создания сложно перемещающихся объектов, вам придётся написать свой метод, который будет сохранять текущую позицию объекта в самом объекте и делать удаление объекта из старой сцены. Вы можете указать исходную позицию (комнату) объекта в качестве третьего параметра move.
|
||
|
||
\begin{verbatim}
|
||
move('mycat','inmycar', 'forest');
|
||
\end{verbatim}
|
||
|
||
|
||
Отдельно следует упомянуть функции альтернативного вывода текста. Их назначение можно понять по следующим формам записи:
|
||
|
||
\begin{verbatim}
|
||
act = function(s)
|
||
p "Я осмотрел его...';
|
||
p "Гммм...."
|
||
end
|
||
|
||
act = function(s)
|
||
return "Я осмотрел его... Гммм...."
|
||
end
|
||
\end{verbatim}
|
||
|
||
\begin{description}
|
||
\item[p] Добавляет строку и пробел в буфер
|
||
\item[pn] Добавляет строку и перевод строки в буфер
|
||
\item[pclr] Очистка буфера
|
||
\item[pget] Получение содержимое буфера на текущий момент
|
||
\end{description}
|
||
|
||
Другой пример:
|
||
|
||
\begin{verbatim}
|
||
life = function(s)
|
||
p 'Ветер дует мне в спину.'
|
||
return pget(), true
|
||
end
|
||
\end{verbatim}
|
||
|
||
\section{Добавление динамики в игру}
|
||
|
||
Игра измеряет время в своих единицах - в шагах, или активных действиях. Каждое действие игрока - это его шаг, пусть даже он тратит его на то,чтобы ещё раз осмотреться. Что он увидит нового? Что изменится в мире игры за это время?
|
||
|
||
Именно для того,чтобы задать динамику мира, существует система с говорящим названием life.
|
||
|
||
Вы можете определять обработчики, которые выполняются каждый раз, когда время игры увеличивается на 1. Например:
|
||
|
||
\begin{verbatim}
|
||
mycat = obj {
|
||
nam = 'Барсик',
|
||
lf = {
|
||
[1] = 'Барсик шевелится у меня за пазухой.',
|
||
[2] = 'Барсик выглядывает из за пазухи.',
|
||
[3] = 'Барсик мурлычет у меня за пазухой.',
|
||
[4] = 'Барсик дрожит у меня за пазухой.',
|
||
[5] = 'Я чувствую тепло Барсика у себя за пазухой.',
|
||
[6] = 'Барсик высовывает голову из за пазухи и осматривает местность.',
|
||
},
|
||
life = function(s)
|
||
local r = rnd(6);
|
||
if r > 2 then
|
||
return;
|
||
end
|
||
r = rnd(6);
|
||
return s.lf[r];
|
||
end,
|
||
\end{verbatim}
|
||
|
||
В этом примере кот по имени Барсик, сидя в инвентаре у игрока, будет на каждом шагу показывать свою активность. Но приведённый код пока что не будет работать. Для того,чтобы объявить объект <<живым>>, следует добавить его в соответствующий список с помощью функции \verb/lifeon()/.
|
||
|
||
\begin{verbatim}
|
||
inv():add('mycat');
|
||
lifeon('mycat');
|
||
\end{verbatim}
|
||
|
||
Любой объект или сцена могут иметь свой обработчик \verb/life/, который вызывается каждый раз при смене текущего времени игры, если объект или сцена были добавлены в список живых объектов с помощью \verb/lifeon/. Не забывайте удалять живые объекты из списка с помощью \verb/lifeoff/, когда они больше не нужны. Это можно сделать, например, в обработчике \verb/exit/, или любым другим способом.
|
||
|
||
Вы можете вернуть из обработчика life второй код возврата, важность. (true или false). Если он равен true, то возвращаемое значение будет выведено ДО описания объектов; по умолчанию значение равно false.
|
||
|
||
Если вы хотите <<очистить экран>>, то можно воспользоваться вот каким хаком. Из метода \verb/life/ доступна переменная \verb/ACTION_TEXT/ -- это тот текст, который содержит реакцию на действие игрока. Соответственно, сделав \verb/ACTION_TEXT = nil/,можно <<запретить>> вывод реакции. Например,для перехода на конец игры можно сделать:
|
||
|
||
\begin{verbatim}
|
||
ACTION_TEXT = nil
|
||
return goto('theend'), true
|
||
\end{verbatim}
|
||
|
||
\section{Краски и звуки}
|
||
|
||
В чём очевидное преимущество графического интерпретатора над текстовой веткой -- это то, что он может говорить и показывать. Проще говоря, вы можете добавить в игру графику и музыку.
|
||
|
||
Графический интерпретатор анализирует атрибут сцены \verb/pic/, и воспринимает его как путь к картинке-иллюстрации для сцены. Если в текущей сцене не определён атрибут \verb/pic/, то берётся \verb/game.pic/. Если не определён и он, то картинка не отображается.
|
||
|
||
Unix-версия движка поставляется в исходных кодах, поэтому поддержка форматов графики и музыки определяется на стадии его компиляции; если при сборке в системе присутствуют нужные библиотеки для SDL, то формат будет поддерживаться. Я рекомендую использовать форматы PNG, JPG и GIF. Новые версии движка поддерживают GIF-анимацию. Те же правила действуют для музыки. Здесь строгих рамок нет, поэтому старайтесь не использовать редких форматов. Проверена поддержка WAV, MP3, OGG, FLAC, MIDI, XM, MOD, IT, S3M.
|
||
|
||
Вы также можете встраивать графические изображения в текст или в инвентарь с помощью функции \verb/img/. Например:
|
||
|
||
\begin{verbatim}
|
||
knife = obj {
|
||
nam = 'Нож'..img('img/knife.png'),
|
||
}
|
||
\end{verbatim}
|
||
|
||
Теперь о звуке. Фоновая музыка задаётся с помощью функции:
|
||
|
||
\begin{verbatim}
|
||
set_music(имя музыкального файла, количество проигрываний)
|
||
\end{verbatim}
|
||
|
||
Она проигрывается циклически бесконечно,если количество проигрываний не задано.
|
||
|
||
\verb/get_music()/ возвращает текущее имя трека.
|
||
|
||
Функция \verb/get_music_loop/ возвращает, на каком витке повторения находится мелодия. 0 - означает вечный цикл. n -- количество проигрываний. -1 -- проигрывание текущего трека закончено.
|
||
|
||
Помимо фонового сопровождения, \verb/set_sound()/ позволяет проиграть звуковой файл. \verb/get_sound()/ возвращает имя звукового файла, который будет проигран.
|
||
|
||
\section{Трюки}
|
||
\subsection{Форматирование}
|
||
SDL-INSTEAD поддерживает простое форматирование текста с помощью функций:
|
||
|
||
\begin{description}
|
||
\item[txtc(текст)] -- разместить текст по центру
|
||
\item[txtr(текст)] -- разместить текст справа
|
||
\item[txtl(текст)] -- разместить слева
|
||
\item[txtb(текст)] -- полужирное начертание
|
||
\item[txtem(текст)] -- начертание курсивом
|
||
\item[txtu(текст)] -- подчёркнутый текст
|
||
\end{description}
|
||
|
||
\subsection{Проверка правописания}
|
||
Проверка правописания готовой игры - это большая головная боль. У вас есть примерно 100 Кб кода, в которых находятся около 80 Кб текста. Любая программа проверки орфографии будет сильно ругаться на синтаксис Lua и мешать. Один из способов проверки -- использовать редактор Emacs.
|
||
|
||
Для проверки нужно установить сам Emacs и поддержку Lua к нему (lua-mode); дальнейшие операции с редактором:
|
||
|
||
\begin{enumerate}
|
||
\item Открыть нужный файл
|
||
\item Если русские буквы выглядят кракозябрами -- выбираете в меню Options -- Set Font/FontSet... шрифт fixed
|
||
\item Tools -- Spell Checking -- Select Russian Dict
|
||
\item Tools -- Spell Checking -- Spell-Check Buffer
|
||
\item Пробел для того,чтобы пропустить слово; Английская a,чтобы игнорировать слово вообще; i чтобы добавить слово в словарь пользователя; цифры, чтобы заменить слово на один предложенных вариантов.
|
||
\end{enumerate}
|
||
|
||
Если вы впервые видите этот редактор, я настоятельно НЕ рекомендую нажимать что-нибудь и щёлкать на что-нибудь непонятное. Будет только непонятнее.
|
||
|
||
\subsection{Меню}
|
||
Вы можете делать меню в области инвентаря, определяя объекты с типом menu. При этом, обработчик меню будет вызван после клика мыши. Если обработчик не возвращает текст, то состояние игры не изменяется. Например, реализация кармана:
|
||
|
||
\begin{verbatim}
|
||
pocket = menu {
|
||
State = false,
|
||
nam = function(s)
|
||
if s.State then
|
||
return txtu('карман');
|
||
end
|
||
return 'карман';
|
||
end,
|
||
gen = function(s)
|
||
if s.State then
|
||
s:enable_all();
|
||
else
|
||
s:disable_all();
|
||
end
|
||
end,
|
||
menu = function(s)
|
||
if s.State then
|
||
s.State = false;
|
||
else
|
||
s.State = true;
|
||
end
|
||
s:gen();
|
||
end,
|
||
};
|
||
|
||
knife = obj {
|
||
nam = 'нож',
|
||
inv = 'Это нож',
|
||
};
|
||
|
||
inv():add(pocket);
|
||
put(knife, pocket);
|
||
pocket:gen();
|
||
|
||
main = room {
|
||
nam = 'test',
|
||
};
|
||
\end{verbatim}
|
||
|
||
\subsection{Статус}
|
||
Ниже представлена реализация статуса игрока в виде текста, который появляется в инвентаре, но не может быть выбран.
|
||
|
||
\begin{verbatim}
|
||
pl.Life = 10;
|
||
pl.Power = 10;
|
||
|
||
status = obj {
|
||
nam = 'Жизнь: '..pl.Life..',Сила: '..pl.Power,
|
||
};
|
||
inv():add('status');
|
||
status.object_type = false
|
||
\end{verbatim}
|
||
|
||
Вы можете использовать конструктор \verb/stat/ для создания статуса:
|
||
|
||
\begin{verbatim}
|
||
status = stat {
|
||
nam = function(s)
|
||
return 'Статус!!!';
|
||
end
|
||
};
|
||
|
||
inv():add('status');
|
||
\end{verbatim}
|
||
|
||
\subsection{Кодирование исходного кода}
|
||
|
||
Если вы не хотите показывать исходный код своих игр, вы можете закодировать его с помощью команды
|
||
|
||
\begin{verbatim}
|
||
sdl-instead -encode <путь к файлу> [выходной путь]
|
||
\end{verbatim}
|
||
|
||
и использовать его с помощью lua функции \verb/doencfile(путь к файлу)/.
|
||
|
||
\textbf{\textcolor{red}{Важное замечание:}} Лучше не использовать компиляцию игр с помощью luac, так как luac создаёт платформозависимый код. Таким образом, вам придётся выдавать сразу две скомпилированных версии: для 32-битных и 64-битных машин\footnote{А в будущем, возможно, SDL-INSTEAD будет поддерживать больше платформ, поэтому использовать предложенный метод будет ещё выгоднее}. Однако, компиляция игр может быть использована для поиска ошибок в коде.
|
||
|
||
\subsection{Создание собственного плейлиста}
|
||
Вы можете написать для игры свой проигрыватель музыки, создав его на основе живого объекта, например:
|
||
|
||
\begin{verbatim}
|
||
tracks = {"mus/astro2.mod", "mus/aws_chas.xm", "mus/dmageofd.xm", "mus/doomsday.s3m"}
|
||
mplayer = obj {
|
||
nam = 'плеер',
|
||
life = function(s)
|
||
local n = get_music();
|
||
local v = get_music_loop();
|
||
if not n or not v then
|
||
set_music(tracks[2], 1);
|
||
elseif v == -1 then
|
||
local n = get_music();
|
||
while get_music() == n do
|
||
n = tracks[rnd(4)]
|
||
end
|
||
set_music(n, 1);
|
||
end
|
||
end,
|
||
};
|
||
lifeon('mplayer');
|
||
\end{verbatim}
|
||
|
||
\subsection{Отладка}
|
||
Для того, чтобы во время ошибки увидеть стек вызовов функций lua, вы можете запустить
|
||
|
||
\begin{verbatim}
|
||
sdl-instead -debug
|
||
\end{verbatim}
|
||
|
||
Вы можете отлаживать свою игру вообще без instead. Например, вы можете создать следующий файл game.lua:
|
||
|
||
\begin{verbatim}
|
||
dofile("/usr/share/games/stead/stead.lua"); -- путь к stead.lua
|
||
dofile("main.lua"); -- ваша игра
|
||
game:ini();
|
||
iface:shell();
|
||
\end{verbatim}
|
||
|
||
И запустите игру в lua: \verb/lua game.lua/. При этом игра будет работать в примитивном shell окружении. Полезные команды: ls, go, act, use.... Теоретически движок можно таким образом привязать даже к CGI окружению.
|
||
|
||
\section{Создание тем для SDL-INSTEAD}
|
||
|
||
Графический интерпретатор поддерживает механизм тем.
|
||
|
||
Тема -- это инструкция к оформлению игры. Она задаёт внешний вид и положения всех информационных блоков на экране.
|
||
|
||
Тема представляет из себя каталог, с файлом \verb/theme.ini/ внутри. Файл \verb/theme.ini/ здесь является ключевым.
|
||
|
||
Тема, которая является минимально необходимой -- это тема \verb/default/. Эта тема всегда загружается первой. Все остальные темы наследуются от неё и могут частично или полностью заменять её параметры. Выбор темы осуществляется пользователем через меню настроек, однако конкретная игра может содержать собственную тему и таким образом влиять на свой внешний вид. В этом случае в каталоге с игрой должен находиться свой файл \verb/theme.ini/. Тем не менее, пользователь свободен отключить данный механизм, при этом интерпретатор будет предупреждать о нарушении творческого замысла автора игры.
|
||
|
||
Синтаксис \verb/theme.ini/ очень прост.
|
||
|
||
\begin{verbatim}
|
||
<параметр> = <значение>
|
||
; комментарий
|
||
\end{verbatim}
|
||
|
||
Значения могут быть следующих типов: строка, цвет, число.
|
||
|
||
Цвет задаётся в форме \verb/#rgb/, где \verb/r/, \verb/g/ и \verb/b/ --- компоненты цвета в шестнадцатеричном виде. Кроме того некоторые основные цвета распознаются по своим именам:
|
||
|
||
\newcommand{\tabParam}[6]{
|
||
\texttt{#1} & #2 & \texttt{#3} & #4 & \texttt{#5} & #6 & & \\
|
||
\hline
|
||
}
|
||
|
||
\newcommand{\tabsParam}[8]{
|
||
\texttt{#1} & #2 & \texttt{#3} & #4 & \texttt{#5} & #6 & \texttt{#7} & #8\\
|
||
\hline
|
||
}
|
||
|
||
\begin{table}[p]
|
||
\begin{tabular}{|l|c|l|c|l|c|l|c}
|
||
\hline
|
||
параметр & & параметр & & параметр & & параметр & \\
|
||
\hline
|
||
\tabsParam{aliceblue}{\colorbox[HTML]{F0F8FF}{T.}}{forestgreen}{\colorbox[HTML]{228B22}{T.}}{mediumvioletred}{\colorbox[HTML]{C71585}{T.}}{violet}{\colorbox[HTML]{EE82EE}{T.}}
|
||
\tabsParam{antiquewhite}{\colorbox[HTML]{FAEBD7}{T.}}{fuchsia}{\colorbox[HTML]{FF00FF}{T.}}{midnightblue}{\colorbox[HTML]{191970}{T.}}{violetred}{\colorbox[HTML]{D02090}{T.}}
|
||
\tabsParam{aqua}{\colorbox[HTML]{00FFFF}{T.}}{gainsboro}{\colorbox[HTML]{DCDCDC}{T.}}{mintcream}{\colorbox[HTML]{F5FFFA}{T.}}{wheat}{\colorbox[HTML]{F5DEB3}{T.}}
|
||
\tabsParam{aquamarine}{\colorbox[HTML]{7FFFD4}{T.}}{ghostwhite}{\colorbox[HTML]{F8F8FF}{T.}}{mistyrose}{\colorbox[HTML]{FFE4E1}{T.}}{white}{\colorbox[HTML]{FFFFFF}{T.}}
|
||
\tabsParam{azure}{\colorbox[HTML]{F0FFFF}{T.}}{gold}{\colorbox[HTML]{FFD700}{T.}}{moccasin}{\colorbox[HTML]{FFE4B5}{T.}}{whitesmoke}{\colorbox[HTML]{F5F5F5}{T.}}
|
||
\tabsParam{beige}{\colorbox[HTML]{F5F5DC}{T.}}{goldenrod}{\colorbox[HTML]{DAA520}{T.}}{navajowhite}{\colorbox[HTML]{FFDEAD}{T.}}{yellow}{\colorbox[HTML]{FFFF00}{T.}}
|
||
\tabsParam{bisque}{\colorbox[HTML]{FFE4C4}{T.}}{gray}{\colorbox[HTML]{808080}{T.}}{navy}{\colorbox[HTML]{000080}{T.}}{yellowgreen}{\colorbox[HTML]{9ACD32}{T.}}
|
||
\tabParam{black}{\colorbox[HTML]{000000}{T.}}{green}{\colorbox[HTML]{008000}{T.}}{oldlace}{\colorbox[HTML]{FDF5E6}{T.}}
|
||
\tabParam{blanchedalmond}{\colorbox[HTML]{FFEBCD}{T.}}{greenyellow}{\colorbox[HTML]{ADFF2F}{T.}}{olive}{\colorbox[HTML]{808000}{T.}}
|
||
\tabParam{blue}{\colorbox[HTML]{0000FF}{T.}}{honeydew}{\colorbox[HTML]{F0FFF0}{T.}}{olivedrab}{\colorbox[HTML]{6B8E23}{T.}}
|
||
\tabParam{blueviolet}{\colorbox[HTML]{8A2BE2}{T.}}{hotpink}{\colorbox[HTML]{FF69B4}{T.}}{orange}{\colorbox[HTML]{FFA500}{T.}}
|
||
\tabParam{brown}{\colorbox[HTML]{A52A2A}{T.}}{indianred}{\colorbox[HTML]{CD5C5C}{T.}}{orangered}{\colorbox[HTML]{FF4500}{T.}}
|
||
\tabParam{burlywood}{\colorbox[HTML]{DEB887}{T.}}{indigo}{\colorbox[HTML]{4B0082}{T.}}{orchid}{\colorbox[HTML]{DA70D6}{T.}}
|
||
\tabParam{cadetblue}{\colorbox[HTML]{5F9EA0}{T.}}{ivory}{\colorbox[HTML]{FFFFF0}{T.}}{palegoldenrod}{\colorbox[HTML]{EEE8AA}{T.}}
|
||
\tabParam{chartreuse}{\colorbox[HTML]{7FFF00}{T.}}{lavender}{\colorbox[HTML]{E6E6FA}{T.}}{palegreen}{\colorbox[HTML]{98FB98}{T.}}
|
||
\tabParam{chocolate}{\colorbox[HTML]{D2691E}{T.}}{lavenderblush}{\colorbox[HTML]{FFF0F5}{T.}}{paleturquoise}{\colorbox[HTML]{AFEEEE}{T.}}
|
||
\tabParam{coral}{\colorbox[HTML]{FF7F50}{T.}}{lawngreen}{\colorbox[HTML]{7CFC00}{T.}}{palevioletred}{\colorbox[HTML]{D87093}{T.}}
|
||
\tabParam{cornflowerblue}{\colorbox[HTML]{6495ED}{T.}}{lemonchiffon}{\colorbox[HTML]{FFFACD}{T.}}{papayawhip}{\colorbox[HTML]{FFEFD5}{T.}}
|
||
\tabParam{cornsilk}{\colorbox[HTML]{FFF8DC}{T.}}{lightblue}{\colorbox[HTML]{ADD8E6}{T.}}{peachpuff}{\colorbox[HTML]{FFDAB9}{T.}}
|
||
\tabParam{crimson}{\colorbox[HTML]{DC143C}{T.}}{lightcoral}{\colorbox[HTML]{F08080}{T.}}{peru}{\colorbox[HTML]{CD853F}{T.}}
|
||
\tabParam{cyan}{\colorbox[HTML]{00FFFF}{T.}}{lightcyan}{\colorbox[HTML]{E0FFFF}{T.}}{pink}{\colorbox[HTML]{FFC0CB}{T.}}
|
||
\tabParam{darkblue}{\colorbox[HTML]{00008B}{T.}}{lightgoldenrodyellow}{\colorbox[HTML]{FAFAD2}{T.}}{plum}{\colorbox[HTML]{DDA0DD}{T.}}
|
||
\tabParam{darkcyan}{\colorbox[HTML]{008B8B}{T.}}{lightgrey}{\colorbox[HTML]{D3D3D3}{T.}}{powderblue}{\colorbox[HTML]{B0E0E6}{T.}}
|
||
\tabParam{darkgoldenrod}{\colorbox[HTML]{B8860B}{T.}}{lightgreen}{\colorbox[HTML]{90EE90}{T.}}{purple}{\colorbox[HTML]{800080}{T.}}
|
||
\tabParam{darkgray}{\colorbox[HTML]{A9A9A9}{T.}}{lightpink}{\colorbox[HTML]{FFB6C1}{T.}}{red}{\colorbox[HTML]{FF0000}{T.}}
|
||
\tabParam{darkgreen}{\colorbox[HTML]{006400}{T.}}{lightsalmon}{\colorbox[HTML]{FFA07A}{T.}}{rosybrown}{\colorbox[HTML]{BC8F8F}{T.}}
|
||
\tabParam{darkkhaki}{\colorbox[HTML]{BDB76B}{T.}}{lightseagreen}{\colorbox[HTML]{20B2AA}{T.}}{royalblue}{\colorbox[HTML]{4169E1}{T.}}
|
||
\tabParam{darkmagenta}{\colorbox[HTML]{8B008B}{T.}}{lightskyblue}{\colorbox[HTML]{87CEFA}{T.}}{saddlebrown}{\colorbox[HTML]{8B4513}{T.}}
|
||
\tabParam{darkolivegreen}{\colorbox[HTML]{556B2F}{T.}}{lightslateblue}{\colorbox[HTML]{8470FF}{T.}}{salmon}{\colorbox[HTML]{FA8072}{T.}}
|
||
\tabParam{darkorange}{\colorbox[HTML]{FF8C00}{T.}}{lightslategray}{\colorbox[HTML]{778899}{T.}}{sandybrown}{\colorbox[HTML]{F4A460}{T.}}
|
||
\tabParam{darkorchid}{\colorbox[HTML]{9932CC}{T.}}{lightsteelblue}{\colorbox[HTML]{B0C4DE}{T.}}{seagreen}{\colorbox[HTML]{2E8B57}{T.}}
|
||
\tabParam{darkred}{\colorbox[HTML]{8B0000}{T.}}{lightyellow}{\colorbox[HTML]{FFFFE0}{T.}}{seashell}{\colorbox[HTML]{FFF5EE}{T.}}
|
||
\tabParam{darksalmon}{\colorbox[HTML]{E9967A}{T.}}{lime}{\colorbox[HTML]{00FF00}{T.}}{sienna}{\colorbox[HTML]{A0522D}{T.}}
|
||
\tabParam{darkseagreen}{\colorbox[HTML]{8FBC8F}{T.}}{limegreen}{\colorbox[HTML]{32CD32}{T.}}{silver}{\colorbox[HTML]{C0C0C0}{T.}}
|
||
\tabParam{darkslateblue}{\colorbox[HTML]{483D8B}{T.}}{linen}{\colorbox[HTML]{FAF0E6}{T.}}{skyblue}{\colorbox[HTML]{87CEEB}{T.}}
|
||
\tabParam{darkslategray}{\colorbox[HTML]{2F4F4F}{T.}}{magenta}{\colorbox[HTML]{FF00FF}{T.}}{slateblue}{\colorbox[HTML]{6A5ACD}{T.}}
|
||
\tabParam{darkturquoise}{\colorbox[HTML]{00CED1}{T.}}{maroon}{\colorbox[HTML]{800000}{T.}}{slategray}{\colorbox[HTML]{708090}{T.}}
|
||
\tabParam{darkviolet}{\colorbox[HTML]{9400D3}{T.}}{mediumaquamarine}{\colorbox[HTML]{66CDAA}{T.}}{snow}{\colorbox[HTML]{FFFAFA}{T.}}
|
||
\tabParam{deeppink}{\colorbox[HTML]{FF1493}{T.}}{mediumblue}{\colorbox[HTML]{0000CD}{T.}}{springgreen}{\colorbox[HTML]{00FF7F}{T.}}
|
||
\tabParam{deepskyblue}{\colorbox[HTML]{00BFFF}{T.}}{mediumorchid}{\colorbox[HTML]{BA55D3}{T.}}{steelblue}{\colorbox[HTML]{4682B4}{T.}}
|
||
\tabParam{dimgray}{\colorbox[HTML]{696969}{T.}}{mediumpurple}{\colorbox[HTML]{9370D8}{T.}}{tan}{\colorbox[HTML]{D2B48C}{T.}}
|
||
\tabParam{dodgerblue}{\colorbox[HTML]{1E90FF}{T.}}{mediumseagreen}{\colorbox[HTML]{3CB371}{T.}}{teal}{\colorbox[HTML]{008080}{T.}}
|
||
\tabParam{feldspar}{\colorbox[HTML]{D19275}{T.}}{mediumslateblue}{\colorbox[HTML]{7B68EE}{T.}}{thistle}{\colorbox[HTML]{D8BFD8}{T.}}
|
||
\tabParam{firebrick}{\colorbox[HTML]{B22222}{T.}}{mediumspringgreen}{\colorbox[HTML]{00FA9A}{T.}}{tomato}{\colorbox[HTML]{FF6347}{T.}}
|
||
\tabParam{floralwhite}{\colorbox[HTML]{FFFAF0}{T.}}{mediumturquoise}{\colorbox[HTML]{48D1CC}{T.}}{turquoise}{\colorbox[HTML]{40E0D0}{T.}}
|
||
\end{tabular}
|
||
\end{table}
|
||
|
||
\subsection{Параметры окна изображений}
|
||
|
||
Окно изображений --- область, в которой располагается картинка сцены. Интерпретация зависит от режима расположения.
|
||
|
||
Для окна изображений заданы следующие параметры:
|
||
|
||
\medskip
|
||
|
||
\renewcommand{\tabParam}[3]{
|
||
\texttt{#1} & #2 & #3 \\
|
||
\hline
|
||
}
|
||
\begin{table}[h]
|
||
\begin{tabular}{|l|c|l|}
|
||
\hline
|
||
параметр & тип & описание \\
|
||
\hline
|
||
\tabParam{scr.w}{число}{ширина игрового пространства, пиксели}
|
||
\tabParam{scr.h}{число}{высота игрового пространства, пиксели}
|
||
\tabParam{scr.col.bg}{цвет}{цвет фона}
|
||
\tabParam{scr.gfx.bg}{строка}{путь к файлу фонового изображения}
|
||
\tabParam{scr.gfx.cursor.x}{число}{абсцисса центра курсора, пиксели}
|
||
\tabParam{scr.gfx.cursor.y}{число}{ордината центра курсора, пиксели}
|
||
\tabParam{scr.gfx.cursor.normal}{строка}{путь к картинке-курсору}
|
||
\tabParam{scr.gfx.cursor.use}{строка}{путь к картинке-курсору режима использования}
|
||
\tabParam{scr.gfx.use}{строка}{путь к картинке-индикатору режима использования}
|
||
\tabParam{scr.gfx.pad}{число}{размер отступов к скролл-барам и краям меню, пиксели}
|
||
\tabParam{scr.gfx.x}{число}{абсцисса окна изображений, пиксели}
|
||
\tabParam{scr.gfx.y}{число}{ордината окна изображений, пиксели}
|
||
\tabParam{scr.gfx.w}{число}{ширина окна изображений, пиксели}
|
||
\tabParam{scr.gfx.h}{число}{высота окна изображений, пиксели}
|
||
\tabParam{win.gfx.h}{число}{синоним \texttt{scr.gfx.h}}
|
||
\tabParam{scr.gfx.mode}{строка}{режим расположения}
|
||
\end{tabular}
|
||
\end{table}
|
||
|
||
\medskip
|
||
|
||
Параметр \verb/scr.gfx.mode/ может принимать одно из значений: \verb/fixed/, \verb/embedded/ или \verb/float/.
|
||
|
||
В режиме \verb/embedded/ картинка является частью содержимого главного окна, параметры главного окна (см. ниже) \verb/win.x/, \verb/win.y/, \verb/win.w/ игнорируются.
|
||
|
||
В режиме \verb/float/ картинка расположена по указанным координатам (\verb/win.x/, \verb/win.y/) и масштабируется к размеру \verb/win.w/ x \verb/win.h/ если превышает его.
|
||
|
||
В режиме \verb/fixed/ -- картинка является частью сцены как в режиме \verb/embedded/, но не скроллируется вместе с текстом, а расположена непосредственно над ним.
|
||
|
||
\subsection{Параметры главного окна}
|
||
|
||
Главное окно --- область, в которой располагается описание сцены.
|
||
Для главного окна заданы следующие параметры:
|
||
|
||
\medskip
|
||
|
||
\begin{table}[h]
|
||
\begin{tabular}{|l|c|l|}
|
||
\hline
|
||
параметр & тип & описание \\
|
||
\hline
|
||
\tabParam{win.x}{число}{абсцисса главного окна, пиксели}
|
||
\tabParam{win.y}{число}{ордината главного окна, пиксели}
|
||
\tabParam{win.w}{число}{ширина главного окна, пиксели}
|
||
\tabParam{win.h}{число}{высота главного окна, пиксели}
|
||
\tabParam{win.fnt.name}{строка}{путь к файлу шрифта}
|
||
\tabParam{win.fnt.size}{число}{размер шрифта главного окна, пункты}
|
||
\tabParam{win.gfx.up}{строка}{путь к файлу изображения скроллера вверх для главного окна}
|
||
\tabParam{win.gfx.down}{строка}{путь к файлу изображения скроллера вниз для главного окна}
|
||
\tabParam{win.gfx.h}{число}{синоним \texttt{scr.gfx.h}}%интересно, почему для scr.gfx.w нету?
|
||
\tabParam{win.col.fg}{цвет}{цвет текста главного окна}
|
||
\tabParam{win.col.link}{цвет}{цвет ссылок главного окна}
|
||
\tabParam{win.col.alink}{цвет}{цвет активных ссылок главного окна}
|
||
\end{tabular}
|
||
\end{table}
|
||
|
||
\medskip
|
||
|
||
\subsection{Параметры области инвентаря}
|
||
|
||
Для области инвентаря заданы следующие параметры:
|
||
|
||
\medskip
|
||
|
||
\begin{table}[h]
|
||
\begin{tabular}{|l|c|l|}
|
||
\hline
|
||
параметр & тип & описание \\
|
||
\hline
|
||
\tabParam{inv.x}{число}{абсцисса области инвентаря,пиксели}
|
||
\tabParam{inv.y}{число}{ордината области инвентаря,пиксели}
|
||
\tabParam{inv.w}{число}{ширина области инвентаря,пиксели}
|
||
\tabParam{inv.h}{число}{высота области инвентаря,пиксели}
|
||
\tabParam{inv.col.fg}{цвет}{цвет текста инвентаря}
|
||
\tabParam{inv.col.link}{цвет}{цвет ссылок инвентаря}
|
||
\tabParam{inv.col.alink}{цвет}{цвет активных ссылок инвентаря}
|
||
\tabParam{inv.fnt.name}{строка}{путь к шрифту инвентаря}
|
||
\tabParam{inv.fnt.size}{число}{размер шрифта инвентаря,пункты}
|
||
\tabParam{inv.gfx.up}{строка}{путь к изображению скроллера вверх для инвентаря}
|
||
\tabParam{inv.gfx.down}{строка}{путь к изображению скроллера вниз для инвентаря}
|
||
\tabParam{inv.mode}{строка}{режим инвентаря}
|
||
\end{tabular}
|
||
\end{table}
|
||
|
||
\medskip
|
||
|
||
Параметр \verb/inv.mode/ может принимать значение \verb/horizontal/ или \verb/vertical/.
|
||
|
||
В горизонтальном режиме инвентаря в одной строке могут быть несколько предметов. В вертикальном режиме, в каждой строке инвентаря содержится только один предмет.
|
||
|
||
\subsection{Параметры главного меню}
|
||
|
||
Для главного меню INSTEAD-SDL заданы следующие параметры:
|
||
|
||
\medskip
|
||
|
||
\begin{table}[h]
|
||
\begin{tabular}{|l|c|l|}
|
||
\hline
|
||
параметр & тип & описание \\
|
||
\hline
|
||
\tabParam{menu.col.bg}{цвет}{цвет фона меню}
|
||
\tabParam{menu.col.fg}{цвет}{цвет текста меню}
|
||
\tabParam{menu.col.link}{цвет}{цвет ссылок меню}
|
||
\tabParam{menu.col.alink}{цвет}{цвет активных ссылок меню}
|
||
\tabParam{menu.col.alpha}{цвет}{прозрачность меню (0---255)}
|
||
\tabParam{menu.col.border}{цвет}{цвет границы меню}
|
||
\tabParam{menu.bw}{число}{толщина границы меню, пиксели}
|
||
\tabParam{menu.fnt.name}{строка}{путь к шрифту меню}
|
||
\tabParam{menu.fnt.size}{число}{размер шрифта меню, пункты}
|
||
\tabParam{menu.gfx.button}{строка}{путь к значку меню}
|
||
\tabParam{menu.button.x}{число}{абсцисса кнопки меню, пиксели}
|
||
\tabParam{menu.button.y}{число}{ордината кнопки меню, пиксели}
|
||
\tabParam{snd.click}{строка}{путь к звуку щелчка}
|
||
\tabParam{include}{строка}{имя темы}
|
||
\end{tabular}
|
||
\end{table}
|
||
|
||
\medskip
|
||
|
||
Напоминаю,что имя темы есть имя каталога с нею.
|
||
|
||
\subsection{Прочее}
|
||
|
||
Кроме того, заголовок темы может включать в себя комментарии с тегами. На данный момент существует только один тег: \verb/$Name:/, содержащий строку с именем темы. Например:
|
||
|
||
\begin{verbatim}
|
||
; $Name:Новая тема$
|
||
; модификация темы book
|
||
include = book
|
||
scr.gfx.h = 500
|
||
\end{verbatim}
|
||
|
||
Интерпретатор ищет доступные темы в каталогах:
|
||
|
||
Unix версия интерпретатора просматривает игры в:\\
|
||
\verb;/usr/local/share/instead/themes; (по умолчанию),\\
|
||
\verb,~/.instead/themes,.\\
|
||
WinXP версия:\\
|
||
\verb;Documents and Settings/USER/Local Settings/Application Data/instead/themes;\\
|
||
WinVista: \verb;Users\USER\AppData\Local\instead\themes;\\
|
||
Все Windows: \verb;куда-вы-установили-INSTEAD/themes;
|
||
|
||
|
||
Игра может задавать собственную тему; для этого в каталоге с игрой должен лежать тот самый \verb/theme.ini/. Его формат никак при этом не меняется, просто он загружается в первую очередь вместе с игрой.
|
||
|
||
\section{Дополнительные источники документации}
|
||
Вот и закончен справочник по INSTEAD. Напомним, что INSTEAD расшифровывается (и переводится) как <<Интерпретатор простых текстовых приключений>>. Официальная документация находится в каталоге doc и поставляется с instead. Дополнительную информацию вы можете получить в Интернете:
|
||
|
||
\begin{itemize}
|
||
\item \href{http://instead.googlecode.com/}{Сайт программы}
|
||
\item \href{http://instead.pinebrush.com/}{Форум программы}
|
||
\end{itemize}
|
||
\end{document}
|