Вы можете использовать алгоритм, который проверяет близкие блоки и изменяет вероятность в зависимости от того, что там есть, но я думаю, что это в значительной степени неправильный подход.
То, на что вы хотите обратить внимание, это фрактальные типы шума - в данном случае перлин или симплексный шум. Если вы генерируете шум, вы получите значения от -1 до 1.
http://en.wikipedia.org/wiki/Perlin_noise
Затем вы можете отрегулировать уровень воды, установив порог того, что делает воду. Для других блоков вы можете запустить второй набор шумов, чтобы переключаться между камнем и травой. (таким образом, у вас могут быть большие куски воды, но небольшие куски камня).
getTerrain(x,y) {
if(perlin_noise(x,y) > 0) {
if(perlin_noise(x * scale,y * scale) > 0) {
return rock
} else {
return dirt
}
} else {
return water
}
Поскольку я считаю, что метод сканирования и броска слишком сложен и не слишком масштабируем, я предложу другой метод, который мне понравился:
Положите сетку на карту, разбивая карту на большие квадраты.
Генерация случайного числа на каждом перекрестке (от 0 до 1 будет работать для ваших процентов)
Разделите, разрезав каждый квадрат на 4 четных квадрата - следуйте старым линиям, и там, где вы найдете линии подразделения, сгенерируйте случайное число между 2 смежными точками, аналогично, для центра креста, сгенерируйте точку, которая находится между самой высокой и самые низкие значения.
Промыть и повторить. Вы получите начальную случайность с первого прохода, но последние проходы дадут некоторую однородность. Извините за псевдослучайные числа:
0-------5 0---3---5 0-1-3-4-5 011233455
| | | | | | | | | | 012344555
| | | | | 0-2-4-6-5 002445665
| | | | | | | | | | 123445666
| | 2---5---7 2-4-5-7-7 234455777
| | | | | | | | | | 233455688
| | | | | 2-3-5-5-9 223455589
| | | | | | | | | | 233455589
2-------9 2---4---9 2-4-4-5-9 234445579
Это работает даже лучше для треугольников, потому что у вас нет потерянной поперечины, когда вы делите.
Конечно, абсолютный лучший результат будет получен при объединении этих методов - слой за слоем, некоторые методы дадут вам огромные массы земли, другие дадут вам потрясающие пещеры, другие будут работать на холмах, а другие будут работать на водные системы.
Шум является хорошим решением, как уже упоминалось. Другой вариант - сделать второй проход данных, чтобы подтолкнуть их к нужному макету. Размытие по Гауссу - один из многих способов добиться этого. Выполнение прохода с этим должно дать вам хорошие "круглые" капли каждого типа.
Независимо от того, какой метод вы используете, важно помнить одну вещь - сохранять результаты процесса в новом месте. Если вы измените карту на месте, части, которые вы уже обработали, начнут влиять на алгоритм, и вы получите странные шаблоны.
источник
Относительно простым способом сделать это было бы создание нескольких ядер в случайных положениях. Нарисуйте диаграмму Вороного этих точек. Присвойте элемент каждой области результата.
Это приводит к чему-то довольно уродливому и механически выглядящему. Немного испортите границы, и вы будете в приличной форме.
Если вы генерируете для большой карты, вы можете сделать это на двух уровнях. Создайте исходную диаграмму Вороного, используя, скажем, 20 ядер, и назовите каждый полученный регион нацией. Создайте еще одну диаграмму, используя 400 ядер, и назовите каждую полученную область викарием.
Все викарии, полностью содержащиеся в нации, будут иметь элемент нации. Викариумы, частично содержащиеся в двух или более нациях, будут случайным образом брать один из элементов вмещающих их наций.
Этот пост заслуживает картины, но мне лень ее предоставить.
источник
Генератор полигональных карт будет полезен для создания карт с различными «зонами», которые также дадут вам лучшие карты. Он основан на диаграммах вороной, но я думаю, это будет хорошим началом.
источник
Вы можете сделать это, используя этот метод:
источник