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

Логин (e-mail)

Пароль

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

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

Использование модуля «Inventory». Часть 1-я

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

Предположим, у нас есть простейшая история с двумя сценами: дом и рынок. Цель игры: сходить на рынок, купить там что-нибудь и вернуться домой. Добавляем в историю модуль «Inventory».

Появились 11 новых параграфов. Название каждого из них начинается с «m_». Учтите, что в процессе добавления модуля ASM выполнит автоматическую расстановку всех параграфов проекта. Поэтому, если вы предпочитаете работать в визуальном режиме редактора, расставляя параграфы вручную, добавляйте модуль в самом начале разработки.

Кроме стандартного, есть и другой способ добавления модуля, при котором позиция параграфов не собьётся. Откройте модуль в ASM, переключитесь в режим текстового редактора и скопируйте весь код в буфер обмена (Ctrl+A, Ctrl+C). Затем откройте целевой проект и вставьте скопированный код в самом низу. Переключившись в визуальный режим, вы увидите, что все параграфы проекта остались на своих местах.

Настройка предметов

Начинаем настройку модуля с параграфа m_Init и редактируем списки со свойствами предметов:

<<set $m_listItem = ["авоську", "большую матрёшку", "среднюю матрёшку", "маленькую матрёшку", "копилку", "кирпич", "бусы", "подарочную коробку", "бантик"]>>
<<set $m_listPosition = ["гг", "Хмурый торговец", "большую матрёшку", "среднюю матрёшку", "Ваш дом", "Рынок", "Радостный торговец", "Хмурый торговец", "Радостный торговец"]>>
<<set $m_listVolume = [15, 3, 2, 1, 5, 4, 2, 4, 1]>>
<<set $m_listSpace = [15, 0, 0, 0, 0, 0, 0, 3, 0]>>
<<set $m_listPrice = [5, 15, 12, 9, 35, 0, 45, 10, 4]>>

Названия предметов записываем в винительном падеже. В первом списке $m_listItem у нас получилось 9 предметов, значит все прочие списки должны также содержать по 9 элементов. Остальные свойства предметов (позиция $m_listPosition, объём $m_listVolume, пространство $m_listSpace и цена $m_listPrice) должны следовать в том же порядке, в котором перечислены названия предметов в первом списке.

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

Под пространством внутри предмета понимается оставшееся свободное место. Например, большая матрёшка является контейнером, но в списке $m_listSpace второй элемент равен 0. Мы учли, что в большой матрёшке изначально находится средняя, и другие предметы в неё теперь не поместятся.

Свойства предметов мы настроили, теперь нужно не забыть вызвать параграф m_Init в начале истории. Например, в параграфе Start:

<<display "m_Init">>
<<set $onMarket = false>>
<<set $present = 0>>
===[[''Играть!''|Дом]]===

Здесь мы также объявили объекты $onMarket и $present, которые понадобятся нам в игре.

Для каждого предмета игры нужно создать отдельный параграф, название которого должно совпадать с названием предмета (учитывая падеж). Для предметов-контейнеров дублируем параграф m_коробку и редактируем его. Например, так будет выглядеть параграф авоську:

<<if $m_boxMode>>[[Положить в авоську|m_Move {$m_newPosition = "авоську"} {$m_market = 0}]]<<else>>[[*авоську|m_ItemActions {$m_item = "авоську"} {$m_description = "Хорошая крепкая авоська. Ходить с такой на рынок -- одно удовольствие."}]]<<endif>>

Мы просто заменили в параграфе все слова «m_коробку» на «авоську» и поменяли описание предмета. Обратите внимание, что весь текст параграфа должен быть записан в одну строку.

Для предметов, которые не являются контейнерами, дублируем и аналогично редактируем параграф m_предмет. К примеру, вот параграф кирпич:

[[*кирпич|m_ItemActions {$m_item = "кирпич"} {$m_description = "Красный глиняный кирпич. Ваш дом выстроен как раз из таких."}]]

В готовой истории параграфы-образцы m_коробку и m_предмет можно удалить.

Настройка сцен

Теперь обратимся к параграфу Дом, который описывает первую игровую сцену:

<<set $m_location = "Ваш дом">>
<<display "m_Title">>
Вы дома. Через окна в комнату льётся солнечный свет.
<<if not $onMarket>>
    Сегодня особенный день! День рождения мамы. Пока её нет, можно сходить на рынок и купить ей подарок.
    <<display "Шкаф">>
<<else>>
    На рынок вы уже сходили, и теперь можно подождать маму.
    [[Дожидаться маму|Поздравление]]
    [[+Порыться в шкафу|Шкаф]]
<<endif>>
[[Идти на рынок|Рынок]]

Первым делом нужно занести в объект $m_location название сцены, после чего можно показывать заголовок m_Title. Значение объекта $onMarket будет установлено в true, когда герой побывает на рынке.

Параграф Шкаф перечисляет предметы, содержащиеся на сцене:

<<set $m_position = $m_location>>
<<set $m_textPosition = "Хорошенько порывшись в шкафу, вы находите">>
<<set $m_textEmpty = "Вы снова роетесь в шкафу, но ничего полезного там нет.">>
<<display "m_Items">>

До вызова m_Items, устанавливаем значения трёх объектов: позицию перечисления $m_position (приравниваем её к названию сцены), текст до перечисления $m_textPosition и текст при отсутствии предметов на сцене $m_textEmpty.

Мы выделили перечисление предметов сцены в отдельный параграф, чтобы до посещения рынка предметы сцены показывались автоматически, а после — по нажатию ссылки «Порыться в шкафу».

Параграф Рынок, описывающий одноимённую сцену, ещё проще:

<<set $m_location = "Рынок">>
<<display "m_Title">>
<<set $onMarket = true>>
Вы на рынке. Здесь шумно -- торговцы кричат, зазывая покупателей и расхваливая свой товар. Ваше внимание привлекают два торговца.
<<set $m_position = $m_location>>
<<set $m_textPosition = "Под кустом вы замечаете">>
<<set $m_textEmpty = "">>
<<display "m_Items">>
[[Подойти к радостному торговцу|РадостныйТорговец]]
[[Подойти к хмурому торговцу|ХмурыйТорговец]]
[[Вернуться домой|Дом]]

Если при отсутствии предметов на сцене мы не хотим ничего сообщать, заносим в объект $m_textEmpty пустую строку (две кавычки подряд).

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

<<set $m_location = "Рынок">>
<<display "m_Title">>
<<if not $m_action>>
    <<set $onMarket = true>>
    Вы на рынке. Здесь шумно -- торговцы кричат, зазывая покупателей и расхваливая свой товар. Ваше внимание привлекают два торговца.
    <<set $m_position = $m_location>>
    <<set $m_textPosition = "Под кустом вы замечаете">>
    <<set $m_textEmpty = "">>
    <<display "m_Items">>
<<else>>
    [[Осмотреться|Рынок {$m_action = 0}]]
<<endif>>

[[Подойти к радостному торговцу|РадостныйТорговец]]
[[Подойти к хмурому торговцу|ХмурыйТорговец]]
[[Вернуться домой|Дом]]

Теперь описание сцены и перечисление находящихся на ней предметов будут отображаться только в том случае, если герой не выполнял действий с предметами (т.е. при переходе с другой сцены или по нажатию ссылки «Осмотреться»).

Настройка уникальных действий

Для каждого предмета помимо автоматических базовых можно задать уникальные авторские действия. Для этого редактируем параграф m_SpecialActions:

<<if ($m_item eq "бантик") and ($m_listPosition[7] eq $m_hero)>>
    [[Прицепить бантик на коробку|ПрицепитьБантик]]
<<elseif $m_item eq "подарочную коробку">>
    <<if $m_listPosition[8] eq "+">>
        С бантиком коробка выглядит ещё лучше.
    <<else>>
        Вас не покидает чувство, что на коробке чего-то не хватает.
    <<endif>>
<<elseif ($m_item eq "копилку") or (($m_item eq "кирпич") and ($m_listPosition[4] eq $m_hero))>>
    [[Разбить копилку|РазбитьКопилку]]
<<endif>>

Когда герой выбирает какой-либо предмет, содержимое параграфа m_SpecialActions выводится сразу после статичного описания предмета. Название выбранного предмета содержится в объекте $m_item. Итак, первое условие сработает, если выбран бантик и герой держит предмет с индексом 7 (подарочную коробку) в руках. Напомню, что отсчёт индексов в списках начинается с 0. При срабатывании второго условия (если герой рассматривает подарочную коробку) вместо действий выводится дополнительное описание, которое зависит от позиции предмета с индексом 8 (бантика). Наконец, третье условие сработает, если выбрана копилка, либо выбран кирпич, но копилка (индекс 4) тоже находится в руках.

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

<<set $m_listPosition[8] = "+">>
<<set $m_listVolume[7] = $m_listVolume[7] + $m_listVolume[8]>>
<<set $m_textAction = "Пришлось изрядно повозиться, но вам, наконец, удалось прикрепить бантик к подарочной коробке.">>
<<set $m_action = 100>>
<<display "m_RefreshLocation">>

Мы изменили позицию бантика, чтобы он исчез из инвентаря. Затем добавили к объёму подарочной коробки объём бантика, задали текст действия $m_textAction и установили произвольный код действия $m_action. (Вообще код действия имеет смысл устанавливать в случаях, если предполагается реакция сцены или персонажей на действия героя.) В самом конце вызываем параграф m_RefreshLocation для обновления текущей сцены.

Параграф РазбитьКопилку немного сложнее, поскольку нам нужно проверить, какой именно предмет использует герой. Кроме того, результат действия будет зависеть и от сцены, на которой герой находится.

<<set $m_action = 101>>
<<if $m_item eq "кирпич">>
    <<set $m_listPosition[4] = "-">>
    <<if $m_location neq "Ваш дом">>
        <<set $m_textAction = "Поцеловав напоследок копилку в пятачок и тяжело вздохнув, вы разбили её кирпичом. Монеты посыпались в дорожную пыль, и прохожие радостно бросились их собирать вместе с вами.">>
        <<set $m_money = $m_money + 50 + Math.round(Math.random() * 5)>>
    <<else>>
        <<set $m_textAction = "Поцеловав напоследок копилку в пятачок и тяжело вздохнув, вы разбили её кирпичом и собрали все накопленные деньги.">>
        <<set $m_money = $m_money + 100 + Math.round(Math.random() * 5)>>
    <<endif>>
<<else>>
    <<set $m_textAction = "Вы никогда прежде не разбивали копилок, но предполагаете, что если грохнуть её об землю, накопленные деньги разлетятся во все стороны. Вы не можете так рисковать, здесь нужно что-то тяжёлое.">>
<<endif>>
<<display "m_RefreshLocation">>

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

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

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

Профиль


Закрыть
Евгений Туголуков (Korwin)
02.05.13 07:39

Великолепный инструмент! Благодарю.
Morych
03.05.13 17:40

Спасибо! А вот и продолжение: http://hyperbook.ru/blog.php?id=13675876457746

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

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