- PVSM.RU - https://www.pvsm.ru -

Генерация подземелий и пещер для моей игры

Генерация подземелий и пещер для моей игры - 1

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

Разбиение пространства

Существует множество способов генерации комнат для подземелья (случайное размещение [1], генерация на основе агентов [2], с использованием separation steering behavior [3] или физического движка [4], и т.д.). Но мой любимый метод — это разбиение пространства, потому что оно легко контролируется и расширяется.

Способов разбиения пространства тоже очень много: разделение на сетки, двоичное разбиение пространства, разбиение пространства деревом квадрантов, диаграммы Вороного и т.д. Я решил использовать двоичное разбиение пространства, потому что оно хорошо подходит для генерации прямоугольных комнат. Этот метод получил популярность благодаря статье [5] на RogueBasin.

Единственная сложность этого алгоритма — выбор позиции разделения. Если мы не наложим ограничение на позицию разделения, то будем получать странные разбиения пространства:

Генерация подземелий и пещер для моей игры - 2

Такого поведения можно избежать несколькими способами. Один из них — ограничить позицию разделения двумя соотношениями длин сторон, например, в интервале от 30% до 70% или от 40% до 60%. Другой способ — использовать вместо равномерного распределения нормальное или биномиальное, благодаря этому повысится вероятность разделения по центру стороны, а не по краям. Эти способы устраняют проблему, но сложно понять, как конкретно параметры влияют на окончательный результат.

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

Генерация подземелий и пещер для моей игры - 3

Хорошие результаты даёт максимальное соотношение от 2.0 до 3.0:

Генерация подземелий и пещер для моей игры - 4

Генерация комнат

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

Вот результаты:

Генерация подземелий и пещер для моей игры - 5

Выбор рёбер

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

Вместо этого на этапе разбиения пространства я строю структуру двусвязного списка рёбер [6], который позволяет знать, какие ячейки расположены рядом друг с другом. Таким образом я получаю следующие графы:

Генерация подземелий и пещер для моей игры - 6

У такого подхода есть три преимущества. Первое: если в дальнейшем я захочу изменить способ разбиения пространства, то остальная часть генератора останется действующей, потому что она получает на входе только полурёберную структуру данных. Второе: теперь для выбора рёбер, которые станут коридорами, я могу использовать любой алгоритм генерации лабиринтов [7]. Третья: если я захочу добавить в подземелье петли, то легко смогу это реализовать.

Пока я просто использую алгоритм Крускала и расстояние городских кварталов для выбора рёбер. Вот результаты:

Генерация подземелий и пещер для моей игры - 7

Генерация коридоров

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

Вот результаты:

Генерация подземелий и пещер для моей игры - 8

Генерация пещер

Предыдущие результаты подходили для создания подземелий, склепов и других рукотворных структур, но пещерам и шахтам я хотел придать более природный вид. Классический способ генерации пещер — использование клеточного автомата, как это описано в данной статье [8] на RogueBasin. Большая проблема клеточных автоматов заключается в том, что их результаты не совсем контролируемы.

Я решил всё равно использовать для создания естественного внешнего вида клеточные автоматы, но наложить на них ограничения для получения контролируемого результата. Вместо всего двух состояний: мёртвый и живой, я использую четыре: совершенно точно мёртвый, мёртвый, живой, совершенно точно живой. «Совершенно точные» состояния не могут изменяться в процессе, они используются для ограничения результатов.

Комнаты и коридоры, сгенерированные на предыдущих этапах, заполняются «точно живыми» клетками. То есть у нас всё равно остаются опорные комнаты и мы гарантируем, что они будут соединены друг с другом. Рёбра, которые не были выбраны, заполняются «точно мёртвыми» клетками, чтобы между комнатами не появлялось никаких новых путей. Наконец, вокруг комнат и коридоров мы случайным образом делаем некоторые ячейки живыми. Вот изначальная конфигурация:

Генерация подземелий и пещер для моей игры - 9

Затем мы запускаем клеточный автомат:

Генерация подземелий и пещер для моей игры - 10

Вот ещё несколько примеров результатов:

Генерация подземелий и пещер для моей игры - 11

Позже я добавлю заливку для удаления недостижимых частей.

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

Удаление изолированных ячеек

Затем я реализовал заливку для удаления недоступных ячеек:

Генерация подземелий и пещер для моей игры - 12

Множественные коридоры между комнатами

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

Вот разница результатов до применения шума к соединяющимся комнатам и сразу после, параметр меняется всего на одну единицу:

Генерация подземелий и пещер для моей игры - 13

Генерация подземелий и пещер для моей игры - 14

Если сделать комнаты немного больше, то результат получится ещё более интересным:

Генерация подземелий и пещер для моей игры - 15

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

Генерация подземелий и пещер для моей игры - 16

Генерация тайлов для пещер

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

Вот примеры результатов:

Генерация подземелий и пещер для моей игры - 17

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

Генерация подземелий и пещер для моей игры - 18

Следующими этапами генерации подземелья будет добавление декораций и монстров.

Автор: PatientZero

Источник [9]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/algoritmy/324933

Ссылки в тексте:

[1] случайное размещение: https://gamedevelopment.tutsplus.com/tutorials/create-a-procedurally-generated-dungeon-cave-system--gamedev-10099

[2] генерация на основе агентов: http://pcgbook.com/wp-content/uploads/chapter03.pdf

[3] separation steering behavior: https://www.reddit.com/r/roguelikes/comments/1dodsv/my_procedural_dungeon_generation_algorithm/

[4] физического движка: https://www.gamasutra.com/blogs/AAdonaac/20150903/252889/Procedural_Dungeon_Generation_Algorithm.php

[5] статье: http://roguebasin.roguelikedevelopment.org/index.php?title=Basic_BSP_Dungeon_generation

[6] структуру двусвязного списка рёбер: https://en.wikipedia.org/wiki/Doubly_connected_edge_list

[7] алгоритм генерации лабиринтов: https://en.wikipedia.org/wiki/Maze_generation_algorithm

[8] данной статье: http://www.roguebasin.com/index.php?title=Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels

[9] Источник: https://habr.com/ru/post/461087/?utm_campaign=461087&utm_source=habrahabr&utm_medium=rss