Добрый день. Хочу поделиться историей о том, как я в течении месяца разрабатываю собственную игру, в которую решил собрать все, что я люблю. А именно - иммерсивный рогалик на основе The Binding of Isaac, поощряющий исследование и эксперименты.
В этом посте будут расписаны принципы рандомной генерации, сложности которые я встречал, и идеи, которые реализовываю. А так же много скринов, описания и лирики. Погнали.
Начну я с того, что всего месяц назад впервые открыл Unreal Engine 4. До этого я работал только в GameMaker Studio 2, и мой прошлый проект вы могли видеть около полугода назад. Поэтому какие-то встреченные мной проблемы вполне могут оказаться интересны новичкам.
Я решил скрестить пару игр в одну. Я собирался взять геймплей TBoI, с его сотнями стакаемых артефактов и рандомной генерацией уровня
Взять очень запавшую мне в душу графику и атмосферу малоизвестного рогалика Delver. Пиксельные текстуры и несложная геометрия моделей + объемный свет, и узкие коридоры, полные секретов и врагов. Такая графика мне вполне под силу, учитывай бекграунд дизайнера.
И соединить все это вместе. Вид от первого лица дает огромный потенциал для эффектов будущих артефактов, вроде просвета стен насквозь, двойных прыжков и вообще вертикальной мобильности.
На этот момент я решил что в моей игре точно должна быть интересная вертикальность. Это будет выражаться в двухэтажных тайлах, из которых будет собираться уровень.
Генерация уровня - пожалуй, самая сложная вещь, которая была запланирована в этом проекте.
Я решил изучить то, как она работает в Айзеке, и вот принцип работы:
За основу, на которой располагаются комнаты, используется массив целых чисел, хитро используемый как координаты.
Десятки используются как положение комнаты по Y, а единицы - по X. Таким образом, мы получаем массив координат комнат, в котором можно легко программным методом искать соседние комнаты - если мы хотим найти комнату сверху - достаточно просто вычесть из координаты десятку.
В этой системе берется центральная комната, допустим, 55. Она считается как стартовая. Потом алгоритм проходится по соседним клеткам, заполняя их комнатами. При этом, он проверяет, что бы у комнаты было не больше 1 соседа при установке. Такое условие позволяет создать "коридорность" этажа, в котором отдельные коридоры комнат никогда не зацикливаются.
При этом, когда этаж сгенерирован, алгоритм опознает тупики в разросшейся структуре комнат - в этих местах могут оказаться расположены особые комнаты, вроде сокровищницы, магазина или босса.
Более подробно о процессе генерации уровней в айзеке можно почитать Здесь.
Воссоздание данного алгоритма заняло у меня суммарно больше недели, но результат того стоил. Хотя тут визуально сложно что разобрать...
Мой вариант генерации несколько отличается, в основном по причине использования 3д-графики.
Изначально я планировал понаделать ассетов и собирать из них тайлы внутри анрила - но это оказалось очень неоптимально и медленно. К тому же были проблемы, что отдельные тайлы не успевали прогружаться при быстром повороте камеры.
Эта проблема решилась тем, что я начал моделировать всю основную геометрию уровня в Blender, а затем наполнять ее интерактивными элементами в анриле.
Как можно заметить, тайл сделан с той самой "Вертикальностью". Каждый тайл создается в рамках жестких условий входов и выходов из него, что позволяет бесшовно соединять их при генерации. И, конкретно в моем случая, я решил добавить во все свои тайлы механику второго этажа.
Второй этаж в игре - это довольно труднодостижимое место. Туда редко ведут прямые лестницы или подъемы, иногда можно забраться туда при помощи паркура или подлететь на инерции от взрыва, потеряв здоровье.
Но в награду игрока ждет большее количество ценного лута + иногда есть возможность пройти в особые комнаты без траты ключа. Но, если первый этаж всегда спроектирован так, что игрок может пройти куда угодно, гулять по второму этажу всего этажа не поулчится - его геометрия порой вовсе не соединена друг с другом.
Вот наглядный пример - тупиковый уголок с крайне ценным лутом, в который из своего тайла проходу вовсе нет. Но, есть шанс на генерацию соседней комнаты, которая позволит этот лут собрать. Каковы шансы? Довольно низки. Учитывая, что каждая комната может при генерации быть случайно повернутой, разнообразие такой генерации довольно велико.
В целом, развивая тему "исследовательства" данжа, было понятно что от "комнатности" айзека придется уйти. Некоторые мои тайлы крайне коридорны, и как следствие возникла проблема - игрок мог пропетлять по длинному коридору, и упереться в стену, потому что там конец карты и вообще ничего нет. Неприятно удивленный бесполезностью коридора, игрок должен был топать обратно. Такие "безперспективные" коридоры встречались в каждом тайле, и это очень раздражало. Поэтому я внедрил систему динамических дверей - в каждой комнате они находились не в самом "краю" тайла, а в указанном месте, обычно - в самом начале такого коридора, просто обрезая его и делая незаметным для игрока. Вот пример:
Вот эта стена с красной стрелкой - дверь, которая остается неразрушимой, если в конце коридора с той стороны конец карты. А если там есть комната - то при генерации стена убирается, открывая игроку проход.
Ну, или если по ту сторону - секретная комната, то дверь перекрашивается в другую текстуру с малозаметным крестиком. И такую стену можно взорвать, открыв проход. Система динамических дверей по факту работает и на сложность нахождения этих секретных проходов - так как разрушаемые стены гладко вписаны в окружение, их легко пропустить.
В целом, если данный материал окажется интересным, я запилю продолжение, благо рассказывать есть много чего. И про методы генерации лута на основе весов, и про особенности и принципы геймдизайна и левелдизайна, навязываемые геймплеем, и про принципы реализации системы артефактов.
Могу так же более подробно углубляться в сам процесс реализации данных систем на блупринтах анрила - с примерами элементов кода и его описанием. Если интересно.
Если хотите следить за развитием проекта - основной движ происходит тут.
https://vk.com/crystallpunk Тут же можно найти много геймплейных роликов.
А на этом, спасибо вам за внимание, и вот вам немного скриношов текущего игрового процесса напоследок.