Процедурная генерация | Delares — блог разработки

Процедурная генерация | Delares — блог разработки

Процедурная генерация

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

Delares — это рогалик. И, по канонам, локации должны выглядеть как унылые комнаты с лутом и парочкой мобов. Но, конечно же, мы не такие как все.
У нас будут не комнаты, а острова в воздухе, с ресурсами и мобами, словно вырезки мира из какой-нибудь РПГ игры.

Почему не Перлин?

Что мы будем применять в реализации? Конечно же шум Перлина!
Именно так подумал наивный, глупый я.
Как выяснилось позже — шум Перлина прекрасен во всём, но не во всём удобен, как, например, в генерации линейных островков.
Перлин бесконечен по осям. Мы не можем без постобработки сгенерировать шум, который будет плавно расползаться от центра к краям. Мы можем применить к шуму радиальную маску, и тогда заимеем картинку, похожую на что-то подобное:

Вычитаем из значения шума значение маски<br />
Вычитаем из значения шума значение маски

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

Всем привет, я - клеточный автомат!

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

Концепция клеточного автомата состоит в клетках и правилах, по которым они живут/умирают/размножаются в зависимости от клеток по соседству.
Так, например, в автомате с установленными правилами 5678/45678 клетка будет "рождаться" если вокруг есть 5, 6, 7 или 8 живых клеток, и просто оставаться в своём состоянии, если вокруг от 4 до 8 живых клеток. В остальных случаях (0, 1, 2, 3 соседей) клетка умирает.
Входные данные автомата - двумерный массив с булевыми значениями (да/нет), правила автомата разобранные выше, кол-во итераций и шанс спавна стартовой клетки.

1. Мы делаем живыми какой-то процент клеток автомата в случайных местах, обычно около 50%.
2. Проходимся по массиву обработчиком с указанными правилами определённое кол-во раз.
3. Забираем результат!

Процедурная генерация | Delares — блог разработки

С ходу я понял, что этот алгоритм нам подходит. Он имеет достаточную кастомизируемость, поддерживает генерацию по сиду и хорошо сочетается с другими шумами, с тем же Перлином. Полученное клеточное булевое значение просто интерпретируется как значения шума 0 и 1.

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

Процедурная генерация | Delares — блог разработки

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

Поверх

Это всё конечно хорошо, островки мы генерировать научились. Но что насчёт наполнения? Если у нас лишь два значения шума, то генератору уже не скажешь, в каких высотах генерировать деревья, а в каких, например, кусты.

Как я уже и сказал - мы просто представляем булевое значение как 0 и 1, а потом подключаем шум перлина, перемножая значения. Таким образом булевая карта становится просто маской для Перлина.

Процедурная генерация | Delares — блог разработки

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

Процедурная генерация | Delares — блог разработки

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

Процедурная генерация | Delares — блог разработки

В редакторе всё это выглядит вот так. Пусть и не сильно красиво, зато вполне понятно.

Процедурная генерация | Delares — блог разработки

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

Процедурная генерация | Delares — блог разработки
Процедурная генерация | Delares — блог разработки

Что дальше?

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

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

Процедурная генерация | Delares — блог разработки

Тени деревьев отображаются на пустоте вокруг острова, да и вообще везде, где не должны. Как это решить - пока не знаю.

Процедурная генерация | Delares — блог разработки

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

Всем спасибо за фидбек.

33
1 комментарий