17

Gamemaker Studio 2. Инвентарь

Привет-привет.
Сегодня разберём с вами, что такое инвентарь и как его реализовать в GMS2.

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

Инвентарь с точки зрения компьютера.

Прежде, чем реализовывать инвентарь, нам необходимо понять, как наш компьютер его видит.
Если сильно упрощать, то инвентарь - это, в первую очередь, массив, который хранит наши с вами данные. Какие - решать только нам.
То есть, в самом простом виде инвентарь мы видим так: [Предмет1, Предмет2, Пусто, Предмет3].
Соответственно, реализовывая инвентарь, нам с вами необходимо ориентироваться в первую очередь на работу с массивом данных, а уже затем - на отображение этих данных.

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

Структура инвентаря.

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

В Create у данного объекта нам нужно написать следующий код:

obj = { name : "", id : noone, sprite : noone, stack : 0,}
cellId = noone;

Переменная obj будет хранить основную информацию об объекте отрисовки: имя, которое нужно выводить на экран, айди объекта (не экземпляра!), спрайт и количество в ячейке.
cellId - переменная, которая хранит номер текущей ячейке в массиве.

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

enum objectTypes { any, weapon, potion, shield,
armorHead, // Шлем
armorChest, // Нагрудник
armorBracers, // Наручи
armorGloves, // Перчатки
armorPants, // Штаны
armorBoots, // Ботинки}

Чтобы получить значение - нужно указать энумиратор, а затем выбрать значение. Пример: objectTypes.any - вернёт 0, т.к. этот элемент стоит первым.

Теперь что касается массива. Нам нужно хранить в нём: имя объекта, тип объекта, спрайт объекта, текущее и максимальное количество предметов в ячейке и, конечно же, тип ячейки.
Заполнять их будем через цикл, сначала по оси x, затем по оси y, одновременно создавая клетки инвентаря.
Храниться эти значения будут у объекта игрока.
Не забудьте деактивировать ячейки. Полный код по ссылке ниже:
https://pastebin.com/Sa0MjYKN

Для удобства, сделайте открытие и закрытие инвентаря на какую-либо кнопку.
В моём случае, код для этого также по ссылке ниже:
https://pastebin.com/hffJXm0m

Код в user event 3 нужен не только для закрытия и открытия инвентаря, но и для того, чтобы обновлять значения в ячейках, поэтому в дальнейшем будет вызываться часто, а именно - после каждого изменения значения в ячейках.

Структура предметов.

Со структурой инвентаря разобрались - теперь по предметам. На самом деле, здесь всего четыре строки.
name - для обозначения имени нашего предмета.
type - для обозначения особой ячейки, в которую можно будет поместить только этот предмет. Используется энумиратор objectTypes.нужный_предмет
maxStack - максимальное количество предметов в одной ячейке.
quantity - базовое количество предметов в одном экземпляре. Соответственно, это значение мы сможем изменять, чтобы выбрасывать и подбирать сразу множество предметов.

Логика работы инвентаря.

- Подбор предметов
.

Делайте на ваш вкус и цвет. Я предлагаю разобрать для начала наиболее простой случай: подбор при столкновении.
Для этого у объекта игрока делаем событие столкновения с предметом, где пишем следующий код:
https://pastebin.com/unZqXSfB
Код здесь можно было бы написать компактнее, но для удобства чтения решено было оставить так. :)

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

Вторая большая проверка - на совпадение типов объекта и ячейки. Если они совпадают, это значит две вещи:
- Ячейка не общая, а только под этот тип предмета.
- В этой ячейке может быть только один предмет.
Соответственно, мы вставляем предмет в ячейку, если она свободна.
Все значения мы в конечном счёте обновляем.

- Меняем предметы местами в инвентаре.

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

Данный код по ссылке ниже:
https://pastebin.com/f8mEmF1T

Если хотите потыкать проект и поразбираться в кодах самостоятельно, то вот:
https://disk.yandex.ru/d/WVTCchskv_QaGQ

В целом, это всё. В самом проекте также реализовано взаимодействие с хранилищами (сундуками).
Чтобы заспавнить объект - наведитесь на клетку и нажмите на колёсико мыши.
Можно навестись на ту же клетку, где стоит игрок.

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"