GameMaker Studio 2. Урок 4. - Иерархия объектов. «Объекты-родители» и их «дети». Глобальные переменные

Привет!

Приношу свои извинения за долгое отсутствие. Лето, выходные, ну вы понимаете. :)

Ссылки на предыдущие гайды:
Первый гайд
Второй гайд
Третий гайд

Недавно проводил один из стримов, на котором частично воссоздал старые добрые "танчики" с Денди (Battle City). Исходники, которые можно будет допилить самому, приложу к посту ниже. Там тоже есть что потыкать.

Иерархия объектов

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

Подробно:
Перед созданием любого объекта, мы должны чётко представлять его предназначение. Часто множество объектов исполняют схожие функции, но с небольшими отклонениями. Таким образом, вырисовывается проблема: создавать стопицот объектов с одинаковым кодом - бред, который захламляет код и делает его нечитаемым.
Решение этой проблемы - создание универсального "шаблона", на основе которого будут строиться другие объекты с нужными дополнениями.
Таким образом, наш шаблон становится родителем. А все, кто создан по этому шаблону - его "детьми" (дочерними объектами). Они перенимают его свойства, но могут их в нужной степени корректировать.

Работа иерархической системы в GML (GameMaker Language) имеет особенность, с которой быстро придётся познакомиться на практике.
Все "дочерние" объекты по умолчанию считаются частью "родительского".
У нас есть общий родительский объект для всех блоков. При этом, в комнате его у нас нет. Но есть его дочерние объекты.
Следовательно, делая проверку на наличие родительского объекта, у нас высветится "истина".
Делайте проверки на наличие тех или иных объектов в комнате обдуманно.

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

Какие проблемы могут возникнуть при работе с иерархической системой.

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

Собственно, по этой причине для данного гайда была выбрана относительно простая в реализации игра.
Основа в упрощённом виде выглядит так:

GameMaker Studio 2. Урок 4. - Иерархия объектов. «Объекты-родители» и их «дети». Глобальные переменные Разработка, Gamedev, Программирование, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Обучение

Небольшие пояснения, слева направо.

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

Аналогично с объектами.
- Всё, что есть в игре, кроме персонажей - у нас будет объектом, с которым мы можем взаимодействовать.
- Каждый такой объект мы делим по двум типам: постройки, которые что-то делают (или не делают), но суть - должны быть построены. И природные объекты, которые игрок ставить не сможет.
Дальше, соответственно, они снова делятся.

Как это выглядит в движке.

Создадим два объекта: oObject и oNature.
Первый - родительский объект для всех типов объектов, второй - только для "природных". При этом, у нас также есть объект для земли - oDirt.
Перейдём к oObject.
Нажмём у него на Parent. Далее - на плюсик, где поставим ему дочерним объект oNature.

GameMaker Studio 2. Урок 4. - Иерархия объектов. «Объекты-родители» и их «дети». Глобальные переменные Разработка, Gamedev, Программирование, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Обучение

Аналогично проделаем с oNature для oDirt. Как видно, родитель у него уже выставился.

GameMaker Studio 2. Урок 4. - Иерархия объектов. «Объекты-родители» и их «дети». Глобальные переменные Разработка, Gamedev, Программирование, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Обучение

Ок. Родительские объекты сделали.

Перейдём обратно к oObject и создадим у него событие Create.
Теперь немного мыслей в слух.

Базово, каждый наш объект должен иметь следующий перечень "настроек":
- Количество ХП. Так как каждый объект интерактивен, следовательно, каждый объект можно атаковать. С-но, вводим переменную hp и приравниваем её к 0 по умолчанию.
- Координаты по сетке. coordx, coordy. Не столько необходимость, сколько просто упрощение. Делаем их равными -1 по умолчанию, так как мы в любом случае будем их переназначать при размещении объектов.
- Может объект гореть или нет - flammable. False по умолчанию.

Пока остановимся на этом. Перейдём к объекту oNature.

GameMaker Studio 2. Урок 4. - Иерархия объектов. «Объекты-родители» и их «дети». Глобальные переменные Разработка, Gamedev, Программирование, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Обучение

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

У нас появится выпадающее меню из трёх опций:
- Open Parent Event - открыть это же событие в родительском объекте.
- Inherit Event - унаследовать событие
- Override Event - переписать событие.

GameMaker Studio 2. Урок 4. - Иерархия объектов. «Объекты-родители» и их «дети». Глобальные переменные Разработка, Gamedev, Программирование, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Обучение

С-но, нам нужно выбрать второй пункт: унаследовать событие.

Тогда у нас откроется окно кода с готовой строкой:

event_inherited();

Это значит, что то, что мы прописали в oObject, для oNature у нас унаследуется и будет активно для этого объекта. И при этом, ниже этой строки кода мы можем добавить то, что нам нужно.

Следуя плану, сейчас нам нужно убрать связь между oNature и oDirt, создать ещё два объекта (oResource и oNotResource) и уже затем выставить связь между oNotResource и oDirt.

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

Открыв объект oResource (родительский для всех блоков, с которых что-то будет добываться), создадим его с наследованием от родителя.

Далее - обозначим ресурсы, приравняв их все к нулю.

Metal = 0;
Coal = 0;
Wood = 0;
Stone = 0;
Gem = 0;

По сути - всё.

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

Проверим, как это всё работает.

Создадим объект oRock.
Поставим ему в качестве родителя oResource.
Создадим у него событие Create, унаследовав код.
Пишем код:

event_inherited();
Stone = irandom_range(5, 15)
Далее, чтобы проверить, что всё работает как мы и рассчитывали, в Draw сделаем вывод текста на экран. Выводим текущее количество камня. Не забываем про отрисовку!
GameMaker Studio 2. Урок 4. - Иерархия объектов. «Объекты-родители» и их «дети». Глобальные переменные Разработка, Gamedev, Программирование, Инди игра, Gamemaker Studio 2, Образование, Длиннопост, Урок, Обучение

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

Добавлю ещё кое что прежде, чем закрыть эту тему.
Когда выстраивается взаимодействие между объектами игры, которые не находятся под прямым управлением игрока, очень часто, чтобы избежать ошибок, придётся делать проверку на наличие объекта в комнате. Для этого используется команда: instance_exists(объект);.
Это ещё одна вещь, которую нам позволяет делать иерархия и которая немного развязывает руки в разработке.

Глобальные переменные

В прошлом гайде мы их уже использовали, поэтому здесь - только справка. Всего у нас есть четыре типа переменных:

1. Локальные переменные. Объявляются с помощью ключевого слова var

var название = значение

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

2. Обычные переменные (не знаю, как правильно их обозвать:D)
Мы с ними уже активно работали, объявляются они просто:

название = значение

В дальнейшем, их можно вызывать из других объектов, используя with или обращаясь к объекту через переменную, хранящую его id. К примеру:

inst.coordx = 1;
3. Глобальные переменные. Данный вид переменных может быть вызван в любом событии любого объекта и изменён там. Объявляются следующим образом:

global.название = значение

В основном, они используются для хранения важных (в целом для игры) значений, которые могут меняться в её процессе. Работать с ними нужно предельно осторожно и всегда знать, где и в каких местах значения переменной перезаписываются.

4. Макро переменные. По сути, те же глобальные переменные, но за одним исключением. Они не могут быть изменены. Также используются для хранения значений, которые являются константами и могут пригодиться в нескольких местах программы. Объявляются следующим образом:

#macro Название Значение

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

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

План, как всегда.
- Массивы и с чем их едят, а также grid (сетка комнаты), размещение объектов по сетке. Включая объяснение, в каких случаях лучше использовать встроенные функции, в каких – писать свои с нуля.

- Пути. Один большой гайд, включая скрипты поиска путей для различных сеток в т.ч. с примерами из моего личного проекта.

- Иные способы хранения информации в GMS2, когда их стоит или не стоит использовать.

- Сохранение. Встроенное VS самописное.

- Звуки.


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

Ссылки на скачивание:
Исходник

Полуготовые танчики

Лига Разработчиков Видеоигр

6.7K пост22.2K подписчика

Добавить пост

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

ЗАПРЕЩЕНО:

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

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

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


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

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

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

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

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