Como posso gerar terrenos no estilo Worms?

48

Estou trabalhando em um jogo estilo Worms e quero gerar um terreno proceduralmente. Eu já fiz muita geração de terreno usando ruído perlin, e foi isso que comecei a usar para este jogo. O único problema é que é muito simples e chato, me dando algumas colinas, mas não a complexidade que eu quero. Eu gostaria de ter características como cavernas e montanhas suspensas e não me importo de ilhas flutuantes e coisas do tipo. Algo assim, mas ainda mais louco seria bom:

insira a descrição da imagem aqui

Pensei em primeiro gerar o terreno usando o ruído perlin clássico e depois remover as peças para criar cavernas e o que não, mas estou tendo problemas para orientar a remoção dessas peças. Existem alternativas para gerar um terreno assim?

Xeon06
fonte
O vermelho representa cavernas ou isso é apenas parte do terreno?
Richard Marskell - Drackir
Faz parte do terreno. Acabei de pesquisar no Google essa imagem, foi a mais próxima do que quero realizar. A parte "caverna" pode ser aquele pequeno buraco à direita, se continuar mais dentro do terreno à esquerda.
Xeon06
@Drackir, editou a imagem.
Xeon06
Relacionado: gamedev.stackexchange.com/questions/6721/… (mas não uma duplicata, pois parece focar na implementação versus os algoritmos de geração).
Josh
@JoshPetrie de fato. Eu sou bom com a destruição. É a geração com a qual estou tendo problemas.
Xeon06

Respostas:

51

Eu sugiro que você comece com o ruído 2D Perlin. Algo assim:

ruído permanente

Em seguida, aplique um limite na imagem, para obter várias ilhas isoladas, como mostrado aqui:

ruído permanente com limiar

Eu escolhi um limite de 0,04, tudo acima do limite seria colorido em azul. O restante permanece preto. Depois disso, é hora de determinar quais "ilhas" manter e quais jogar fora.

Uma abordagem possível seria percorrer a imagem da esquerda para a direita em várias alturas e selecionar as "ilhas" que se cruzam, com uma certa probabilidade. Na figura de exemplo, a linha mais baixa tem uma probabilidade de 100%; portanto, todas as ilhas que cruzar serão selecionadas (preenchidas em branco). A segunda linha tem uma probabilidade de 50% e a linha superior tem uma probabilidade de 10%.

Depois de marcar suas ilhas dessa maneira, você pode fechar as lacunas no meio aplicando uma operação morfológica ( dilatar )

ilhas dilatadas

E há uma paisagem possível.

A "granularidade" do ruído determinará quão pequenos serão os detalhes em seu mundo. Portanto, provavelmente é melhor experimentar esses valores.

Também onde e com quais probabilidades suas "linhas de seleção" estão posicionadas, o resultado será muito diferente. Se você tiver uma linha próxima ao topo da imagem com alta probabilidade de "selecionar" uma ilha, poderá criar algum tipo de paisagem de caverna, etc.

bummzack
fonte
Muito obrigado pela excelente resposta detalhada e ilustrada! Isto é exatamente o que eu vou fazer.
Xeon06
Você teria alguma dica sobre a geração desse ruído permanente, com esse nível de detalhe e tal? Eu tenho tentado a noite toda e não estou chegando a lugar nenhum.
Xeon06
@ Xeon06 Eu estava apenas usando a função de ruído Perlin fornecida pelo flash . Os parâmetros foram 24para baseXe baseY, 1 oitava e eu escolhi emitir ruído em escala de cinza e desativar o "fractal". Em qual idioma você está implementando isso?
bummzack
Estou implementando JavaScript. Venho vasculhando a web por uma boa implementação que daria resultados semelhantes por uma semana, mas não consegui encontrar nada.
Xeon06
Eu fiz uma outra pergunta referente à parte do ruído perlin gamedev.stackexchange.com/questions/20880/fast-noise-generation #
11401 Xeon06
6

Eu começaria com um ruído permanente, filtrado com cuidado. Você terminaria com algo como na figura anexada à pergunta, com ilhas flutuantes. Juste remove as ilhas flutuantes posteriormente usando um algoritmo de contagem como os discutidos aqui

Ravachol
fonte
Oh, acho que entendi agora. Preciso usar ruído perlin 2D, não 1D. Você poderia elaborar a referida filtragem?
Xeon06
2
Não posso postar fotos no momento, mas estou falando de um filtro de limite simples à la if (0.3> pixelValue> 0.5) KeepIt () ;. A parte 'cuidadosamente' é sobre como acertar 0,3 e 0,5. Você também pode ter um gradiente linear (ou não), começando com alfa alto na parte superior, chegando gradualmente a 0 na parte inferior, para ter espaço para um céu e o solo fica quase todo preenchido. Espero que ajude.
Ravachol
@ Ravachol Se você postar um link para uma foto, alguém com mais representantes poderá adicioná-lo à sua postagem.
Richard Marskell - Drackir
"if (0.3> pixelValue> 0.5)", acho que isso é apenas um erro de digitação, mas pode ser confuso ter coisas contraditórias em sua postagem ... Você pode editar isso?
jcora
Não consigo editar um comentário. Leia "if (0.3 <pixelValue <0.5)", obviamente.
Ravachol
4

Na verdade, eu implementei isso a partir da excelente resposta do bummzack.

Aqui estão as etapas que acabei com:

  1. Gere uma imagem com ruído Perlin
  2. Enchimento onde você deseja terrenos
  3. Dilatação + erosão para remover as cavidades muito pequenas
  4. Remova as demais regiões de segundo plano dentro do terreno
  5. Antialiasing

E este é um exemplo do resultado: exemplo de terreno gerado

Eu escrevi um artigo detalhado sobre todo o processo aqui e o código (JavaScript) é de código aberto, confira se você quer algo pronto para usar;)

Julian Go
fonte