Вы читали «Хроники янтаря» Роджера Желязны?
Представьте, что вы играете в MMO от третьего лица. Вы появляетесь в мире и начинаете бродить вокруг. Через некоторое время, когда вы думаете, что изучили карту, вы понимаете, что находитесь в месте, которое вы никогда раньше не видели. Вы возвращаетесь в последнее место, в котором вы были уверены, что знаете, и оно все еще там. Но остальной мир изменился, и вы даже не заметили, как это произошло.
Я читал о процессуальном поколении мира. Я читал о перлинском шуме и октавах, симплексном шуме, алгоритме Алмазного квадрата, о симуляции тектонических плит и водной эрозии. Я полагаю, что у меня есть смутное понимание общего подхода в процессуальном мире.
И с этим знанием я понятия не имею, как вы можете сделать что-то, как написано выше. Каждая идея, которая приходит мне в голову, сталкивается с некоторыми теоретическими проблемами. Вот некоторые идеи, которые я могу придумать:
1) «Обратимое» поколение мира с начальным номером в качестве входного и некоторым полностью описывающим номером чанка
Я сомневаюсь, что это даже возможно, но я представляю себе функцию, которая получит начальное число и создаст матрицу чисел, на которой построены фрагменты. И для каждого уникального номера есть уникальный кусок. И вторая функция, которая получает этот уникальный номер чанка и производит начальное число, которое содержит этот номер. Я попытался сделать схему на картинке ниже:
2) Делаем куски совершенно случайными и делаем переход между ними.
Как предположил Арактор . Преимущества такого подхода в том, что он возможен и не требует магической функции :)
Минусы этого подхода, на мой взгляд, в том, что, вероятно, невозможно иметь разнообразный мир. Если у вас есть, скажем, и архипелаг, и континент, представленный только одним числом, и его соседние куски, то размер кусочка не будет равен континенту. И я сомневаюсь, что можно сделать красивый переход между кусками. Я что-то пропустил?
Другими словами, вы разрабатываете MMO с процедурно сгенерированным миром. Но вместо одного мира у вас много . Какой подход вы бы использовали для генерации миров и как бы вы осуществили переход игрока из одного мира в другой, не заметив этого перехода.
Во всяком случае, я думаю, у вас есть общая идея. Как бы вы это сделали?
источник
Ответы:
Используйте кусочек шума более высокого порядка. Если вы ранее использовали 2D-шум для карты высот, используйте 3D-шум с фиксированной последней координатой. Теперь вы можете медленно менять положение в последнем измерении, чтобы изменить местность. Поскольку шум Перлина непрерывен во всех измерениях, вы будете получать плавные переходы, пока вы плавно меняете положение, в котором вы выбираете функцию шума.
Если вы хотите изменить местность только на расстоянии от игрока в качестве смещения, например. Вы также можете сохранить смещение для каждой координаты на карте и только увеличивать, но никогда не уменьшать его. Таким образом, карта только обновляется, но никогда не стареет.
Эта идея также работает, если вы уже используете 3D-шум, просто сэмплируйте из 4D. Также обратите внимание на симплексный шум. Это улучшенная версия шума Perlin, которая работает лучше для больших размеров.
источник
Ваша идея разделить мир на несколько кусков неплоха. Это просто неполноценно.
Единственная проблема - соединения между кусками. Например, если вы используете перлин-шум для генерации рельефа, а семена различны для каждого куска и рискуете это произойти:
Решением было бы создание рельефа фрагментов не только из его шумов Perlin, но и из других фрагментов вокруг него.
Алгоритм Перлина использует значения случайной карты вокруг них, чтобы «сгладить» себя. Если они используют общую карту, то они будут сглажены вместе.
Единственная проблема заключается в том, что если вы измените чанк, чтобы он изменился, когда игрок отступит, вам также придется перезагрузить чанки, потому что их границы также должны измениться.
Это не изменит размер чанков, но увеличит минимальное расстояние от игрока до загрузки / выгрузки, потому что чанк должен быть загружен, когда игрок его видит, и, с помощью этого метода, как соседние чанки должны быть слишком ,
ОБНОВИТЬ:
Если каждый кусок вашего мира имеет другой тип, проблема возрастает. Это не просто облегчение. Дорогое решение будет следующим:
Давайте предположим, что зеленые куски - это лесные миры, синие - архипелаги, а желтые - плоские пустыни.
Решение здесь состоит в том, чтобы создать «переходные» зоны, в которых ваш рельеф и наземная природа (а также заземленные объекты или все, что вы хотите) будут постепенно переходить от одного типа к другому.
И как вы можете видеть на этой картинке, адская часть кода - это маленькие квадраты в углах чанков: они должны создавать связь между 4 чанками, потенциально разной природы.
Так что для этого уровня сложности я думаю, что классические поколения 2D-мира, такие как Perlin2D, просто не могут быть использованы. Я отсылаю вас к ответу @danijar за это.
источник
Хотя идея Данияра довольно солидна, в конечном итоге вы можете хранить много данных, если хотите, чтобы локальная область была одинаковой, а расстояние сдвигалось. И запрашивать все больше и больше кусков все более и более сложного шума. Вы можете получить все это более стандартным способом.
Я разработал алгоритм для процедурного генерирования случайного фрактального шума, частично основанный на алгоритме алмазного квадрата, который я установил как бесконечный и детерминированный. Таким образом, бриллиантовый квадрат может создавать бесконечный пейзаж, а также мой собственный довольно блочный алгоритм.
Идея в основном та же самая. Но вместо выборки шумов с более высокой размерностью вы можете перебирать значения на разных итерационных уровнях.
Таким образом, вы по-прежнему сохраняете запрошенные ранее значения и кешируете их (эту схему можно независимо использовать для ускорения уже сверхбыстрого алгоритма). И когда запрашивается новая область, она создается с новым значением y. и любая область, не запрошенная в этом запросе, удаляется.
Так что вместо того, чтобы смотреть сквозь другое пространство в дополнительных измерениях. Мы храним дополнительный бит монотонных данных для смешивания в разных (постепенно увеличивающихся количествах на разных уровнях).
Если пользователь перемещается в направлении, значения перемещаются соответственно (и на каждом уровне), и новые значения генерируются на новых краях. Если верхнее итеративное начальное число будет изменено, весь мир будет резко изменен. Если на последней итерации задан другой результат, то величина изменения будет очень незначительной + -1 блок или около того. Но холм все еще будет там, долина и т. Д., Но закоулки изменились. Если вы не зайдете достаточно далеко, и тогда холм исчезнет.
Так что, если мы храним 100x100 порций значений в каждой итерации. Тогда ничто не могло измениться в 100x100 от игрока. Но в 200x200 все может измениться на 1 блок. В 400x400 вещи могут измениться на 2 блока. На расстоянии 800x800 вещи смогут измениться на 4 блока. Так что все изменится, и они будут меняться все больше и больше, чем дальше вы идете. Если вы вернетесь назад, они будут другими, если вы зайдете слишком далеко, они будут полностью изменены и полностью потеряны, поскольку все семена будут заброшены.
Добавление другого измерения для обеспечения этого стабилизирующего эффекта, безусловно, будет работать, сдвигая y на расстоянии, но вы будете хранить большое количество данных для большого количества блоков, когда это не нужно. В алгоритмах детерминированного фрактального шума вы можете получить тот же эффект, добавляя изменяющееся значение (в другом количестве), когда позиция выходит за пределы определенной точки.
https://jsfiddle.net/rkdzau7o/
источник