Ищете хороший алгоритм генерации карты мира

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

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

Perlin noise

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

Random expansion

Кто-нибудь знает хороший алгоритм для создания реалистичных континентов на сетке, сохраняя контроль над их количеством и относительными размерами?

Ответ 1

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

Изменить: Здесь другой способ сделать это, в комплекте с реализацией - Создание многоугольной карты для игр.

Ответ 2

Я предлагаю вам создать резервную копию и

  • Подумайте о том, что делает "хорошие" континенты.
  • Напишите алгоритм, который может отличить хороший континентальный макет от плохого.
  • Уточните алгоритм, чтобы вы могли количественно определить, насколько хорош хороший макет.

После того, как вы это сделаете, вы можете начать реализовывать алгоритм, который должен иметь такую ​​форму:

  • Создайте дерьмовые континенты, а затем улучшите их.

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

Ответ 3

Я написал что-то похожее на то, что вам нужно, на автоматизированный клон Query Civilization 1. Для записи я написал это на VB.net, но так как вы не упоминаете ничего о языке или платформе в своем вопросе, я 'оставим его абстрактным.

В "карте" указано количество континентов, дисперсия по размеру континента (например, 1.0 сохранит все континенты с одинаковой приблизительной площадью земли, вплоть до 0,1, что позволит континентам существовать с 1/10 по массе самого большого континента), максимальная площадь земли (в процентах) для генерации и центральный уклон земли. "Семя" распределяется случайным образом вокруг карты для каждого континента, взвешивается по центру карты в соответствии с центральным смещением (например, низкое смещение создает распределенные континенты, более похожие на Землю, где, поскольку высокий центральный смещение будет напоминать больше Пангея). Затем для каждой итерации роста "семена" назначают земельные плитки по алгоритму распределения (подробнее об этом позже), пока не будет достигнута максимальная площадь земли.

Алгоритм распределения земли может быть столь же точным, как вы хотите, но я нашел более интересные результаты, применяя различные генетические алгоритмы и перекатывая кости. Конвей "Игра жизни" - очень простая задача, с которой можно начать. Вам нужно будет добавить НЕКОТОРУЮ глобальную логику, чтобы избегать таких вещей, как континенты, растущие друг в друге, но по большей части вещи заботятся о себе. Проблема, с которой я столкнулась с более фундаментальными подходами (это был мой первый наклон), - это результаты, которые выглядели слишком структурированными или приводили к слишком большому количеству сценариев, требующих обходных правил для взлома, чтобы получить результат, который еще не чувствовал себя достаточно динамичным. В зависимости от используемого алгоритма вы можете применить "размытие" прохода по результату, чтобы устранить такие вещи, как обильные одноквартирные океанские плитки и клетчатые береговые линии. В случае, когда какой-то континент будет порожден, окруженный несколькими другими, и нигде не будет расти, переместите семя в новую точку на карте и продолжите проходы роста. Да, это может означать, что иногда у вас больше континентов, чем планировалось, но если это действительно то, чего вы твердо не хотите, то другой способ избежать этого - это смещение алгоритмов роста, чтобы они способствовали росту в направлении с наименьшей близостью к другим семена. В худшем случае (по-моему, так или иначе), вы можете отметить серию как недопустимую, когда семя нигде не осталось расти и создать новую карту. Просто убедитесь, что вы установили максимальное количество попыток, поэтому, если указано что-либо нереальное (например, установка 50 равномерно взвешенных континентов на плате 10x10), он не проводит навсегда попытку найти правильное решение.

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

Ответ 4

Создание многоугольной карты описывают поэтапное формирование карты, не использующую полигоны Вороного.

Этот парень дает также все исходники. Это Flash (ActionScript 3/ECMAScript), но переносимый на любой другой объектно-ориентированный язык

Или попробуйте использовать алгоритмы, реализованные в некоторых программах фрактальной environement, например TerraJ

Ответ 5

Я создал нечто похожее на ваше первое изображение в JavaScript. Это не супер сложный, но он работает:

http://jsfiddle.net/AyexeM/zMZ9y/

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<style type="text/css">
    #stage{
        font-family: Courier New, monospace;
    }
    span{
        display: none;
    }
    .tile{
        float:left;
        height:10px;
        width:10px;
    }
    .water{
        background-color: #55F;
    }
    .earth{
        background-color: #273;
    }
</style>
</head>

<body>


<div id="stage">

</div>

<script type="text/javascript">

var tileArray = new Array();
var probabilityModifier = 0;
var mapWidth=135;
var mapheight=65;
var tileSize=10;

var landMassAmount=2; // scale of 1 to 5
var landMassSize=3; // scale of 1 to 5


$('#stage').css('width',(mapWidth*tileSize)+'px');


for (var i = 0; i < mapWidth*mapheight; i++) {

    var probability = 0;
    var probabilityModifier = 0;

    if (i<(mapWidth*2)||i%mapWidth<2||i%mapWidth>(mapWidth-3)||i>(mapWidth*mapheight)-((mapWidth*2)+1)){

        // make the edges of the map water
        probability=0;
    }
    else {

        probability = 15 + landMassAmount;

        if (i>(mapWidth*2)+2){

            // Conform the tile upwards and to the left to its surroundings 
            var conformity =
                (tileArray[i-mapWidth-1]==(tileArray[i-(mapWidth*2)-1]))+
                (tileArray[i-mapWidth-1]==(tileArray[i-mapWidth]))+
                (tileArray[i-mapWidth-1]==(tileArray[i-1]))+
                (tileArray[i-mapWidth-1]==(tileArray[i-mapWidth-2]));

            if (conformity<2)
            {
                tileArray[i-mapWidth-1]=!tileArray[i-mapWidth-1];
            }
        }

        // get the probability of what type of tile this would be based on its surroundings 
        probabilityModifier = (tileArray[i-1]+tileArray[i-mapWidth]+tileArray[i-mapWidth+1])*(19+(landMassSize*1.4));
    }

    rndm=(Math.random()*101);
    tileArray[i]=(rndm<(probability+probabilityModifier));

}

for (var i = 0; i < tileArray.length; i++) {
    if (tileArray[i]){
        $('#stage').append('<div class="tile earth '+i+'"> </div>');
    }
    else{
        $('#stage').append('<div class="tile water '+i+'"> </div>');
    }
}

</script>

</body>
</html>

Ответ 6

Просто подумайте о манжете:

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

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

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

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

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

Таким образом, вам нужно будет генерировать рельеф на каждом бите отдельно.

Ответ 7

У меня возникла идея создания карты, аналогичной ответу на тектонические плиты. Это произошло примерно так:

  • прокладываем квадраты сетки, давая каждому квадрату квадрат земли, если rnd <= 0.292 (фактический процент сухой земли на планете Земля).
  • Перенесите каждый кусок земли на один квадрат ближе к ближайшему более крупному соседу. Если соседи находятся на равном расстоянии, идите к большему куску. Если куски равного размера, выберите один случайным образом.
  • если два земельных квадрата касаются, группируйте их в кусок, перемещая все квадраты как один с этого момента.
  • повторите шаг 2. Остановитесь, когда все куски подключены.

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

  • Попадание в n квадратов земли стартера в случайных положениях x, y и допустимых расстояниях друг от друга. Это семена для ваших континентов. (Используйте теорему Пифагора, чтобы гарантировать, что семена имеют минимальное расстояние между собой и всеми остальными.)
  • создайте квадрат земли с существующего земельного квадрата в случайном направлении, если это направление представляет собой океанский квадрат.
  • повторите шаг 2. Остановитесь, когда квадраты земли заполняют 30% от общего размера карты.
  • Если континенты достаточно близки друг к другу, по возможности удаляйте наземные мосты, чтобы имитировать эффект типа Панамы.
  • Поместите меньшие, случайные острова, если хотите, чтобы выглядеть более естественным.
  • для каждого добавочного "островного" квадрата вы добавляете, вырезаете внутренние моря и озерные квадраты с континентов, используя тот же алгоритм в обратном порядке. Это будет поддерживать процент земли в желаемой сумме.

Сообщите мне, как это получается. Я никогда не пробовал это сам.

PS. Я вижу, что это похоже на то, что вы пробовали. За исключением того, что он устанавливает все семена сразу, перед началом, поэтому континенты будут достаточно далеко друг от друга и остановятся, когда карта будет заполнена.

Ответ 8

Вы можете попробовать алгоритм алмазного квадрата или перлинный шум, чтобы создать нечто вроде карты высоты. Затем присвойте значениям диапазонов значениям, отображаемым на карте. Если ваша "высота" идет от 0 до 100, то делайте 0-20 воды, 20-30 пляжей, 30 - 80 травы, 80 - 100 гор. Я думаю, что вырезание сделало что-то похожее на это в майнифте, но я не эксперт, я просто в алмазном менталитете, наконец, получив его работу.

Ответ 9

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

Сначала разрешить небольшие проблемы и объединить решения, позволяющие решать проблема.

A1= [elliptical rectangular random ... ]// list of continents with area A1 approx. 
A2= [elliptical rectangular random ... ]// list of continents with area A2 approx.
A3= [elliptical rectangular random ... ]// list of continents with area A3 approx.
...
An= [elliptical rectangular random ... ]// list of continents with area An approx.

// note that elliptical is approximately elliptical in shape and same for the other shapes.

Choose one/more randomly from each of the lists (An).

Now you have control over number and area of continents.

You can use genetic algorithm for positioning them 
as you see "fit" ;)

Будет очень полезно взглянуть на некоторые "алгоритмы компоновки графа"

Вы можете изменить их в соответствии с вашими задачами.

Ответ 10

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

Мир делится на регионы. в зависимости от размера мира, он определит, сколько регионов. В этом примере мы будем предполагать средний мир с 6 регионами. Каждая зона сетки разбивается на 9 зон сетки. эти зоны сетки разбиваются на 9 сеток. (это не для движения персонажа, а просто для создания карты). Решетки предназначены для биомов, сетчатые зоны предназначены для перечеркивания наземных объектов (континент и океан), а регионы - для общего климата. Сетки разбиваются на плитки.

Произвольно генерируемые регионы получают заданные логические климатические наборы. Зоны сетки распределяются случайным образом, например; океан или землю. Гриды получают назначенные биомы случайным образом с помощью модификаторов, основанных на их сетчатых зонах и климате, это леса, пустыни, равнины, ледниковые, болотные или вулканические. Как только все эти основы назначены, время смешивания их вместе, используя случайную функцию на основе процентов, которая заполняет наборы плитки. Например; если у вас есть лесной биом, рядом с пустынным биомом, у вас есть алгоритм, который уменьшает вероятность того, что плитка будет "лесной" и увеличится, что она будет "десертной". Итак, примерно на полпути между ними, вы увидите нечто вроде смешанного аффекта, сочетающего два биома с несколько плавным переходом между ними. Переход от одной зоны сетки к следующей, вероятно, займет немного больше работы, чтобы обеспечить логические наземные образования. Подобно, например, биому из одной зоны сетки, которая касается биома от другого, вместо того, чтобы иметь простой процент переключения, основанный на близости. Например, есть 50 плиток от центра биома до края биома, то есть есть 50 от края, к которому он касается центра следующего биома. Это логично оставляет 100% -ное изменение от одного биома к другому. Так как плитки приближаются к границе двух биомов, процент сужается примерно до 60% или около того. Было бы, я думаю, неразумно давать слишком большую вероятность пересечения биомов далеко от границы, но вам нужно, чтобы граница была несколько смешана. Для зон сетки процентное изменение будет намного более выраженным. Вместо того, чтобы% снизилось примерно до 60%, оно снизилось бы примерно до 80%. Затем необходимо выполнить вторичную проверку, чтобы гарантировать, что в середине наземного биома рядом с океаном нет никакой случайной водной черепицы без какой-либо логики. Итак, подключите эту водную плитку к массе океана, чтобы создать канал для объяснения водной черепицы или вообще удалить его. Землю в водном биоме легче объяснить с помощью обнажений горных пород и т.д.

О, вроде немой, извини.

Ответ 11

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

Ответ 12

Я на самом деле не пробовал это, но он был вдохновлен ответом Дэвида Джонстона относительно тектонических тарелок. Я попытался реализовать его сам в своем старом проекте Civ, и когда дело дошло до обработки столкновений, у меня возникла другая идея. Вместо того, чтобы создавать плитки напрямую, каждый континент состоит из узлов. Распределите массу для каждого node, затем создайте серию "blob" континентов, используя 2D-метабаллический подход. Тектоника и континентальный дрейф были бы смехотворно легко "подделать", просто перемещая узлы вокруг. В зависимости от того, насколько сложным вы хотите идти, вы можете даже применять такие вещи, как токи, для обработки движения node и генерации горных хребтов, которые соответствуют перекрытию границ плиты. Вероятно, это не придавало бы большого значения игровой стороне вещей, но это могло бы сделать интересное поколение карт с чисто академической точки зрения:)

Хорошее объяснение метабаллов, если вы раньше не работали с ними:

http://www.gamedev.net/page/resources/_//feature/fprogramming/exploring-metaballs-and-isosurfaces-in-2d-r2556