8. ПРЕДМЕТЫ
Предметы, корзина, брать, класть, применять




Предметы и корзина

Предметы (item objects), которые игрок может нести с собой, представляются в виде динамических кистей (dynamic brushes). В процессе игры их можно брать, выкладывать или же применять к различным активным объектам (action objects). Именно с помощью предметов решается большинство головоломок, чинятся сломанные вещи, открываются двери и разрешаются проблемы других персонажей игры.

Давайте заглянем в прилагающийся пример, и откроем карту в редакторе. Выберите тайл (tile) с id (идентификатором) 211, и отметьте область по координатам 32,32, размером 16x16 точек, отображающую ведро. Откройте окно свойств кисти, и установите тип кисти dynamic (динамический), object id (идентификатор объекта) 100, а class (класс) обьекта item (предмет). Установите draw property (свойства рисования) равным 1 (img), т.к. динамические объекты все равно не отрисовываются в карте материалов (material map), а рисуются только на экране. Так же, при желании можно установить brush shader (метод наложения) opaque (непрозрачный), и разместить объект в одном из слоев (layer) со старшим приоритетом, например в слое 4, таким образом, ваш предмет будет всегда отображаться поверх остальных активных объектов.

Теперь присвоим вашему предмету имя. Под этим именем предмет будет отображаться в корзине (inventory), и вы сможете его выкладывать или применять.

Откройте скрипт game.gs и добавьте следующую строчку в конец функции ObjectsSetNames. Сохраните файл, и запустите игру. Нажмите 'применить' на фоне ведра и увидите, что оно появилось в вашей корзине. Закройте корзину, отойдите в другое место экрана и откройте корзину снова. Выберите ведро, и вы выложите его на том месте экрана, где находитесь теперь.



ObjSetName(idx, name)

Предметы - это динамические кисти с установленным классом item (предмет) и заданным id.

Данная функция передает движку имя объекта привязанное ко внутреннему индексу в списке динамических кистей (используйте функцию ObjFind, чтобы получить индекс). Обычно имя предметам присваивается внутри колбека ObjectsSetNames, располагающегося в файле game.gs, и вызывается каждый раз в начале новой игры. В процессе игры имя предмета можно изменять, но тогда вам придется написать дополнительный код для корректной работы загрузки/выгрузки состояния игры.

Для других объектов имя устанавливать не нужно, поскольку только предметы могут отображаться в корзине. Однако предметам имена давать необходимо, иначе в корзине вы увидите вместо них пустые строчки.



Применение предметов

Давайте посмотрим, как применять предмет к персонажу, нуждающемуся в нем. Откроем карту в редакторе, и добавим активного персонажа, как это было показано в предыдущей главе. На этот раз персонажем будет Дилан (tile=175, id=1000, class=action). Сохраните карту.

Теперь необходимо добавить специальную колбек-функцию для обработки выкладывания предмета на фоне Дилана. Это называется 'давать' или 'использовать' предмет по отношению к активному объекту. Добавьте следующую функцию в файл game.gs, затем запустите игру, возьмите ведро и дайте его Дилану.




UseObject_ID( idx )

Этот фоновой колбек вызывается из хендлера обработки нажатия клавиши 'использовать' (action handler), когда игрок использует (пытается выложить) предмет на фоне активного объекта с тем же id (идентификатором), который задан в имени функции (ID). Параметр idx - это внутренний индекс предмета.
Таким способом вы можете написать для активного объекта всего одну функцию UseObject, и уже в ней по индексу проверять вещи, применяемые к этому объекту.

Колбек ActionObject_ID имеет более высокий приоритет, нежели UseObject_ID, и если присутствуют обе функции, то автоматически будет вызвана только ActionObject_ID.


В предыдущем примере Дилан отвечает одной и той же фразой на все предметы, примененные к нему. Это потому, что в функции обработки не проверялся индекс предмета. Давайте теперь это исправим. Добавьте еще один предмет - красное ведро (цвет задается в редакторе) с id=101. Присвоим ему имя "RED BUCKET". А так же допишем нижеприведенные строчки в функцию UseObject для Дилана. Запишите, запустите и посмотрите результат.




Получение предметов

Получать предметы еще проще. Фактически, предмет существует все время, но его кисть заблокирована (disabled) по умолчанию, что запрещает видеть и брать данный предмет. Однако, когда необходимо, предмет можно разрешить (enable) и после этого уже видеть и брать его, как и все остальные предметы.

Итак, добавим еще один предмет. На этот раз это будет маленький зеленый листик с tile=218. Не забудьте установить его тип dynamic (динамический), класс item (предмет), и id=102. Назовем его "LEAFS". Установим свойство disable равным 1 (запретить объект). Теперь поместим листик рядом с Диланом. Так же добавим в обработчик UseObject для Дилана нижеприведенные строки, и запустим игру. Теперь можно передать красное ведро Дилану, а взамен он даст вам листик, который до этого был недоступен.




Корзина

Теперь, когда вы кратко познакомились с возможностями корзины, углубимся в некоторые подробности ее работы.

Корзина (The Inventory) содержит предметы, которые несет при себе игрок. Предметы из корзины содержатся в списке, который начинается с переменной G_INVENTORY, и адресуются по внутреннему индексу объекта. Когда вы берете предмет, на самом деле он остается на месте, но отключается посредством установки свойства O_DISABLE равным 1. Его индекс при этом добавляется в список предметов. Когда же вы выкладываете предмет, он перемещается на текущую позицию, занимаемую игроком, посредством изменения свойств O_X и O_Y, и разрешается снова, установкой свойства O_DISABLE равным 0.

По умолчанию, в корзине можно нести до трех предметов. Но вы можете изменить этот параметр в переменной MAXINVENTORY, располагающейся в файле gamedef.gs

Большинство функций для работы с корзиной находится в файле inventory.gs.


InventoryCount()
Функция возвращает количество предметов, находящихся в корзине.

InventoryAdd( idx )
Эта функция позволяет добавить предмет в корзину, посредством указания его внутреннего индекса. Если в корзине больше нет свободного места, то функция выдаст ошибку, возвратив параметр 0 вместо 1. Таким образом, если вы хотите поместить предмет непосредственно в корзину, вместо того чтобы просто разрешить его на карте, а потом взять; то в этом случае всегда проверяйте наличие свободного места в корзине перед вызовом функции InventoryAdd.

InventorySub( idx )
Эта функция убирает предмет из корзины, используя его внутренний индекс. Если предмета с заданным индексом в корзине нет, эта функция выдаст ошибку, возвратив 0 вместо 1.

InventoryClear( idx )
Функция очищает корзину (удаляет из нее все предметы).

InventoryFind( idx )
Эта функция применяется, чтобы узнать, существует ли заданный предмет в корзине или нет. Если искомого предмета в корзине нет, функция возвращает -1, в ином случае возвращается позиция предмета в корзине.

InventoryHasItem(id)
Это упрощенная версия предыдущей функции. Вы можете узнать, есть ли предмет в корзине, используя его id, вместо индекса. Функция возвращает 1, если предмет есть в корзине, и 0, если его нет.

OpenDialogInventory()
Этот фоновой колбек открывает диалог работы с корзиной, позволяя игроку выбрать предмет для использования. Если предмет выбран, то диалог закрывается и функция возвращает индекс предмета. Если же выбран пункт 'exit' (выход), функция возвращает -1.



Более сложные действия

Вы уже узнали, как взаимодействовать с активными объектами используя колбек ActionObject, и как обрабатывать применение вещей, используя колбек UseObject. Однако, в некоторых случаях персонаж должен сперва сообщить вам, в чем он нуждается до того, как вы попробуете ему дать какой-либо предмет. А следовательно, необходимо применять комбинацию из этих двух колбеков.

Попробуем добавить в наш пример колбек ActionObject для Дилана. Сделаем так, чтобы он сперва рассказал нам о том, что ему нужно красное ведро. Как вы понимаете, всякий раз, когда вы будете нажимать кнопку 'применить' на фоне Дилана, будет вызываться колбек ActionObject, а колбек UseObject, который вы написали до этого, будет проигнорирован. Это происходит потому, что колбек ActionObject имеет выше приоритет, чем UseObject. Поэтому необходимо сделать таким образом:



Конечно, можно проделать все манипуляции и внутри колбека ActionObject, тестируя возвращаемый индекс предмета, проверяя, красное ведро или нет, и ввыводя соответствующие сообщения без вызова колбека ActionObject. Оба эти способа будут корректными.


Домашняя работа

Пример, описанный в этой главе, имеет небольшой недостаток. Если вы дадите Дилану предмет, не являющийся красным ведром, он всегда будет отвечать одно и то же. Это не совсем уместно после того, как он получил свое ведро обратно, и тем более дал за него листик. Попробуйте сделать так, чтобы он игнорировал вас после проделанного обмена. И сделайте так, чтобы используемый предмет просто оказывался на земле. Для этого вам необходимо будет использовать свойства статуса (status) Дилана, чтобы сохранять текущее состояние диалога. Используйте функцию DropObject внутри колбека UseObject, чтобы выложить отвергнутый предмет.

Здесь находится возможное решение задачи.

Еще одним неплохим дополнением данной задачи могло бы стать то, что красное ведро еще надо где-то достать. Сделайте этот предмет запрещенным (disabled) и добавьте еще одного персонажа - дедушку Диззи, который бы раскрашивал белое ведро красной краской. Но у него нет красной краски... Это хорошая головоломка для усвоения пройденного материала.

Попробуйте сами решить эту задачу,
и только потом смотрите ответ.

Более подробно читайте в следующих разделах:
Функции для работы с корзиной
Функция OpenDialogInventory





 

Hosted by uCoz