Войти
ПроектыФорумОцените

Niko Saves World [RELEASED][Конкурс: «Я слышу тебя!»]

Страницы: 1 2 38 9 Следующая »
#0
(Правка: 30 июля 2021, 0:43) 16:49, 18 мая 2021

NIKO SAVES WORLD

Жанр: GTA-like Action
Сеттинг: Современный город
Движок: Unity3D
Особенности: Бесконечный мир, процедурная генерация
Мин требования для GPU:
Минимально комфортно можно играть на интегрированной карте Intel HD 4200. На medium она выдает 30 FPS.
Интегрированная карта чуть повыше Intel UHD 620 выдает 60 FPS на medium.

Ссылка для скачивания: [Билд v0.3.839]

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

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

Скрин:
Изображение

+ Больше_скринов

Последний видосик:

Запустить видео по клику - Как делать игрыЗапустить видео по клику - Как делать игры


#1
17:57, 18 мая 2021

Подписался

#2
(Правка: 3 авг. 2021, 12:45) 2:12, 19 мая 2021

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

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

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

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

В результате получаем следующую картину:

+ Показать

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

Далее, в каждом гексе буду строить город/село. И поскольку они будут иметь 6 сосдених гексов, то из каждого города будет выходть 6 дорог к соседям. Таким образом гарантируется свзяность мира, так что из каждого грода можно гарантированно попасть в любой другой город.

#3
(Правка: 3 авг. 2021, 12:45) 0:31, 20 мая 2021

Сделал генерацию схемы дорог внутри города.
Поддерживаются две схемы города - радиальная и прямоугольная:

+ Показать

Розовые линии - основные дороги, синие - второстепенные.

#4
23:35, 20 мая 2021

Главный Герой: Niko.
Подобраны анимации, сделан аниматор, сделан контроллер.
Фишка - поддержка кувырков.

Запустить видео по клику - Как делать игрыЗапустить видео по клику - Как делать игры

По схеме дорог генерируются меши асфальта и тротуаров:

Запустить видео по клику - Как делать игрыЗапустить видео по клику - Как делать игры

#5
14:12, 22 мая 2021

Сделал процедурный заборчик.

Запустить видео по клику - Как делать игрыЗапустить видео по клику - Как делать игры

#6
18:15, 22 мая 2021

Круто

#7
(Правка: 23 мая 2021, 14:04) 22:54, 22 мая 2021

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

+ Примеры сгенерированных городов
+ Примеры мужских имен
+ Примеры женских имен
+ Исходный код (C#)
#8
4:47, 23 мая 2021

Zeus44
Можно на пальцах объяснить, как происходит генерация имени? Ты изначально задавал вес переходам от букве к букве?

#9
(Правка: 9:02) 8:50, 23 мая 2021

Incvisitor
Математически, програмка считает вероятность появления символа исходя из двух предыдущих символов.
При генерации, сначала случайным образом выбирается начальные символы, а затем добавляются следующие символы, согласно вероятностям. И так пока не встретится стоп-символ.
Сами вероятности считаются из обучающей выборки.

Словарь nextChar хранит два символа (как ключ) и список из символов, которые появлялись в обучающей выборке после ключевой пары.
Предварительно в програмку подается файл из списка имен. Что бы алгоритм корректно работал спереди слова добавляется два служебных символа (\x0\x0), а в конце - стоп символ (\x1).
Метод AddToDict разбивает слово на тройки символов, и добавляет их в словарь (два символа - как ключ, третий - как значение).
Метод GetWord начинает с комбинации "\x0\x0", а затем случайным образом (но согласно вероятностям), добавляет к строке новые символы из словаря, пока не встрети стоп-символ.
Все.

В качестве исходных данных для имен городов, взял вот этот список https://www.britannica.com/topic/list-of-cities-and-towns-in-the-… tates-2023068
Результат генерации - выше.

#10
(Правка: 16:06) 14:03, 23 мая 2021

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

Изначально я ставил следующие условия на генерацию мира:

1. Мир НЕ должен строится итерационно. То есть для каждой точки пространства можно получить полную информацию о ландшафте, строениях и дорогах в этой точке, не имея данных о других точках пространства. Назовем это локальной независимостью.
2. Мир должен быть связным. То есть всегда можно попасть из одной точки в другую (по дорогам). Это связность.
3. Мир должен быть максимально разнообразным, не регулярным и не выглядеть как сетка. То есть непредсказуемым.
4. Построение мира должно быть таким, что в нем генерируются как природные ландшафты (моря, горы, реки и равнины), так и искусственные - города, дороги.

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

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

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

+ Показать

Некоторые варианты были вполне неплохие. Например вариант, показанный на скриншоте 5. Я некоторе время даже хотел его взять как основной вариант.
Генерация клеточными автоматами обладает локальной независимостью (в моем варианте алгоритма по кр мере), гарантирует связность, может генерировать дороги.
Но у этих автоматов есть минусы. Очевидный минус - они довольно предсказуемы. Они очень равномерно покрывают поверхность. Здесь нет больших пустых пространств, сменяющихся заполненными. Здесь нельзя сделать горы, моря. Здесь очень хорошо можно сделать один большой непрерывный город. Но не более. Поэтому отбросил.

Далее я долго смотрел на генеративные алгоритмы типа алгоритма коллапса волновой функции WFC.
Некторые картинки, даже из описания WFC выглядят очень похожими на город. В интернете есть даже впечатляющие демки больших городов, сгенерированных WFC: https://www.youtube.com/watch?v=-W7zt8181Zo&ab_channel=marian519
Вяглядит очень круто. Казалось бы - вот оно, бери и используй.
Но нет. Не все так просто.
Во-первых, WFC не обладает локальностью. Он итеративно строится из начальной точки. Да, можно построить город и в дальней точке, например в (1000, 1000). Но только для этого вам нужно построить весь город начиная от (0, 0) и до (1000, 1000).
К тому же, этот алгортим с откатами. То есть в определенный момент он может оказаться в тупиковой ситуации и ему нужно будет "переиграть" город с начала (по кр мере так в классической версии алгоритма, понятно, что в игре никто так делать не станет, уж лучше локальный артефакт, чем перестройка всего мира).
Далее, основная проблема WFC - он строит правдоподобную структуру только в локальном масштабе. Собственно даже в описании алгритма так и написано:

This program generates bitmaps that are locally similar to the input bitmap.

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

По итогам получаем следующие результаты:

Шум перлина:
Локальная независимость +
Связность -
Непредсказуемость -
Города/дороги -

Клеточные автоматы:
Локальная независимость +/-
Связность +
Непредсказуемость -
Города/дороги +

Генеративные алгоритмы (WFC):
Локальная независимость -
Связность -
Непредсказуемость -
Города/дороги +

#11
(Правка: 17:08) 14:51, 23 мая 2021

Теперь о моем решении.

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

Далее. На большом масштабе я использую искаженную гексагональную сетку.

+ Показать

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

Разбитие пространства на большие куски позволяет строить крупномасштабную структуру, в которой природный ландшафт (моря, реки, горы) будут перемежаться с городами и селами.
Город/село помещаем в центр гекса, а переферию гекса делаем морями/полями/горами. Сами моря генерируем по шуму Перлина. Поскольку шум перлина локален, то не возникает проблем сшивания соседних гексов - у них ландшафт будет совпадать на границах.

Почему именно гексы а не прямоугольная сетка? Ну причины очевидны. Гексы менее изотропны, в них нет явных выделенных направлений. В случае прямоагольной сетки у меня были бы только горизонтальные и только вертикальные дороги, что бросалось бы в глаза. В случае гексов определенная изотропность тоже есть, но не такая уж явная.
Кроме того, гексы это частный случай диаграммы Вороного. А это хорошо. В них нет точек, очень удаленных от центра. У прямоугольников же всегда есть углы, которые далеко от центра. Кроме того в этих углах встречались бы четыре острова. А в гексагональной сетке - только три.

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

Далее. На среднем масштабе я строю содержимое острова. В первую очередь дороги. Поскольку у нас уже есть шесть входящих дорог (как описано выше), то от них строится продолжение. Можно строить одну "окружную" дорогу по периметру острова, таким образом соединяя все 6 входящих дорог, либо же можно строить город в центре, где строить перекресток, опять же соединяющий эти дороги.
Пока что я выбрал второй вариант как более простой. Хотя если взять тотже GTA, то там всегда есть окружная дорога, которая идет по периметру острова.
Итак я выбираю центр острова (со случайным смещением естественно), и вокруг него строю кольцо (на самом деле гекс), куда входят шесть дорог. И затем это кольцо становится внешним кольцом города. А снаружи - внешняя часть с природным ландшафтом.

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

В результате получаем город с улицами:

+ Показать

+ А здесь некоторые удачные и не очень варианты, которые я получал в процессе разработки

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

Таким образом, если оценить этот алгоритм по сформулированным критериям, то:

Локальная независимость +
Связность +
Непредсказуемость +/-
Города/дороги +

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

#12
(Правка: 15:58) 15:57, 23 мая 2021
Затравка под описание построения зданий
#13
17:16, 23 мая 2021

Zeus44
> В результате получаем город с улицами:
Все города напоминают Москву ))
Zeus44
> Сделал процедурный заборчик.
Круто! Это можно продавать в ассет сторе ;)

#14
(Правка: 18:24) 18:23, 23 мая 2021
Все города напоминают Москву ))
Нет, не все. Я изучил тонну pdf про генерацию городов, и знаю что типов городов только в самом простом случае - три вида.
А есть еще экзотические и те, что предлагались архитекторами, тогда еще больше.
Вообще я пока за референс беру нью-йорк.
Круто! Это можно продавать в ассет сторе ;)
Да там есть подобное.
Страницы: 1 2 38 9 Следующая »
ПроектыФорумОцените