Godot и сферический диаблоид в вакууме

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Итак, я собрал прототип arpg-проекта Сферамида с теми механиками, о которых писал ранее прошлой в статье Поиграть в браузере/скачать можно здесь: https://thenonsense.itch.io/spheramyd

Ниже некоторые подробности, по игре и приёмам работы с движком Godot.

Особенности игровой структуры и механик

Сферические подземелья

В то время как с разбиением цельной сферы на единообразные, удобные в текстурировании элементы, имеются некоторые проблемы, сбор сферического уровня из отдельных "комнаток" частично решает этот вопрос. То есть вместо того чтобы замостить всю сферу единообразными элементами на 100%, мы составляем сеть "комнат" и "переходов", оставляя часть пространства неиспользуемым. Остаётся лишь более менее аккуратно стыковать "комнатки" друг с другом. Кстати, даже цельную сферу в любом случае стоило резать на отдельные части из соображений оптимизации, а "комнатный" подход этому изначально лучше соответствует.

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

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

Персонаж

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

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

Концентрированное здоровье

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

У шкал здоровья и маны есть параметр концентрации, который падает со временем. Простое зелье не даёт концентрации. Среднее - меньше ресурса, но и некоторое количество концентрации. Сильное - ещё меньше ресурса, но больше концентрации.

При низкой концентрации шкалы зелье восстанавливает ресурсы с задержкой. При средней концентрации - сразу. А при высокой - шкала постоянно регенерирует, пока концентрация не понизится до среднего значения.

Органический инвентарь

Разные предметы блокируют разное количество пустых окружающих ячеек, попадая в инвентарь. Если же стараться укладывать предметы вплотную, то можно уменьшить количество заблокированных клеток, высвободив больше места. Зелья не имеют блокирующего влияния.

Камни заклинаний

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

Враги

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

Слизни просто путешествуют в том направлении, куда смотрят. Сталкиваясь с препятствиями меняют направление, а коснувшись игрока наносят ему повреждения.

Призраки мониторят окружающее пространство вращающимися рейкастами и, если обнаружат игрока - двигаются к нему. Если персонаж попадает в зону атаки, то призрак атакует. Призраки маги ведут себя похожим образом, но вместо ближних атак создают выстрелы и приближаются медленнее.

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

Скрипты, алгоритмы, логика

Способы связи с объектами

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

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

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

Узлы-обёртки

В большинстве случаев удобнее крепить отдельные специфические элементы (модель, спрайт, кнопка, текстовое поле) к простому стандартному узлу, который будет выступать в качестве контейнера. Это очень пригодится, например, при создании анимаций средствами движка - вместо того, чтобы непосредственно анимировать какую-то модель (MeshInstance или префаб), анимируется узел-контейнер модели. Таким образом, если потребуется сменить модельки, то можно будет не переделывать анимацию заново, а подкорректировать уже имеющуюся. То есть вместо конкретной анимации "молоток ударяет по гвоздю", делается анимация вида "пустышка ударяет по пустышке", где в первую вложен "молоток", а во вторую "гвоздь". И позднее можно вложить в них другие модели, например, "топор" и "полено" (или заменить "молоток" и "гвоздь" высокодетализированными версиями), без пересоздания анимационного трека заново.

Анимация-таймер

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

Защита от множественного срабатывания

Иногда требуется по условию сделать с объектом что-то важное, необратимое, и только один раз. Например, удалить врага, у которого кончилось здоровье от полученного выстрела. Для гарантии того, что операция не произойдёт несколько раз (в том числе пытаясь удалить то, чего уже нет) желательно использовать в объекте какой-то регулирующий это флаг. Например, у монстра может быть переменная is_exist, изначально истинная. Когда монстр должен умереть, то это происходит только при успешной проверке is_exist на истинность. Тогда сначала is_exist устанавливается в ложное положение и далее происходит операция удаления. Теперь из тысячи одновременно прилетевших во врага снарядов, уничтожит его только один из них.

Часто используемые практики

Создание и импорт моделей

Для моделирования используется Blender. Собирается моделька с модификатором Mirror, разворачивается, красится. Затем сохраняется в отдельный файл, где отзеркаливание применяется и модель крепится к скелету. После этого создаются отдельные файлы с разными анимациями.

Простые модели, без анимаций, я перекидываю в Godot в формате .obj, которые затем следует открывать внутри движка, устанавливая как форму MeshInstance. Нужно убедиться, что у экспортируемой модельки порядок с нормалями, применены модификаторы, есть развёртка (если надо) и экспортируется только она, ничего лишнего и скрытого. Также стоит удалить с неё материал, чтобы собрать его заново уже в Godot. При экспорте также может появиться файл .mtl, он не нужен (тем не менее, более старые версии Godot могут писать об ошибке с .mtl при закидывании .obj файла, но на это можно не обращать внимания).

Импорт анимированного персонажа

Объекты с костной анимацией я экспортирую из Blender в Godot в формате collada (.dae). Это не то, чтобы рекомендуемый вариант, но он работает. Материал с модели также удаляется, а вот модификатор арматуры применять не нужно.

После того как файл перенесён в Godot, нужно щёлкнуть по нему, открыть вкладку Import (слева вверху), в разделе Animation - Storage выбрать пункт "Files (.anim)" и нажать внизу кнопку reimport.

Далее модель добавляется на сцену и нужно открыть её для редактирования (выбрав пункт new inherited). Там, в аниматоре (AnimationPlayer) меняем имя дефолтной анимации на желаемое название анимации и сохраняем эту анимацию как файл .anim. Также сохраняем саму открытую сцену персонажа как файл .tscn - это и будет префаб с моделькой.

Теперь убираем со сцены модельку в формате .dae, и добавляем/используем тот полученный .tscn префаб. Сам файл .dae продолжаем хранить в ресурсах.

Добавление новых анимаций персонажу

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

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

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

Полезное

Фишки среды разработки

В Godot можно нажать Ctrl и кликнуть по строке кода с вызовом функции, чтобы переместиться в то место, где находится эта функция. Таким же образом, кликая по переменным можно перемещаться в место, где эта переменная объявляется. Выделенный код можно двигать вверх-вниз стрелками клавиатуры. Чтобы закомментировать несколько выделенных строк сразу нужно нажать кнопку K, а для раскомментирования Ctrl + K.

Эффект просвечивания

Для того, чтобы силуэт героя подсвечивался, когда его перекрывает препятствие, нужно сделать вот что: у базового материала героя приоритет рендера сменить с 0 на 1, а в next pass добавляется второй материал с нужным цветом и флагами unshaded и no depth test.

Спасибо за внимание.

Источник: https://habr.com/ru/post/683200/


Интересные статьи

Интересные статьи

Привет! Меня зовут Саша Шутай, я тимлид в AGIMA. В прошлой статье я рассказывал, что делать, если на проекте Bitrix сожительствует с Vue.js и поисковые боты не видят контента сайта. А в этой помогу ра...
Компания «Деловой разговор» — Титановый партнер 3СХ — осуществила расширенную интеграцию IP-АТС 3CX с Битрикс 24. Ранее уже существовали отдельные модули, решающие конкретные задачи, напр...
Нередко при работе с Bitrix24 REST API возникает необходимость быстро получить содержимое определенных полей всех элементов какого-то списка (например, лидов). Традиционн...
Среди советов по улучшению юзабилити интернет-магазина, которые можно встретить в инете, один из явных лидеров — совет «сообщайте посетителю стоимость доставки как можно раньше».
Тема статьи навеяна результатами наблюдений за методикой создания шаблонов различными разработчиками, чьи проекты попадали мне на поддержку. Порой разобраться в, казалось бы, такой простой сущности ка...