Последовательная генерация мира — создание карты для Unexplored 2 Материал редакции

Разные условия в каждом регионе, строгие правила построения локаций и диаграмма Вороного, лежащая в основе.

В закладки
Аудио

Unexplored 2: The Wayfarer's Legacy — это роглайт, в котором герою предстоит путешествовать, чтобы уничтожить различные магические вещи. В игре есть перманентная смерть, но после гибели персонажа пользователь может сохранить мир, чтобы продолжить раскрывать местные секреты. В каком-то смысле карта — один из самых важных и постоянных персонажей в игре.

Основатель студии Ludomotion Йорис Дорманс на сайте Gamasutra опубликовал текст, в котором детально объяснил, каким образом генерируется игровой мир в Unexplored 2. Он описал подробный алгоритм, позволяющий добиться создания интересной локации, которую пользователи обязательно захотят исследовать. Мы выбрали из его текста главное.

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

Всё начинается с рандомной диаграммы Вороного с 80 ячейками, размещёнными на карте с соотношением сторон 3:2.

Изначальная диаграмма

Разработчики используют диаграмму Вороного, потому что она имеет довольно естественное распределение ячеек, и потому что структуру можно рассматривать как граф, где каждая ячейка является отдельным узлом, а каждое ребро — связью между узлами. Это полезно, поскольку команда использует определённые правила для создания карты.

На первом этапе ячейки на западной границе начинают изображать океан. Затем он расширяется, создавая всё более интересное побережье, а оставшиеся клетки становятся сушей. Начальная локация установлена где-то вдоль побережья, а целевая локация — где-то на восточной стороне. Каждая ячейка содержит информацию о том, как далеко она от начала и конца. Расстояние в этом случае измеряется количеством ячеек между двумя точками.

Суша и океан

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

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

«Хребет Толкина»

Горы образуют барьер, поэтому их можно пересечь только на перевалах (белые границы на рисунке выше), но не где-либо ещё (красные границы).

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

Граф, который показывает правило превращения пустой ячейки в горную

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

Каждая такая точка находится внутри регионов разных типов. В данном случае цель находится в болотах (s — swamp), гавань (зелёная h — haven) размещается в области холмов недалеко от начала, а другие места размещаются в пустыне (d — desert), лесу (f — forest) и бесплодной местности (b — barren). Оранжевые края указывают на границы между регионами.

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

Правило графа, которое превращает границу региона рядом с океаном в реку

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

Готовая топография

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

Граф правила создания реки в болоте

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

На основе расположения стартовой и финальной зоны выстраивается сложность, и генерируются различные опасности и возможности.

Граф регионов

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

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

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

Вид карты, который представлен в игре

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

Исходные ячейки проецируются на карту

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

Другие декорации построены из простой геометрии на основе графика Вороного с высоким разрешением. Это можно легко увидеть на рисунке ниже.

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

Мир Unexplored 2 не является абсолютно открытым. Игроки путешествуют от узла к узлу и могут выбирать, какие зоны исследовать дальше. Связь между узлами определяет, где игрок может путешествовать. Чтобы разместить узлы на карте, разработчики используют исходную диаграмму Вороного с низким разрешением. Узел помещается в каждую ячейку и на каждую границу между ячейками, как показано на рисунке ниже.

Сеть узлов, размещённых на диаграмме Вороного

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

Детализированная сеть с переходами через реки и горы

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

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

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

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

{ "author_name": "Владимир Семыкин", "author_type": "editor", "tags": ["\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f","\u0433\u0435\u0439\u043c\u0434\u0438\u0437\u0430\u0439\u043d"], "comments": 18, "likes": 99, "favorites": 198, "is_advertisement": false, "subsite_label": "gamedev", "id": 57978, "is_wide": true, "is_ugc": false, "date": "Tue, 09 Jul 2019 16:44:47 +0300", "is_special": false }
0
{ "id": 57978, "author_id": 94357, "diff_limit": 1000, "urls": {"diff":"\/comments\/57978\/get","add":"\/comments\/57978\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/57978"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 64954, "last_count_and_date": null }
18 комментариев
Популярные
По порядку
Написать комментарий...
1

Зарегался благодаря этой статье. Заабрал в закладки. Очень интересная тема. Хотелось бы еще чего-нибудь об этом проекте почитать, технических фишечек.

Ответить
3

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

Ответить
0

С удовольствием почитал бы!

Ответить
0

Было бы интересно. Сам алгоритм весьма такой...

Ответить
1

Забавно, буквально на днях думал о том, что диаграмма Вороного - идеальный инструмент для костяка игрового мира.

Ответить
0

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

Ответить
1

По работе не так давно прикидывал разбивку карты на сектора в зависимости от ряда параметров, там вспомнилось и прям зашло.
А как таковую узнал... На матфаке наверное? :)

Ответить
0

тогда понятно, почему это прошло мимо меня. На журфаке такое не проходят :)

Ответить
0

Не могу понять что такое "роглайт". Рогалик, рогулайк знаю, а это что-то новое. В гугле бан (на самом деле прост ничего путного не находит). Это опечатка или я проспал новый жанр? :)

Ответить
2

роглайт — это чуть упрощённый роглайк. Чаще всего отличие выражается в том, что после смерти остаётся хоть какой-то прогресс. В Rogue Legacy, например, было дерево развития, которое давало бонусы для всех следующих попыток. Ещё там можно было заплатить, чтобы в новой попытке мир не генерировался заново. В Unexplored 2 тоже будет нечто подобное

Ответить
0

И еще сам геймплей не пошаговый. Это основная черта "ортодоксальных" рогаликов, как-никак.

Ответить
0

Спасибо за пояснение, Rogue Legacy в своё время зашёл, к Unexplored 2 уже присматриваюсь :)

Ответить
0

Здорово, спасибо! Не очень понятно как в это играть и что видит игрок? Только вот эту карту со скриншота? В чем заключается геймплей?

Ответить
0

Посмотрие трейлер в начале статьи

Ответить
0

Выглядит прикольно! Особенно если добавят много уникального и редкого контента, ради которого захочется снова и снова исследовать мир — будет круто!

Ответить
0

Очень крутая статья, обожаю процедурную генерацию, она реально даёт играм живость. Делает их отличными от других видов искусства) очень вдохновляет это. А когда сочетается с крутым визуалом, так вообще конфетка. Лайк!
А что по технологиям? Все самописное и openGL? Расскажите нубу, может есть выгодные решения для разработки именно процедурных игр? Хотя, наверное, все равно где и чем... Интересно.

Ответить
0

Как же это охуенно!!!

Ответить
0

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

Ответить

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fizc" } } }, { "id": 4, "label": "Article Branding", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "cfovz", "p2": "glug" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "clmf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "clmf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-250597-0", "render_to": "inpage_VI-250597-0-1134314964", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=clmf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Баннер в ленте на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudo", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "chvjx", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fzvc" } } }, { "id": 20, "label": "Кнопка в сайдбаре", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "chfbl", "p2": "gnwc" } } } ]