Авторизация
×

Логин (e-mail)

Пароль

Интерактивные истории, текстовые игры и квесты
Гиперкнига

Библиотека    Блог

Посетите наш новый сайт AXMAJS.RU

Пишем интерактивную историю вместе. Часть 3-я

Борис Семёнов (Morych), 09.03.13 | Практика ASM

Объекты

Объекты применяются в ASM для хранения каких-либо значений. Значением этим может быть число или строка (набор символов). Каждому объекту автор истории придумывает уникальное имя (двух объектов с одинаковыми именами не бывает) и это имя всегда должно начинаться с символа «$». В именах могут содержаться как русские, так и английские буквы, цифры и знаки подчёркивания. А вот пробелы и любые другие знаки использовать в именах объектов нельзя.

Кстати имена лучше всего придумывать с тем расчётом, чтобы в них были отражены назначения объектов. Например, некто дал нашему герою два яблока. Чтобы запомнить количество яблок, нам нужно будет создать объект «$яблоки» или «$Число_Фруктов» или «$applesCount» и установить значение этого объекта в 2. Скоро мы начнём применять объекты на практике, и тогда всё станет понятнее.

Все объекты в ASM являются глобальными, то есть однажды присвоив объекту значение в каком-либо параграфе, мы сможем получить это значение во всех последующих параграфах. До тех пор, пока читатель не нажмёт кнопку «Начать заново» в готовой истории.

В редакторе параграфов есть специальная кнопка «Объекты», при нажатии на которую раскрывается список всех существующих в нашей истории объектов. Щелчком на соответствующем пункте списка имя объекта вставляется в позицию курсора. Задавать объектам значения и выполнять обработку этих значений можно при помощи макросов.

Макросы

Макросы — это специальные слова и выражения в ASM, которые облегчают работу автора, а также позволяют сделать историю динамической, живой. Все макросы называются по-английски и заключаются в парные угловые скобки (<<…>>) благодаря чему их всегда можно распознать. А список всех макросов раскрывается по кнопке «Макросы» в редакторе параграфов.

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

Сгоревший дом

<<set $сцена = 'Сгоревший дом'>>
<<display 'Заголовок'>>
Какой же это был хороший дом! Крепкий, добротный, срубленный из душистых сосновых брёвен! А теперь... мрачные чёрные обломки дымятся в горах золы. И лишь одинокая [[+каменная печь|Про печь]] сиротливо стоит посреди пепелища. Но самое ужасное, что всё [[+добро|Подробнее о добре]] пропало!
[[Пойти со двора|Старое селение]]

Первый макрос «set» (от англ. «установить») создаёт объект «$сцена» и присваивает ему определённое значение. В нашем случае, это название текущей сцены. Название — это строка, а строковые значения нужно заключать в одинарные кавычки (апострофы). Макрос «set» хоть и написан в тексте параграфа, но на экран он не выводится.

Второй макрос «display» (от англ. «отобразить») выводит на экран вместо себя текст параграфа «Заголовок». В этом служебном параграфе «Заголовок» мы и опишем требуемое оформление всех заголовков. Отныне все параграфы с описанием сцен будем начинать с этих двух строчек, меняя только название сцены в макросе «set».

Нажмём правой кнопкой мыши на макросе «display», и выберем пункт меню «Перейти по ссылке». В добавленном параграфе «Заголовок» тоже используем макрос.

Заголовок

===''<<print $сцена>>''===
----

Макрос «print» (от англ. «печатать») выводит на экран вместо себя значение объекта «$сцена». Окружаем макрос теми же символами форматирования текста, которые мы использовали для выделения заголовка сцены.

Разнообразие описаний и условные операторы

Довольно нашему герою сидеть на месте. Пусть уже куда-нибудь идёт. Для этого создадим новый параграф-сцену «Старое селение». С этой сцены можно будет попасть в дом старейшины, вернуться к сгоревшему дому и покинуть селение после разговора с второстепенным персонажем.

Старое селение

<<set $сцена = 'Старое селение'>>
<<display 'Заголовок'>>
Селение наше было невелико. Всего-то десяток дворов. А ведь бывают селения, где дворов этих даже не два десятка -- сотня! Сам-то я не видал, но слухи такие слыхивал.
Я как рассудил, слезами горю не поможешь, верно же? Стало быть, нечего кручиниться сидеть, когда можно совета путного спросить! А кто подскажет лучше, чем дед Закром, над всеми домовыми в нашем селении голова?! К нему-то я и решил отправиться.
[[Идти к дому старейшины|Дом старейшины]]
[[Вернуться на пепелище|Сгоревший дом]]

Можно было бы оставить описание и таким, но мы не будем этого делать. А дело вот в чём. Представим, что читатель перешёл с этого параграфа на параграф «Дом старейшины», а затем снова вернулся сюда. Он увидит, конечно, то же самое описание, где герой решает отправиться к старейшине. Как будто и не ходил никуда. Чтобы читателю не приходилось несколько раз перечитывать одно и то же, и чтобы читатель видел, что сюжет истории развивается, при повторном посещении сцены нужно выводить другое описание.

Придумаем ещё три коротеньких описания сцены для второго и всех последующих посещений. Параграф преобразится следующим образом:

Старое селение

<<set $сцена = 'Старое селение'>>
<<display 'Заголовок'>>
<<if $селение eq 1>>
    Селение наше было невелико. Всего-то десяток дворов. А ведь бывают селения, где дворов этих даже не два десятка -- сотня! Сам-то я не видал, но слухи такие слыхивал.
    Я как рассудил, слезами горю не поможешь, верно же? Стало быть, нечего кручиниться сидеть, когда можно совета путного спросить! А кто подскажет лучше, чем дед Закром, над всеми домовыми в нашем селении голова?! К нему-то я и решил отправиться.
<<elseif $селение eq 2>>
    Я топал по единственной улице нашего селения, раздумывая над своей нелёгкой судьбинушкой.
<<elseif $селение eq 3>>
    Вновь я шагал по пыльной сельской улице, не глядя вокруг. Горькие думы о сгинувшем [[+добре|Подробнее о добре]] всё никак не шли из головы.
<<else>>
    Жаркое солнце уж давно взобралось на самую маковку неба, а я всё вышагивал по узкой сельской улице.
    <<set $селение = 1>>
<<endif>>
<<set $селение++>>

[[Идти к дому старейшины|Дом старейшины]]
[[Вернуться на пепелище|Сгоревший дом]]

В самом начале истории мы создадим объект «$селение», в котором будем запоминать номер описания сцены «Старое селение». Первоначально значение объекта «$селение» будет равно 1. Чтобы в соответствии со значением объекта вывести то или иное описание, мы использовали набор макросов «if ... elseif ... else ... endif» (от англ. «если ... иначе если ... иначе ... конец если»). Эти макросы ещё называются условными операторами.

В первом макросе «if» выполняется проверка условия. Служебное слово «eq» — это сокращение от английского «equals», что переводится как «равно». Итак, в переводе на человеческий язык в макросе «if» у нас написано: «Если значение объекта «$селение» равно 1». Это условие соответствует истине при первом посещении параграфа. А раз условие истинно, на экран будет выведен блок текста, следующий сразу за макросом «if». Тот самый текст, который выводился в первом варианте параграфа. Остальной текст, вплоть до макроса «endif» в этот раз выводиться не будет.

Приведу общую схему блока условных операторов:

<<if условие1>>
    Этот текст выводится, если условие1 верно.
<<elseif условие2>>
    Этот текст выводится, если условие1 не верно, а условие2 верно.
...
<<elseif условиеN>>
    Этот текст выводится, если все предыдущие условия не верны, а условиеN верно.
<<else>>
    А этот текст будет выведен только в том случае, если ни одно из предыдущих условий не оказалось верным.
<<endif>>

Таким образом, макрос «if» открывает блок условий, а «endif» — закрывает. Эти два макроса обязательны. А вот макросы «elseif» и «else» могут отсутствовать, если они не нужны.

Вернёмся к нашему параграфу. Там, после условных операторов, перед ссылками добавился уже знакомый нам макрос «set», в котором мы изменяем значение объекта «$селение». Два плюса означают увеличение значения объекта на 1. Это сочетание знаков используется во многих языках программирования. Можно было написать этот макрос по-другому:

<<set $селение = $селение + 1>>

Такая запись также означает, что значение объекта будет увеличено на 1. В нашем случае значение объекта будет увеличиваться каждый раз при посещении параграфа «Старое селение».

Когда читатель перейдёт на параграф «Старое селение» во второй раз (значение объекта «$селение» увеличилось с 1 до 2) выражение в макросе «if» будет ложно, и следовательно первое описание сцены читатель уже не увидит. Если условие в первом макросе не срабатывает, начинается проверка условия во втором макросе «elseif». И поскольку условие «если значение объекта «$селение» равно 2» теперь истинно, читатель увидит блок текста следующий за этим «elseif». Аналогично сработает и следующий «elseif», когда читатель увидит параграф третий раз.

А что произойдёт, когда читатель перейдёт на этот параграф четвёртый раз? Не сработают ни первое условие, ни второе, ни третье. В таких случаях выводится текст, следующий за макросом «else», в котором вообще никаких условий нет. Кроме текста описания после макроса «else» мы добавили ещё и макрос «set», который тоже сработает только в этот раз и установит значение объекта «$селение» в 1. В следующем «set», который находится после «endif», значение этого объекта увеличится до 2. Вот мы и зациклили вывод описаний. В следующее посещение параграфа читатель увидит второе по счёту описание и т.д. по кругу. Первое описание в этом цикле не участвует, так как мы договорились показывать его только один раз.

Неплохо бы оформить похожим образом все параграфы с описаниями сцен. Причём, чем больше вариантов описаний будет для каждой сцены, тем лучше. Останется всего лишь добавить требуемое количество макросов «elseif». Однако долго сидеть над выдумыванием большого количества описаний не стоит, иначе можно никогда не закончить историю. Для начала вполне хватит и двух описаний для каждой сцены: одно — для первого посещения, и второе, сокращённое — для всех последующих. При этом, если в описании содержится какая-то ключевая информация, необходимая для дальнейшего продвижения по сюжету, читатель должен иметь возможность ознакомиться с ней и при повторном посещении сцены.

Продолжение следует...

Комментарии: 16.

Профиль


Закрыть

Показать все комментарии

Д. А. Февраль и А. И. Зимовский
10.08.17 08:03

Евгений, чтобы разработчику было проще ориентироваться в параграфах когда их станет слишком много
Tony Hawk
17.12.17 14:28

Не могу присвоить макросу set значение 'Сгоревший дом', выдает две ошибки: отсутствует $ или кавычки: Сгоревший...тоже самое: дом.
Tony Hawk
17.12.17 16:36

Проблема решена заключением в двойные кавычки.

Для того, чтобы оставлять комментарии, необходимо зарегистрироваться и подтвердить в профиле указанный e-mail адрес.

При использовании любых материалов блога обязательно указание ссылки на источник