Какой самый простой метод для создания гладкой местности для 2d игры?

23

Какой самый простой способ создания гладкой местности для 2d-игры, такой как «Moon Buggy» или «Route 960»?

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

astropanic
источник

Ответы:

13

Один из способов добиться этого можно следующим образом:

  • Создайте точку в середине экрана со случайной высотой; Теперь у вас есть два раздела, по одному на каждой стороне этой точки
  • Для каждого раздела разделите на два, поместив точку в середине этого раздела, с (ранжированной) случайной высотой между двумя соседями.
  • Повторите n раз.

Происходит то, что детализация в пейзаже становится лучше с каждой итерацией.

То, как вы обрабатываете граничные случаи, зависит от вас: вы можете предположить точки в (0, высота / 2) и (ширина, высота / 2), например.

Надеюсь это поможет!

РЕДАКТИРОВАТЬ: Вот изображение, которое я сделал для иллюстрации:

terraingen

Это та же идея!

Тим Келсолл
источник
12

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

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

  1. Выберите 4 (реальные) числа случайным образом в диапазоне [1..10] - это будут частоты ваших синусоидальных волн. Я «бросил кости» на random.org и получил: f 0 = 1,75, f 1 = 2,96, f 2 = 6,23 и f 3 = 8,07. В цифре 4 нет ничего волшебного (вы можете использовать больше, но использование меньшего количества сделает более заметными отдельные синусоиды) или диапазон от 1 до 10 здесь (это просто способ убедиться, что ваш самый высокий и самый низкий частоты не слишком далеко друг от друга). Возможно, имеет смысл выбрать одну частоту в диапазоне [1..2], а остальные в диапазоне [2..10], чтобы у вас была известная «доминирующая» синусоида.
  2. Для каждого из этих четырех (или сколько) частот F I , выбрать амплитуду я где - то в интервале между -C / F я и C / F I для некоторой константы C . Значение, которое вы здесь выбираете, контролирует общую амплитуду вашей волны - для удобства я выбрал C = 1. Затем мне нужны были случайные числа в диапазоне [-1 / 1,75 (= -0,571) .. 1 / 1,75 (= 0,571) ] и аналогичным образом в диапазонах [-0,338 ... 0,338], [-0,161 ... 0,161] и [-0,124 ... 0,124]. Перекатывая кости четыре раза снова, я получил в 0 = -0.143, а 1 = -0.180, 2 = -0.012, иа 3 = 0,088. (Обратите внимание, что это, вероятно, не самый лучший способ сделать этот шаг - поскольку максимально возможное значение функции является суммой амплитуд abs ( a 0 ) + abs ( a 1 ) + abs ( a 2 ) + abs ( а 3 ), может иметь смысл разделить каждое из ваших четырех значений a i на эту сумму, как только вы сгенерировали их, а затем умножить каждое из них на C, чтобы вы могли быть уверены, что точный максимум, которого может достичь функция, равен C .)
  3. Выберите четыре «смещения» o i , каждое из которых находится в диапазоне [0..2π] (0..6.28) - они настроят начальные точки ваших волн так, чтобы они не все начинались с 0. Я получил o 0 = 1,73, o 1 = 4,98, o 2 = 3,17 и o 3 = 4,63.
  4. «Построить» функцию f (x) = a 0 sin ( f 0 (kx + o 0 ) ) + a 1 sin ( f 0 (kx + o 1 ) ) + a 2 sin ( f 0 (kx + o 0 ) ) + a 3 sin ( f 0 (kx + o 0 ) ) - здесь k - еще одна константа, управляющая горизонтальным «растяжением» ваших функций. Вы должны будете выяснить, что это для вашего собственного приложения; для удобства я просто выбрал к= 1, и поэтому моя общая функция: f (x) = -0,143 sin (1,75 ( x + 1,73)) - 0,180 sin (2,96 ( x + 4,98)) - 0,012 sin (6,23 ( x +3,17)) + 0,088 sin (8,07 ( х + 4,63)).

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

Простая случайная синусоида

Стивен Стадницки
источник
10

Алгоритм перемещения середины может генерировать красивый 2d ландшафта.

пример местности

Между смещением средней точки и тем, что предлагает @tykel, есть небольшая разница. Алгоритм Tykel разделяет горизонт и выбирает новую высоту. Это создает местность, где пики расположены равномерно. Люди прекрасно умеют определять закономерности, поэтому создаваемая местность будет казаться сгенерированной, а не естественной.

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

Случайное смещение высоты может привести к спуску местности, если вы добавите еще пару параметров (горизонтальное смещение, максимальный уклон и т. Д.). Это подчеркивает другую сильную сторону MPD; это очень просто настроить. Два параметра, ухабистость и уровень детализации.

deft_code
источник
7

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

Предположим, у вас есть высота h0в точке x0и высота h1в точке x1. Затем, чтобы получить высоту в любой точке x( x0<=x<=x1), вы используете

t = (x-x0)/(x1-x0); // map to [0,1] range
t = t*t*(3 - 2*t); // map to cubic S-shaped curve
h = h0+t*h1;

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

fbm(x)=h(x) + 0.5*h(2*x) + 0.25*h(4*x) + 0.125*h(8*x);

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

Это мощная техника. Вы можете играть с умножителем частоты, с весами разных частот, или добавить некоторые функции для искажения шума. Например, чтобы получить более «ребристое» ощущение, h(x)его можно изменить на 1-abs(h(x))(при условии -1<=h(x)<=1)

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

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

Не берите в голову
источник
4

Существует два популярных метода создания карт высоты местности.

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

msell
источник
ОП говорит о 2D, пейзажах в стиле Марио, но все же это хорошие ссылки.
Tenpn
1

Моя идея состоит в том, чтобы создать сглаженную шумовую функцию. Сначала с помощью метода intNoise (int), который возвращает «случайный» тип int, но который зависит от входных данных. Если вы используете один и тот же вход дважды, результат будет одинаковым.

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

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

XGouchet
источник