Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток

Добрый вечер, мои дорогие подписчики. Это продолжение серии Godot путь новичка. Main Menu ч5. Рефакторинг(Практика)

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

Сразу оговорюсь, спорить в комментариях и что-то доказывать я не буду, мне и так за прошлый раз не по себе(ингибитора адекватности на грудь принял). Есть множество различных способов и реализаций, я буду придерживаться исключительно принципа KISS. Аргументированный вариант который ещё проще, с удовольствием приму и буду использовать, все остальное нет. А то само слово Singleton, у некоторых вызывает странную реакцию, молчу про все остальное чего собираюсь наворотить))


Вот описание с вики https://ru.wikipedia.org/wiki/Канал_событий_(шаблон_проектирования)
не вижу смысла дублировать описание, все так и есть.

Преимуществ у этого подхода куча, самое главное легкость для понимания и простота реализации. Недостатки тоже имеются, главный это появляется некая асинхронность в проекте, со временем может возникнуть ситуация, что не очень понятно, что и когда, после чего произойдет. Тут уже не получится последовательно с контролом кликать по методам, чтобы понять суть происходящего, код станет читать сложнее. Зато интереснее, проект уже похож не на скучный структурированный учебник, а на увлекательный детективчик, с незабываемыми Шьямалановскими поворотами сюжета. С другой стороны, просто не стоит делать большие конструкции. Добавляя GlobalDispather(EventChannel) к проекту, уже не стоит смотреть на проект как на дерево, хотя формально структура древовидная сохранится отчасти. Теперь на него лучше смотреть уже как на поляну грибов. Есть грибница(EventChannel) на ней сверху растет куча грибов, которые сообщаются друг с другом посылая сигналы не напрямую друг другу, а посылая их в грибницу, а кому надо те их слушают. Красота тут в том что если половину грибов соберут, то пофигу, те что останутся так и продолжат работать.

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

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

В Game оставим только кнопку назад.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

В скрипте Main тоже убираем лишнее, был у нас там рудимент с кнопкой набирающей очки, выпилили её из Game, логично что убрать надо бы и связанный с ней код.


Для минимального удобства, можно насоздавать разных папочек, чтобы складывать туда всякие вещи. И создать папочку Singletons. Я немного переименовал сцены и для себя раскидал следующим образом.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост
Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

Создаем новый скрипт PlayerStats, пока ничего не будем в нем добавлять, просто создаем. В нем будет храниться накопленное игроком золотишко.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

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


Переходим в настройки проекта.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост
Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

Вот такая должна получится картинка.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

Что такое Singleton можете посмотреть на вики https://ru.wikipedia.org/wiki/Одиночка_(шаблон_проектирования)


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

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост
Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

ну теперь осталось только научиться их добавлять.

в Dispather'е добавляем всего одну строчку. Офигенный класс, будьте уверены он вам придется по нраву, в нем меньше всего будет кода и больше всего пользы) Создатели godot, удивительным образом все сделали уже сами, при том сделали очень хорошо. Используя этот паттерн на флеше или на яве или на javascript, надо было очень внимательно следить за тем, чтобы своевременно отписываться от событий, в противном случае, останется ссылка на объект, он будет недоступен для сборщика мусора, а новые создаются, ссылки оставляют. Ну самый главный по большому счету MemoryLeak и бич всех невнимательных флешистов в свое время)) В godot вообще пох, можно лепить бездумно, ему по барабану, он удаляет объект из памяти даже если тот подписан на какие-то события и проблем никаких нет вообще. Очень трудно наломать дров. Нраица.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

Все с Dispather'ом закончили, он готов к использованию.

Запилим читпанельку, с помощью которой сможем добавлять себе денег.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

Все это уже добавлялось ранее, подробно как добавить кнопочку расписывать не буду, в целом и так все понятно надеюсь. Да, для отдельных страдальцев базовой нодой для CheatPanel, сделана Control, на самом деле сейчас это не принципиально, можно и Node2d. Ну пусть будет, не заморачивайтесь если не понятно, помните про YAGNI.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

В скрипте добавляем скрытие/показ читпанельки. Ну и по нажатию, через диспатчер отправляем сигнал. Теперь надо добавить, обработку этого сигнала в PlayerStats.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

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

Ещё один маленький нюансик, поскольку теперь не так просто отследить зависимости между разными объектами, имеет смысл добавить небольшой комментарий к сигналу.

Godot путь новичка.Singleton. Dispather(Event Channel). Сбор монеток Godot Engine, Godot, Gamedev, Туториал, Длиннопост

Можно конечно и подробненько расписать, что за сигнал, когда применяется, но из названия и так понятно, а вот дописать список параметров которые необходимо передавать вместе с сигналом, очень даже будет не лишним, чтобы потом лишний раз не искать и не вспоминать. Тем более что этих параметров может быть и больше одного, а может и вообще не быть, ну вообщем, как и что комментировать, тут каждый сам за себя решает, а в компании будут по любому всякие гайдлайны, кодестайлы и прочее. С другой стороны, если вы забудете добавить параметр необходимый, то godot при использовании сигнала, выдаст ошибку в дебаггере, что ожидаемый параметр не был передан или наоборот, что параметр был передан, а его там не ждали.


---тут допзадача для киндера, но можете и сами поэксперементировать для интереса---

Чтобы менять кол-вол добавляемых монеток прямо из игры, надо в читпанели изменить тип Label, на TextEdit.


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

Dispather.emit_signal("CHANGE_MONEY",MonsterData.money_reward)
при открытие сундука, при выполнении квеста, да при покупке золотишка за реал, все так же будет добавляться всего одна строчка. Параметров разве что добавится ещё, тип источника, позиция откуда добавилось и тд. И механика будет всегда одинаковая, пофигу с читпанельки нажали или с сервера через сокет пришло сообщение. Это на самом деле плюс.


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

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


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


@xenofob, вдруг с монетками не разобрался ещё, то вот пожалуйста)

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

6.6K постов22.1K подписчика

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

ЗАПРЕЩЕНО:

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

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

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


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

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

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

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

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