Как сделать 3д карту мира майнкрафт
Перейти к содержимому

Как сделать 3д карту мира майнкрафт

  • автор:

BlueMap — 3D карта вашего мира \ сервера, объемная полноценная WEB карта [1.20.2] [1.19.4] [1.18.2] [1.16.5]

BlueMap - 3D карта вашего мира сервера, объемная полноценная WEB карта [1.20.2] [1.19.4] [1.18.2] [1.16.5]

Мод BlueMap — добавит в майнкрафт ВЕБ карту вашего мира, вы можете открыть ее в браузере и перемещаться по миру, видеть все ваши постройки. Но это не просто карта подобно dynmap, она имеет свободный режим при котором вы можете летать по карту аналогично полету в креатив режиме самой игры. Ближайшее сравнение — это режим просмотра улиц в современных картах.

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

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

Настройки:

После установки карты в папке \.minecraft\config\bluemap вы найдете конфиг файлы.
Вы можете установить свой ресурспак, указать значения по умолчанию, настроить WEB сервер для карты.
Для этого нужно указать IP и порт, обратите внимание, что строка с IP портом закомментирована символом #, т.е не работает, указав свой IP, уберите #.
Вы так же можете почитать офф вики, там полно советов.

Как установить мод:

  1. Установи Forge или Fabric
  2. Установи все дополнительные моды если указано.
  3. Скачай мод и скопируй в .minecraft/mods
  4. В лаунчере запускай версию игры с форджем или фабриком.

Как происходит генерация мира Minecraft

image

Задумывались ли вы когда-нибудь, сколько на нашей планете песчинок? По грубым оценкам, более 7 квинтиллионов! Это 7 с 18 нулями. И всё-таки это даже меньше половины количества уникальных миров в Minecraft. Как же Minecraft и другим похожим играм удаётся создавать такие сложные, красивые, однако полностью процедурные миры? В этой статье я расскажу, как игра генерирует свои миры, от самой высокой горы до самой глубокой пещеры.

Часть 1: процедурная генерация

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

Однако первой игрой с процедурно сгенерированным миром является «Elite», первая версия которой вышла для компьютера BBC Micro в 1984 году. Это прапрадед относительно новой «Elite: Dangerous», выпущенной в 2014 году.

Автоматическая генерация новых миров может казаться привлекательным способом ленивого создания бесконечного контента для игры. Однако на самом деле всё наоборот! Чтобы научить машину тому, как выглядит хороший уровень… нужно быть очень хорошим программистом и дизайнером уровней.

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

Процедурная генерация контента определённо не для слабых духом. Однако какими бы ни были ваши алгоритмы, все они зависят лишь от одного аспекта: случайности. И Minecraft в этом не исключение: каждый мир начинается с порождающего значения (seed); по сути, это число, используемое для инициализации генерации рельефа и всего, что на нём будет находиться.

Пусть эти алгоритмы и случайны, однако они детерминированы. Это значит, что при наличии одинаковых исходных условий (одинакового seed) они всегда дают одинаковые результаты. И именно благодаря этому каждый мир Minecraft можно воссоздать по его seed. А поскольку сами seed хранятся как 64-битные числа, то существует 18,4 квинтиллиона уникальных значений, которые можно создать.

В No Man’s Sky тоже используются 64-битные seed, и это объясняет, почему в этой игре тоже 18,4 квинтиллиона уникальных планет.

«Rogue» (1980 год)

Но как случайные числа (по сути, получаемые «бросанием кубиков» компьютером) могут создавать миры? Наверно, для объяснения нужно начать с чего-то меньшего, чем Minecraft. Добро пожаловать в «Dungeons of Doom».

Выпущенная в 1980 году игра «Rogue» считается первой графической адвенчурой, она стала главным источником вдохновения для разработчиков тысяч игр в жанре dungeon crawler, выпущенных за последующие десятилетия.

Minecraft тоже позаимствовала многие характеристики, сделавшие Rogue знаменитой, и генерация процедурных подземелий для исследований — лишь одна из них.

Rogue обычно называют первой «графической» адвенчурой, и она определённо была, по крайней мере, одной из первых.

Как же Rogue создавала свои «Dungeons of Doom» (подземелья рока) в 1980 году? Каждый уровень разделялся на сетку 3 на 3, а в каждую ячейку помещалась случайная комната.

Далее алгоритм выбирал комнату для создания игрока и помечал её как «достижимую». Затем он итеративно обходил все остальные комнаты, соединяя их с ранее достигнутым соседом (если это возможно), или переходя к следующей. Затем в последней присоединённой комнате размещалась лестница на следующий уровень.

В Rogue также могли появляться тупики, потайные двери и даже комнаты монстров! И всё это было реализовано примерно в девяти тысячах строках кода и более чем трёхстах функциях! …307, если точнее! Для сравнения: в Minecraft 1.18 насчитывается более 52 тысяч функций, находящихся примерно в 4200 файлах!

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

Исходный код Rogue

Оригинальный исходный код «Rogue» можно найти в проекте Decoded: Rogue, где Mai Zure провёл тщательный разбор каждого файла. Основная часть кода была написана до появления стандарта ANSI C, что объясняет присутствие большого количества того, что не стоит считать антипаттернами.

Например, авторы использовали макросы для создания циклов until :

#define until(expr) while(!(expr))

И как будто этого недостаточно, они ещё и заменили ключевые слова C case и default на when и otherwise :

#define when break;case #define otherwise break;default

Недавно я говорил об этом в Twitter, что привело к интересному обсуждению:

Когда вы почувствуете вину из-за написанного вами кода, то просто вспомните, что в исходном коде «Rogue» были макросы для переопределения ключевых слов switch .

#define when break;case
#define otherwise break;default

Кодинг «Rogue» в 1980-х, должно быть, сильно походил на игру в рогалик. pic.twitter.com/HbAJbwqlBP— Alan Zucconi (@AlanZucconi) December 18, 2020

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

Исходный код Minecraft

Строго говоря, исходный код Minecraft никогда не публиковался. Однако учитывая, что основная версия игры написана на Java, её достаточно легко декомпилировать. Mojang была толерантна и поддерживала эту практику, поскольку она помогала создать сообщество моддеров.

Если вам любопытно узнать больше об исходном коде Minecraft, то стоит изучить MCP Reborn — Mod Coder Pack, предназначенный для создания модифицированных клиентов и исследования их внутренней работы.

Часть 2: история Minecraft

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

И было неправильным говорить об истории Minecraft без упоминания игры, которая стала источником вдохновения её разработчика: «Infiniminer».

Поначалу кажется, что это игра про добычу полезных ископаемых, в которой две команды соревнуются в сборе наибольшего количества руды, золота и алмазов. Но «Infinimer» был не только про добычу ресурсов, но и про создание; не только своей базы, но и историй.

Легко заметить, что игра стала непосредственным источником вдохновения для разработки Minecraft: блоки, кирка, пещеры и лавовые озёра, золото и алмазы, небо и пустота! Даже TNT! В параллельной Вселенной Minecraft могла бы выглядеть так.

Хотя каждая карта «Infiniminer» далеко не бесконечна, все они и в самом деле генерируется процедурно. Всё начинается с цельного блока земли, в котором отрисовывается множество рудных жил. Каждая начинается в случайной точке, и при каждой итерации жила движется в случайном направлении. Эта техника называется «случайным блужданием» (random walk).

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

Такой подход может показаться простым, может, даже слишком, однако это очень похоже на то, как работала Minecraft в первые девять месяцев своей разработки. В своей самой первой версии, в то время называвшейся «Cave Game», каждый мир состоял всего из 256 блоков в ширину и 64 в высоту.

Чтобы реализовать мечту о безграничном мире Minecraft, потребовалось девять месяцев. И реализована она была при помощи очень простого трюка: каждый раз, когда игрок забирался слишком далеко, создавался новый «фрагмент» мира.

Благодаря этому каждый мир был ограничен ПО: например, на 32-битной системе это примерно расстояние в 4,3 миллиарда блоков от точки создания игрока.

Но постойте, прежде чем вы начнёте паковать рюкзак, знайте, что на самом деле так далеко забраться невозможно! Игроки ограничены площадью 60 000 000 на 60 000 000 блоков. По сравнению с бесконечностью кажется, что это не очень много. Однако это всё равно в семь раз больше, чем поверхность Земли. Примерно в половину размера Нептуна!

Земля Minecraft Нептун
Радиус 6371 км 2 16925 км 2 24622 км 2
Площадь поверхности 510064 км 2 3600000000 км 2 7618000000 км 2
Сторона квадрата 22584 км 60000 км 87281 км

Но даже при этом «больше» не всегда означает «лучше». Ни одна версия Minecraft не даёт игрокам никакой новой геймплейной механики в масштабе больше 25000 блоков. Хотя вблизи мир выглядит богатым и разнообразным, но чем дальше мы отходим, тем сильнее начинает проявляться паттерн. Рано или поздно каждый достаточно большой фрагмент мира будет неотличим от любого другого. В таком масштабе мир Minecraft изотропен, почти как наша Вселенная при максимальном масштабе. Это даёт нам понимание об «истинном» масштабе, в котором в неё нужно играть. И, следовательно, о масштабе, в котором должна по-настоящему работать генерация мира.

2048 блоков

32768 блоков

131072 блока

524288 блоков

2097152 блока

Как генерировать карты биомов?

Minecraft позволяет игрокам рендерить карты мира при помощи стола картографа. Однако она может иметь ограниченное разрешение. Если вы хотите генерировать крупные карты биомов, то лучше всего использовать одну из множества утилит, созданных сообществом моддеров. Две лучшие Java-библиотеки — это BiomeUtils автора KaptainWutax и SeedFinding/mc_biome_java автора hube12. Для более новых версий Minecraft ещё одна библиотека на C — это Cubitect/cubiomes.

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

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

Спустя девять месяцев после обновления, добавившего «бесконечность», в версии Alpha 1.2.0, больше известной как «Halloween Update», появилось десять таких биомов.

Игра определяла, к какому биому принадлежит конкретная часть мира, довольно простым образом: при помощи так называемых «карт шума». Если вкратце, это изображения, пиксели которых созданы при помощи случайных чисел. На основании исходных параметров и конфигурации их можно использовать для генерации множества различных паттернов.

В ранних версиях Minecraft использовались три такие карты шума. Одна — для определения высоты рельефа, две другие — для температуры и осадков.

И именно сочетание последних двух определяло биом области.

Высокая температура и низкая влажность? Пустынный биом!

Низкая температура и низкая влажность? Биом тундры!

Это сработало, потому что карты температуры и осадков были достаточно плавными, поэтому между биомами присутствовали переходы. Это значило, что редко можно было встретить лес по соседству, допустим, с саванной.

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

Существенно переделали эту систему в Beta 1.8: «Adventure Update».

Во-первых, разработчики избавились от Далёких земель. Они обозначали своего рода точку невозврата, после которой генерация мира переставала работать правильно. Они обнаруживались на расстоянии примерно 12 миллионов блоков в любом направлении от точки создания игрока.

Однако избавление от Далёких земель стало лишь побочным эффектом более глубоких изменений. В «Adventure Update» появился совершенно новый генератор рельефа!

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

Всё полностью изменилось в Minecraft 1.7.2, больше известной как «The Update that Changed the World». И это обновление действительно изменило довольно многое! Например, сильно уменьшился размер океанов.

За три года Mojang существенно изменила способ генерации миров. Причём дважды! И это достаточно сильно повлияло на все старые серверы, например, на знаменитый 2b2t – старейший анархический сервер Minecraft. FitMC записал очень интересное видео, демонстрирующее, как такое простое изменение, вроде апгрейда на новую версию, навсегда изменило и так уже неспокойную ситуацию на 2b2t.

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

И хотя в Minecraft 1.18 кое-что изменилось, миры, которые вы годами исследовали, строили, любили и теряли… были созданы одним и тем же алгоритмом.

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

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

Хм, наверно, это не самый эффективный способ объяснения работы алгоритма.

Может быть, стоит показать на примерах?

Часть 3: генерация мира

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

Во второй фазе генерации мира происходит работа с рельефом, она разбита на три этапа.

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

На последующем этапе все каменные блоки на поверхности заменяются типом, соответствующим их биому. Травой в случае равнин, песком для пустынь, гравием для океанов, и так далее. Также на этом этапе генерируется слой коренной породы. Любопытно, что в Java Edition её паттерн не зависит от seed мира и одинаков для каждого мира Minecraft.

На третьем этапе из камня вырезаются пещеры и ущелья.

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

Давайте подробнее рассмотрим, как работает каждая фаза…

Карта биомов

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

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

Миры Minecraft создаются при помощи не одного, а целых четырёх наборов слоёв.

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

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

Разумеется, у Minecraft нет кубика D10, однако она может «бросать» случайные числа при помощи так называемого квадратичного конгруэнтного генератора.

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

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

Например, если пиксель из Island layer соответствует 4096 блокам, то каждый добавленный после масштабирования пиксель будет иметь в игре размер 2048 блоков.

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

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

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

Если выполнять этот слой снова и снова, то мы увидим, что он не всегда обеспечивает одинаковый результат. Даже слои добавляют случайности!

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

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

Основная часть формы суши создаётся попеременным использованием слоёв AddIsland и Zoom. Это позволяет создавать в мире уникальные элементы в различных разрешениях.

Области океанов

Форма океана в основном задаётся двумя слоями.

Первый был добавлен в «Adventure Update», чтобы сделать мир менее «континентальным» и более «взаимосвязанным». В коде Minecraft это в буквальном смысле называется Remove Too Much Ocean («убираем слишком большое количество океана»).

Все области океана, окружённые океаном, имеют вероятность 50% превращения в сушу.

Это не только создаёт более фрагментированные побережья, но и изменяет соотношение суши к воде с 27% до более чем 50%.

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

Температуры и биомы

Ранее мы упоминали только два элемента: сушу и океан. Прелюдией к созданию биомов является последовательность слоёв климата, отвечающих за определение температуры каждой области: Warm (тёплый), Temperate (умеренный), Cold (холодный) или Freezing (морозный). В дальнейшем эта информация будет определять, в какие биомы могут превращаться эти области.

Сначала каждой точке суши случайно назначается температура: Warm (тёплая), Cold (холодная) или Freezing (морозная) в пропорциях 4, 1 и 1.

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

Любая тёплая суша по соседству с холодной или морозной превратится в умеренную. А морозная суша рядом с тёплой или умеренной превратится в холодную.

В конечном итоге эти температуры являются основным фактором определения того, каким биомом станет конкретный фрагмент суши. Например, тёплые области имеют вероятность 50% превращения в пустыню, 33% в саванну, а оставшиеся 17% — в равнины.

Аналогичным образом умеренные, холодные и морозные области имеют определённые вероятности превращения в умеренный, холодный и морозный биомы (леса, тайгу и ледяные равнины).

Варианты биомов

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

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

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

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

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

Второй слой (Shore) также добавляет пляжи, на которых суша встречается с мелководьем океана.

Редкие биомы

Особого упоминания заслуживают редкие биомы, поскольку их генерация выполняется немного иначе. Кроме назначения температур слой климата имеет вероятность 1/13 пометить область как «особую».

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

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

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

Легендарные грибные острова создаются схожим образом. Каждый блок океана, окружённый водой, имеет вероятность 1/100 превращения в грибное поле. Отвечающий за это слой находится довольно высоко, поэтому грибные острова обычно довольно большие и однородные.

Это один из редчайших биомов в Minecraft, единственный, где естественным образом не создаются враждебные мобы.

Слои создания рек

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

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

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

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

Набор слоёв температуры океана

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

Этот набор слоёв при помощи шума Перлина создаёт собственную карту температур. Это очень популярный алгоритм для создания процедурных карт шума, который был разработан в 1982 году, но не для игры, а для фильма «Трон».

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

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

Существуют ли альтернативы шуму Перлина?

С момента публикации статьи о шуме Перлина в 1985 году он стал очень популярен во всех медиа, где в той или иной форме присутствует процедурная генерация. Он настолько известен, что в большинстве движков имеется собственная реализация шума Перлина, например, Mathf.PerlinNoise движка Unity (документация) или Noise Texture Node в Blender.

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

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

Некоторые разработчики предупреждают, что не стоит во всём полагаться на шум Перлина как на первый, а иногда и единственный тип шума для творчества. Если вы хотите узнать об интересных альтернативах, не имеющих недостатков шума Перлина, то крайне рекомендую прочитать статью The Perlin Problem: Moving Past Square Noise.

Например, симплексный шум (наследник шума Перлина) вычисляется в сетке треугольников, благодаря чему карты получаются гораздо менее «квадратными». Симплексный шум был запатентован, но срок действия патента истёк в январе 2022 года. Кроме того, существует множество оперсорсных реализаций, например, OpenSimplex автора K.jpg.

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

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

После этого у нас на руках остаётся готовая карта биомов, в которой каждый пиксель соответствует реальному блоку игры.

И мы готовы двигаться к следующей фазе!

Высота рельефа

Во второй фазе, разбитой на три этапа, генерация мира занимается рельефом.

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

Первый из трёх этапов генерации рельефа Minecraft определённо требует подробного объяснения.

Minecraft создаёт сложный и интересный рельеф при помощи техники под названием «фрактальный шум броуновского движения»: это ещё одно название карты шума.

Фрактальный шум создаётся сложением нескольких карт шума Перлина, сэмплируемых с разным масштабом. Каждая новая (называемая октавой) имеет в два раза большее разрешение по сравнению с предыдущей, но её вклад также снижается вдвое.

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

Minecraft запросто могла бы сэмплировать фрактальную карту в каждой координате , чтобы получить высоты рельефа. Однако алгоритмы игры работают иначе!

Так как же Minecraft получает высоту рельефа? Она начинает с самой вершины мира, в координате , и начинает двигаться вниз, вычисляя значение фрактального шума для каждой конкретной координаты вдоль этого виртуального столбца. Первая координата , для которой фрактальный шум равен или больше нуля, становится окончательной высотой рельефа в координате .

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

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

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

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

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

Строго говоря, в генерации рельефа задействовано ещё как минимум две карты шума. Карта «шума глубин» добавляет вариативности для компенсации того, что интерполяция между ячейками сглаживает мелкие детали. А карта «шума поверхности» определяет, сколько блоков камня нужно заменить стандартным блоком в каждом биоме.

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

Элементы мира

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

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

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

Эти подземелья — единственный способ попасть в измерение Край. В каждом мире есть лишь 128 крепостей, созданных внутри восьми концентрических колец, последнее из которых имеет радиус 22-24 тысяч блоков от начальной точки.

В каждом кольце крепости генерируются приблизительно под прямыми углами от центра.

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

Поздравляю: теперь вы специалист по процедурной генерации!

Ну а теперь давайте возьмём все полученные знания и выбросим их в лаву.

Часть 4: Minecraft 1.18+

Потому что с «Caves & Cliffs Update» в Minecraft 1.18 появился совершенно новый генератор рельефа. Раньше ландшафт имел высоту лишь 128 блоков, а теперь растянулся вверх на 320 блоков. Из-за такого увеличения вертикального пространства неудивительно, что одним из крупнейших изменений стали горы, которые теперь гораздо выше и пропорциональнее к остальной части мира.

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

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

Minecraft 1.16

Minecraft 1.18

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

И это тоже играет важную роль в новой системе пещер. Кроме вырезания пещер при помощи червей Перлина Minecraft 1.18 использует три новых типа пещер: «сырные» пещеры, «спагетти»-пещеры и «макаронные» пещеры. Да, здесь нет никакой ошибки.

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

Также появилась новая функция, создающая внутри пещер столбы.

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

Как же работает Minecraft 1.18? Это сложный вопрос. К тому же, учитывая новизну этой версии, может быть слишком поспешно вдаваться в подробности системы, в которую по-прежнему вносят улучшения и исправления.

Но могу сказать, что биомы и рельеф теперь связаны ещё теснее.

Если раньше ландшафт изменялся в зависимости от биома, теперь они оба зависят от 3D-карты климата.

Каждая четверть фрагмента — кусок размером 4x4x4 блока — получает из карты шума пять климатических параметров: температуру, влажность, «континентность», эрозию и «странность».

Первые два очевидны, «континентность» определяет, насколько далеко область находится от побережья, а от эрозии зависит, насколько плоским или гористым должен быть рельеф. «Странность» определяет варианты биомов.

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

Например, стандартная пустыня будет иметь высокую температуру, «континентальность» и эрозию, при этом низкую влажность и «странность». Все области, соответствующие этим параметрам, превратятся в пустыни.

Очень любопытно, что эта новая система работает схоже с Alpha 1.2.0, но с пятью параметрами (шестью, если учитывать ещё и глубину) вместо двух.

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

Часть 5: заключение

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

Тысячи людей использовали платформы для распределённых вычислений в поисках порождающего значения потерянного мира по одному изображению, а одна команда нашла высочайший кактус в игре — 23 блока!

Как найти высочайший кактус?

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

До июня 2022 года рекорд высочайшего кактуса в Minecraft 1.14 составлял 23 блока. Его можно найти в мире с порождающим значением 184693195438010998 в следующих координатах XYZ: 16274576 64 10230656 .

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

И как не упомянуть ежегодное соревнование The Generative Design in Minecraft Competition, участники которого стремятся расширить границы возможного для процедурной генерации.

В конечном итоге, именно это делает Minecraft настолько привлекательной игрой: вся её притягательная сложность возникает вследствие взаимодействия очень простых механик. И дело не только в геймплее, но и в генерации мира игры.

  • minecraft
  • процедурная генерация
  • процедурная генерация карт
  • шум перлина
  • карта шума
  • Разработка игр
  • Алгоритмы
  • Игры и игровые консоли

Создаём свою Minecraft: генерация 3D-уровней из кубов

Частично из-за популярности Minecraft, в последнее время наблюдается рост интереса к идее игры, действие которой происходит в состоящем из кубов мире, построенном из 3D-рельефа и заполненного такими элементами, как пещеры, обрывы и так далее. Такой мир — идеальное применение для шума, сгенерированного в стиле моей библиотеки ANL. Данная статья возникла из обсуждений моих предыдущих попыток реализации этой техники. С тех пор в структуре библиотеки появились незначительные изменения.

В предыдущих постах я рассказывал об использовании функций 3D-шума для реализации рельефа в стиле Minecraft. После этого библиотека немного эволюционировала, поэтому я решил вернуться к этой теме. Так как мне пришлось отвечать на множество вопросов по этой системе, я попытаюсь более подробно рассказать о задействованных концепциях. Чтобы базовые концепции были понятнее, я начну с идеи генерации 2D-рельефа, используемого в таких играх, как Terraria и King Arthur’s Gold, а затем расширю систему до 3D-примеров наподобие Minecraft. Это позволит мне эффективнее демонстрировать концепции на примере изображений.

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

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

Итак, мы просто моделируем землю и камни. Нам нужна функция, которая сообщит, чем должна быть заданная локация: землёй, песком, воздухом, золотом, железом, углём и т.д… Но мы начнём с самого простого. Нам нужна функция, которая скажет, является ли блок сплошным или полым (заполненным воздухом). Эта функция должна симулировать окружающую нас землю. То есть небо находится наверху, земля — снизу. Итак, давайте возьмёмся за библейскую задачу, и отделим небо от земли. Для этого изучим функцию Gradient. Функции Gradient передаётся отрезок прямой в N-мерном пространстве (т.е. в любом пространстве координат, будь то 2D, 3D, или выше), и она вычисляет поле градиента вдоль этого отрезка. Входящие координаты проецируются на этот отрезок и их значение градиента вычисляется в зависимости от того, где они лежат относительно конечных точек отрезка. Проецируемым точкам назначаются значения в интервале (-1,1). И это станет для нас хорошим началом. Мы можем задать функцию Gradient вдоль оси Y. В верхней части интервала мы сопоставим поле градиента с -1 (воздух), а в нижней — с 1 (земля).

terraintree= < >

(Вкратце объясню запись. Код примеров записан в виде таблицы объявлений Lua. Подробнее о формате можно прочитать в разделе про интеграции с Lua. По сути, формат предназначен для парсинга специальным классом, считывающим объявления и превращающим их в деревья экземпляров модулей шума. Я предпочитаю этот формат более многословному пошаговому формату C++, потому что компактнее и чище. По-моему, исходный код получается более читаемым и сжатым, чем код на C++. По большей части объявления легко читаемы и понятны. Модули имеют названия, источники заданы именем или значением. Код на Lua, используемый для парсинга объявления таблицы, включён в исходники на случай, если вы захотите использовать эти объявления напрямую.)

В случае 2D функция Gradient получает отрезок прямой в виде (x1,x2, y1,y2), а в случае 3D формат расширен до (x1,x2, y1,y2, z1,z2). Точка, образованная (x1,y1), обозначает начало отрезка прямой, сопоставленное с 0. Точка, образованная (x2,y2) — это конец отрезка, сопоставленный с 1. То есть здесь мы сопоставляем отрезок прямой (0,1)->(0,0) с градиентом. Следовательно, градиент будет находиться между областями функции Y=1 и Y=0. То есть эта полоса образует размеры мира по Y. Любая часть мира будет находиться в этой полосе. Мы можем привязать любой регион по X (практически до бесконечности, но здесь нас ограничивает точность double ), но всё интересное, т.е. поверхность земли, будет находиться в пределах этой полосы. Такое поведение можно изменить, но и в его пределах мы имеем большую степень гибкости. Просто не забывайте, что любые значения, которые находятся над или под этой полосой, скорее всего будут не интересными, потому что значения выше вероятнее всего будут воздухом, а значения ниже — землёй. (Как вы вскоре увидите, это заявление вполне может оказаться ошибочным.) Для большинства изображений в этой серии я буду сопоставлять квадратный регион, заданный квадратом (0,1)->(1,0) в 2D пространстве. Следовательно, в начале наш мир выглядит так:

Пока ничего интересного; к тому же, это изображение не отвечает на вопрос «заданная точка сплошная или полая?». Чтобы ответить на этот вопрос, нам нужно применить Step Function (кусочно-заданную функцию). Вместо плавного градиента нам нужно чёткое разделение, при котором все локации с одной стороны полые, а все локации с другой стороны — сплошные. В ANL это можно реализовать при помощи функции Select. Функция Select получает две входящие функции или значения (в этом случае они будут равны «сплошному» (Solid) и «полому» (Open)), и выбирает из них на основании значения контрольной функции (в данном случае Gradient). Модуль Select имеет два дополнительных параметра, threshold и falloff, которые влияют на этот процесс. На данном этапе falloff нежелателен, поэтому мы сделаем его равным 0. Параметр threshold решает, где будет проходить разделительная линия между Solid и Open. Всё, что в функции Gradient будет больше этого значения, превратится в Solid, а всё, что меньше порога — в Open. Так как Gradient сопоставляет интервал со значениями от 0 и 1, логично будет расположить порог в 0.5. Так мы разделим пространство ровно пополам. Значение 1 будет сплошной локацией, а значение 0 — полой. То есть мы зададим функцию плоскости земли следующим образом:

terraintree= < , >

Сопоставив ту же область функции, что и раньше, мы получим нечто подобное:

Такая картина чётко отвечает на вопрос, является ли заданная точка сплошной или полой. Мы можем вызвать функцию с любой возможной координатой 2D-пространства, и её результат будет равен или 1, или 0, в зависимости от того, где находится точка относительно поверхности земли. Тем не менее, такая функция не особо интересна, это всего лишь плоская линия, протянувшаяся в бесконечность. Чтобы оживить картину, мы используем технику под названием «турбулентность» («turbulence»).

«Турбулентность» — это сложное обозначение концепции добавления значений к входящим координатам функции. Представьте, что мы вызываем показанную выше функцию земли с координатой (0,1). Она лежит над плоскостью земли, потому что при Y=1 градиент имеет значене 0, что меньше threshold = 0.5. То есть эта точка будет вычислена как Open. Но что если перед вызовом функции земли мы каким-то образом преобразуем эту точку? Допустим, вычтем из координаты Y случайное значение, например, 3. Мы вычитаем 3 и получаем координату (0,-2). Если теперь мы вызовем функцию земли для этой точки, то точка будет считаться сплошной, потому что Y=-2 лежит ниже сегмента Gradient, соответствующего 1. Внезапно полая точка (0,1) превращается в сплошную. У нас получится висящий в воздухе блок сплошного камня. Так можно сделать с любой точкой в функции, прибавляя или вычитая случайное число из координаты Y входящей точки до вызова функции ground_select. Вот изображение функции ground_select, показывающее это. Перед вызовом функции ground_select к координате Y каждой точки прибавляется значение в интервале (-0.25, 0.25).

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

terraintree= < , , , , >

Здесь стоит заметить пару аспектов. Во-первых, мы задаём модуль Fractal, и соединяем его цепочкой с модулем ScaleOffset. Модуль ScaleOffset масштабирует выходные значения фрактала до более удобного уровня. Часть рельефа может быть горной и требовать большего масштаба, а другая часть — более плоской и с меньшим масштабом. О разных типах рельефа мы поговорим позже, а пока используем их для демонстрации. Выходные значения функции теперь дадут такую картину:

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

На показанном выше изображении все чёрные точки имеют значение -0.25, а все белые — значение 0.25. То есть там, где фрактал чёрный, соответствующая точка функции земли будет смещена «вниз» на 0.25. (0.25 обозначает 1/4 экрана.) Так как одна точка может быть смещена ненамного, а другая точка над ней в пространстве может быть смещена больше, то возникает вероятность появления выступов скал и летающих островов. Выступы в природе вполне естественны, в отличие от летающих островов. (Если только мы не в фильме «Аватар».) Если в вашей игре нужен подобный фантастический ландшафт, то замечательно, но если вам нужна более реалистичная модель, то нам нужно немного настроить функцию фрактала. К счастью, это способна сделать функция ScaleDomain.

Мы хотим заставить функцию вести себя подобно функции карты высот. Представьте 2D-карту высот, где каждая точка карты обозначает высоту точки в решётке точек сетки, которые подняты вверх или опущены вниз. Белые значения карты обозначают высокие холмы, чёрные — низкие долины. Нам нужно похожее поведение, но чтобы добиться его, нужно по сути избавиться от одного из измерений. В случае карты высот мы создаём 3D-рельеф из 2D-карты высот. Аналогично, в случае 2D-рельефа нам нужна 1D-карта высот. Сделав так, чтобы все точки фрактала с одинаковой координатой Y имели одинаковое значение, мы можем сместить все точки с одинаковой координатой X на одинаковую величину, благодаря чему летающие острова исчезнут. Для этого можно использовать ScaleDomain, обнулив коэффициент scaley. То есть перед вызовом функции ground_shape_fractal мы вызываем ground_scale_y, чтобы присвоить координате y значение 0. Это гарантирует, что значение Y не будет влиять на выходные данные фрактала, по сути превратив его в функцию 1D-шума. Для этого мы внесём следующие изменения:

terraintree= < , , , , , >

Мы соединим функцию ScaleDomain в цепочку с ground_scale, а затем изменим исходные данные ground_perturb, чтобы они были функцией ScaleDomain. Это изменит фрактал, смещающий землю и превратит его в нечто подобное:

Теперь если мы взглянем на выходные данные, то получим результат:

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

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

terraintree= < , , , , , , , , >

А вот результат:

Второй способ: можно просто присвоить параметру scaley функции ground_scale_y значение больше 0. Если оставить небольшой масштаб по Y, то мы получим долю вариативности, однако чем больше будет масштаб, тем сильнее рельеф будет напоминать прежнюю версию без масштабирования.

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

Взглянув на предыдущий пример кода, можно увидеть в нём определённый паттерн. У нас есть функция градиента, которая управляется функциями, придающими земле форму, после чего применяется кусочно-заданная функция и земля обретает заполненность. То есть усложнять рельеф логичнее будет на этапе придания земле формы. Вместо одного фрактала, смещающего по Y и другого, смещающего по X, мы можем добиться нужной степени сложности (с учётом производительности: каждый фрактал требует дополнительных вычислительных затрат, поэтому надо стараться быть консервативными.) Мы можем задать формы земли, представляющие собой горы, предгорья, плоские низины, пустоши, и т.д… и использовать выходные данные различных функций Select, объединённых в цепочки с низкочастотными фракталами, чтобы очертить области каждого типа. Итак, давайте посмотрим, как можно реализовать разные типы рельефа.

Чтобы проиллюстрировать принцип, мы выделим три типа рельефа: плоскогорья (плавные покатые холмы), горы и низины (по больше части плоские). Для переключения между ними мы используем систему на основе select и соединим их в сложное полотно. Итак, начинаем…

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

Плоскогорья:

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

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

Итак, здесь мы задаём три основных типа рельефа: lowlands, highlands и mountains. Используем один фрактал для выбора одного из них, чтобы присутствовали естественные переходы (lowlands->highlands->mountains). Затем используем ещё один фрактал для случайной вставки в карту пустошей (badlands). Вот как выглядит готовая цепочка модулей:

terraintree= < , , , , , , , , , , , , , , , , , , , , , >

Вот несколько примеров получаемых рельефов:

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

Для пещер я использую мультипликативную систему, применяемую к ground_select. То есть я создаю функцию, выводящую 1 или 0, и умножаю их на выходные данные ground_select. Благодаря этому полой становится любая точка функции, для которой значение функции пещер равно 0. То есть там, где я захочу получить пещеру, функция пещер должна возвратить 0, а там, где пещеры быть не должно, функция должна быть равна 1. Что касается формы пещер, я хочу основать систему пещер на основе 1-октавного Ridged Multifractal.

В результате получится нечто такое:

Если применить функцию Select как кусочно-заданную функцию, как мы делали с градиентом земли, реализовав её так, чтобы нижняя часть порога select была равна 1 (нет пещеры), а верхняя часть равна 0 (есть пещера), то результат будет примерно выглядеть так:

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

Это слегка зашумливает пещеры и делает их не такими плавными. Давайте теперь посмотрим, что произойдёт, если применить пещеры к рельефу:

Поэкспериментировав со значением threshold в cave_select, мы можем делать пещеры тоньше или толще. Но главное, что нам нужно попробовать — сделать так, чтобы пещеры не отъедали такие огромные фрагменты поверхностного рельефа. Для этого можно вернутся к функции highland_lowland_select, которая, как мы помним, является последней функцией рельефа, искажающей градиент земли. В этой функции полезно то, что она всё ещё является градиентом, увеличивающим значение при углублении функции в землю. Мы можем использовать градиент для ослабления функции пещер, чтобы пещеры увеличивались при углублении в землю. К счастью для нас, это ослабление можно реализовать просто умножением выходных данных функции highland_lowland_select на выходные данные cave_shape, а затем передать результат остальной цепочке функций. Далее мы внесём здесь важное изменение — добавим функцию Cache. Функция кэширования сохраняет результат функции для заданной входящей координаты, и если функция вызывается повторно с той же координатой, она вернёт кэшированную копию, а не будет вычислять результат повторно. Это полезно в подобных ситуациях, когда одна сложная функция (highland_lowland_select) в цепочке функций вызывается несколько раз. Без кэша вся цепочка сложной функции при каждом вызове вычисляется заново. Чтобы добавить кэш, нам сначала нужно внести следующие изменения:

Так мы добавили Cache, а затем перенаправили входные данные ground_select, чтобы они брались из кэша, а не напрямую из функции. Затем мы можем изменить код пещер, чтобы добавить ослабление:

Первым делом мы добавили функцию Bias. Это сделано ради удобства, потому что позволяет нам настраивать интервал функции ослабления градиента. Затем добавлена функция cave_shape_attenuate, которая является Combiner типа anl::MULT. Она умножает градиент на cave_shape. Затем результат этой операции передаётся функции cave_perturb. Результат выглядит примерно так:

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

terraintree= < , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , >

Вот примеры рандомизированных карт, полученных из этой функции:

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

Можно изменять эту систему множеством разных способов, получая различные результаты. Мы можем изменять параметры threshold для cave_select и параметры у cave_attenuate_bias, или заменять cave_attenuate_bias на другие функции, чтобы сопоставлять интервал градиента с иными значениями, лучше подходящими вашим потребностям. Также можно добавить ещё один фрактал, искажающий систему пещер по оси Y, чтобы устранить возможность появления неестественно плавных туннелей по оси X (вызванных тем, что форма пещер искажается только по X). Ещё можно добавить новый фрактал как дополнительный источник ослабления, задать третий источник для cave_shape_attenuate, масштабирующий ослабление на основе регионов, чтобы пещеры в некоторых областях располагались плотнее (допустим, в горах), а в других реже или вовсе отсутствовали. Этот региональный select можно создать из функции terrain_type_fractal, чтобы знать, где расположены области гор. Всё сводится просто к тому, чтобы продумать, чего вы хотите, разобраться в том, какое влияние разные функции будут оказывать на выходные данные, и поэкспериментировать с параметрами, пока не получите нужный результат. Это не точная наука, и часто к нужному эффекту можно прийти разными путями.

Недостатки

У этого метода генерации рельефа есть недостатки. Процесс генерации шума может быть довольно медленным. Важно по возможности уменьшать количество фракталов, количество октав тех фракталов, которые вы используете, и других медленных операций. Пытайтесь использовать фракталы многократно и кэшировать все функции, которые вызываются несколько раз. В этом примере я достаточно вольно пользовался фракталами, создав по одному для каждого из трёх типов рельефа. Воспользовавшись ScaleOffset для изменения интервалов и взяв за основу для них всех один фрактал, я бы сэкономил много процессорного времени. В 2D всё не так плохо, но когда вы доберётесь до 3D и попробуете сопоставлять объёмы данных, время обработки сильно увеличится.

Переходим в 3D

Всё это здорово, если вы создаёте игру наподобие Terraria или King Arthur’s Gold, но что, если вам нужно нечто наподобие Minecraft или Infiniminer? Какие изменения нам нужно будет внести в цепочку функций? На самом деле, их не так много. Показанная выше функция почти без модификаций сработает и для 3D-рельефа. Вам достаточно будет сопоставить 3D-объём, используя 3D-вариации генератора, а также сопоставить ось Y с вертикальной осью объёма, а не 2D-областью. Однако всё-таки потребуется одно изменение, а именно, способ реализации пещер. Как вы видели, Ridged Multifractal отлично подходит для 2D-системы пещер, но в 3D он вырезает множество искривлённых оболочек, а не туннелей, и его влияние оказывается неверным. То есть в 3D необходимо задать два фрактала форм пещер, оба являются 1-октавным шумом Ridged Multifractal, но с разными seed. При помощи Select задаём им значения 1 или 0, и перемножаем их. Таким образом, в местах пересечения фракталов появится пещера, а всё остальное останется сплошным, и внешний вид туннелей станет более естественным, чем при использовании одного фрактала.

terraintree3d= < , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , >

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

  • процедурная генерация карт
  • функции шума
  • процедурная генерация
  • minecraft
  • генерация карт

Мод: 3D Карта [1.18+]

Превью для «Мод: 3D Карта [1.18+]»

Мод Maps, but in 3D | Holographic map позволит вам ознакомиться с вашим миром в 3D, рассмотрев его рельефы. То есть вы сможете изобразить 3D карту своего мира в Майнкрафт ПЕ (Бедрок).

  • Особенность мода на 3D карту
  • Про 3D карту
  • Скачать

Особенность мода на 3D карту

Это отличный мод не только для выживания, но и для игры по сети. А также было бы прикольно использовать этот мод на разных картах в Minecraft PE (Bedrock). Где вы сможете использовать навигацию для игрока в 3D.

3D карта портала в Майнкрафт ПЕ (Бедрок)

Про 3D карту

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

3D карта в Майнкрафт ПЕ (Бедрок)

Скачать Мод на 3D карту для Minecraft PE (Bedrock)

Скачать holographic_mapresource_v1_0_3.mcpack (1.38 Mb)
797 скачиваний · mcpack · 11-январь-22
Скачать holographic_mapbehavior_v1_0_3.mcpack (438.67 Kb)
652 скачиваний · mcpack · 11-январь-22

Мод Maps, but in 3D | Holographic map позволит вам ознакомиться с вашим миром в 3D, рассмотрев его рельефы. То есть вы сможете изобразить 3D карту.

Похожие статьи:

Превью для «Мод: Мини карта [1.19+]»

Мод: Мини карта [1.19+]

Этот мод отлично подойдет для любителей путешествовать в Minecraft PE (Bedrock)! Так-как сверху в игре будет добавлена мини карта.

Превью для «Мод: Метка на карте [1.18+]»

Мод: Метка на карте [1.18+]

Это один из крутых модов для путешествия по миру выживания в Майнкрафт ПЕ (Бедрок). Тут вы сможете размещать метку на карте.

Превью для «Карта: Бой Роботов [1.18+]»

Карта: Бой Роботов [1.18+]

Вам нравится сражаться на разных картах вместе с друзьями? Тогда добро пожаловать на эту карту, где вы сможете устроить полную мясорубку.

Превью для «КАРТА: СКОПИРОВАТЬ КАРТИНКУ MINECRAFT 1.5 / 1.6»

КАРТА: СКОПИРОВАТЬ КАРТИНКУ MINECRAFT 1.5 / 1.6

Эта карта для Майнкрафт предназначена только для одного игрока, где он должен будет запомнить изображение

Превью для «Карта

Карта «Обзор обновления Minecraft 1.5.0.1» | Скачать бесплатно

Если Вы хотите подробно рассмотреть все нововведения в новой версии Minecraft 1.5.0.1, тогда обязательно скачайте эту карту для МКПЕ!

Превью для «Piston Password PE | Minecraft Pocket Edition 0.15.x»

Piston Password PE | Minecraft Pocket Edition 0.15.x

Карта «Piston Password PE» представляет собой карту-головоломку.Карта «Piston Password PE» представляет собой карту-головоломку.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *