Você leu The Chronicles of Amber de Roger Zelazny?
Imagine-se jogando no jogo MMO da terceira pessoa. Você cria no mundo e começa a passear. Depois de algum tempo, quando você pensa que aprendeu o mapa, percebe que está em um lugar que nunca viu antes. Você volta ao último lugar que tinha certeza de que conhece e ele ainda está lá. Mas o resto do mundo mudou e você nem percebeu como isso aconteceu.
Eu li sobre a geração processual mundial. Eu li sobre o ruído e as oitavas de Perlin, o ruído simplex, o algoritmo de diamante quadrado, sobre a simulação de placas tectônicas e a erosão hídrica. Acredito que tenho uma vaga compreensão da abordagem geral na geração processual mundial.
E com esse conhecimento, não tenho idéia de como você pode fazer algo como o escrito acima. Toda idéia que me vem à cabeça encontra alguns problemas teóricos. Aqui estão algumas idéias em que posso pensar:
1) Geração mundial "reversível" com um número inicial como entrada e algum número totalmente descritivo para um pedaço
Duvido que seja até possível, mas imagino uma função que receba uma semente e produza uma matriz de números sobre a qual os pedaços são construídos. E para cada número único, há um pedaço único. E uma segunda função, que obtém esse número de bloco exclusivo e produz uma semente, que contém esse número. Eu tentei fazer um esquema na imagem abaixo:
2) Tornar os pedaços completamente aleatórios e fazer uma transição entre eles.
Como Aracthor sugeriu. Os benefícios dessa abordagem é que é possível e não requer uma função mágica :)
Os contras que essa abordagem tem na minha opinião é que provavelmente não é possível ter um mundo diverso. Se você digitou o arquipélago e um continente representado por apenas um número e seus pedaços adjacentes, o tamanho de um pedaço não seria igual ao continente. E duvido que seja possível fazer uma transição bonita entre os pedaços. Estou esquecendo de algo?
Então, em outras palavras, você está desenvolvendo um MMO com o mundo gerado processualmente. Mas, em vez de ter um mundo, você tem muitos . Qual abordagem você adotaria para gerar mundos e como você implementaria a transição do jogador de um mundo para outro sem o jogador perceber a transição.
Enfim, acredito que você tenha uma ideia geral. Como você teria feito isso?
fonte
Respostas:
Use uma fatia do ruído de ordem superior. Se você usou o ruído 2D em um mapa de altura antes, use o ruído 3D com a última coordenada fixa. Agora você pode alterar lentamente a posição na última dimensão para modificar o terreno. Como o ruído Perlin é contínuo em todas as dimensões, você obterá transições suaves, desde que altere suavemente a posição em que mostra a função de ruído.
Se você deseja alterar apenas o terreno longe da distância do jogador, como deslocamento, por exemplo. Você também pode armazenar o deslocamento para cada coordenada no mapa e apenas aumentar, mas nunca diminuí-lo. Dessa forma, o mapa só fica mais novo, mas nunca mais antigo.
Essa idéia também funciona se você já estiver usando ruído 3D, basta experimentar a partir de 4D. Além disso, dê uma olhada no ruído Simplex. É a versão aprimorada do ruído Perlin e funciona melhor em mais dimensões.
fonte
Sua idéia de dividir o mundo em vários pedaços não é ruim. É apenas incompleto.
O único problema são junções entre os pedaços. Por exemplo, se você usar ruído perlin para gerar alívio e uma semente diferente para cada pedaço, e arriscar que isso aconteça:
Uma solução seria gerar alívio de partes não apenas a partir da sua semente de ruído Perlin, mas também de outras partes ao seu redor.
O algoritmo Perlin usa valores de mapa aleatório ao seu redor para "suavizar" a si mesmos. Se eles usassem um mapa comum, eles seriam suavizados.
O único problema é que se você alterar uma semente de pedaço para torná-lo diferente quando o jogador retroceder, será necessário recarregar os pedaços também, porque suas bordas também devem mudar.
Isso não mudaria o tamanho dos pedaços, mas aumentaria a distância mínima do jogador para ser carregado / descarregado, porque um pedaço deve ser carregado quando o jogador o vê e, com esse método, os pedaços adjacentes devem ser muito grandes. .
ATUALIZAR:
Se cada parte do seu mundo é de um tipo diferente, o problema aumenta. Não se trata apenas de alívio. Uma solução cara seria a seguinte:
Vamos supor que pedaços verdes sejam mundos florestais, arquipélagos azuis e desertos planos amarelos.
A solução aqui é criar zonas de "transição", nas quais a natureza do relevo e do solo (assim como os objetos aterrados ou qualquer outra coisa que você queira) passaria progressivamente de um tipo para outro.
E como você pode ver nesta foto, a parte mais difícil de codificar seria pequenos quadrados nos cantos dos pedaços: eles precisam fazer um link entre quatro pedaços, naturezas potencialmente diferentes.
Portanto, para esse nível de complexidade, acho que as gerações clássicas do mundo 2D como o Perlin2D simplesmente não podem ser usadas. Refiro-lhe a resposta @danijar para isso.
fonte
Embora a ideia de danijar seja bastante sólida, você pode acabar armazenando muitos dados, se quiser ter a área local igual e a mudança de distância. E solicitando mais e mais fatias de ruído cada vez mais complexo. Você pode obter tudo isso de uma maneira 2D mais padrão.
eu desenvolvi um algoritmo para gerar procedimentalmente o ruído aleatório do fractal, em parte com base no algoritmo do quadrado do diamante que consertei para ser infinito e determinístico. Assim, o quadrado de diamante pode criar uma paisagem infinita, bem como meu próprio algoritmo bastante bloqueado.
A ideia é basicamente a mesma. Mas, em vez de amostrar um ruído dimensional mais alto, é possível iterar valores em diferentes níveis iterativos.
Portanto, você ainda armazena os valores solicitados anteriormente e os armazena em cache (esse esquema pode ser usado independentemente para acelerar um algoritmo já super-rápido). E quando uma nova área é solicitada, ela é criada com um novo valor y. e qualquer área não solicitada nessa solicitação é removida.
Então, em vez de procurar em diferentes espaços em dimensões adicionais. Armazenamos um pouco mais de dados monotônicos para misturar diferentes (em quantidades progressivamente maiores em diferentes níveis).
Se o usuário viaja em uma direção, os valores são movidos de acordo (e em cada nível) e novos valores são gerados nas novas arestas. Se a semente iterativa principal for alterada, o mundo inteiro será mudado drasticamente. Se a iteração final receber um resultado diferente, o valor da alteração será muito menor que o bloco + -1. Mas, a colina ainda estará lá e o vale etc., mas os cantos e recantos terão mudado. A menos que você vá longe o suficiente, e então a colina desaparecerá.
Portanto, se armazenarmos 100x100 partes de valores a cada iteração. Então, nada poderia mudar a 100x100 do player. Mas, em 200x200, as coisas podem mudar em 1 bloco. Em 400x400, as coisas podem mudar em 2 blocos. A 800x800 de distância, as coisas poderão mudar em 4 blocos. Então as coisas vão mudar e vão mudar cada vez mais à medida que você avança. Se você voltar, eles serão diferentes; se você for longe demais, eles serão completamente mudados e completamente perdidos, pois todas as sementes serão abandonadas.
Adicionar uma dimensão diferente para fornecer esse efeito estabilizador certamente funcionaria, mudando o y à distância, mas você armazenaria muitos dados para muitos blocos quando não deveria. Nos algoritmos determinísticos de ruído fractal, você pode obter esse mesmo efeito adicionando um valor variável (em uma quantidade diferente) à medida que a posição se move além de um determinado ponto.
https://jsfiddle.net/rkdzau7o/
fonte