Como posso gerar aleatoriamente o terreno do scroller lateral baseado em blocos 2D?

11

Quero gerar aleatoriamente um mapa para um jogo side-scroller 2D usando o seguinte conjunto de peças: insira a descrição da imagem aqui

Encontrei ótimos artigos sobre o processo de criação de bit, por exemplo: http://www.angryfishstudios.com/2011/04/adventures-in-bitmasking/ http://www.saltgames.com/2010/a-bitwise -method-for-apply-tilemaps /

Eu gosto da idéia de usar uma máscara de bits / telha em vez de fazer uma enorme cláusula if ou instrução switch.

No entanto, estou tendo problemas para visualizar todo o processo e nenhum desses artigos fala sobre randomização.

Meus blocos se encaixam de várias maneiras diferentes, não apenas de uma maneira, como os blocos nos exemplos aos quais vinculei parecem.

Por exemplo, aqui estão apenas alguns exemplos:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Como minhas peças se encaixam de várias maneiras diferentes, não acho que uma máscara de 8 bits funcione. Portanto, eu estava pensando em usar uma máscara de bits maior. Algo como char [8] ou char 4 .

Se alguém pudesse, por favor, mostrar alguns pseudocódigo / exemplos de como seria o algoritmo geral, eu agradeceria muito.

erebel55
fonte

Respostas:

3

Sim, o tamanho da máscara aumentaria com o número crescente de opções - o seu próprio link http://www.saltgames.com/2010/a-bitwise-method-for-applying-tilemaps/ segunda parte explica a idéia principal.

Em essência, você teria que enumerar X possibilidades para cada 'borda' entre blocos; no seu exemplo específico, parece que o "bloco superior / inferior do bloco" pode ser (1) branco (2) coberto ou (3) coberto pela metade - o que coincide coincidentemente com o exemplo "trinário" fornecido no artigo.

Mas as máscaras apenas o ajudariam a restringir as possibilidades de blocos àquelas que podem ser desenhadas, por si só não é um método que mostra como gerar os mapas reais de uma maneira sensata.

Seu conjunto de peças em particular é realmente bastante restritivo - descreve apenas uma única superfície subindo / descendo e, em qualquer ponto inicial de 'nível inteiro', você tem apenas algumas opções válidas. Por exemplo, após o ladrilho nº 2, apenas os ladrilhos nº 1 ou 8 são possíveis. Você pode simplesmente mover da esquerda para a direita, fazendo uma lista de quais (poucos) blocos podem vir após o bloco anterior e escolhendo aleatoriamente um deles.

Peter é
fonte
Penso que esta é a resposta que estou procurando, no entanto, ainda está um pouco nublado. Você pode obter um pouco mais de detalhes, em texto ou pseudocódigo, sobre como a última parte da sua explicação funcionaria? "Você pode simplesmente mover-se da esquerda para a direita, fazendo uma lista de quais (poucas) peças podem vir depois da peça anterior e escolhendo aleatoriamente uma delas."
erebel55
1
Para cada tipo de bloco, tenha uma lista de quais blocos são permitidos depois disso - existem tão poucos blocos que podem ser feitos rapidamente manualmente. A 'altura' mudará, preencha tudo abaixo do novo ladrilho com # 10s.
Peteris 17/02
Ah, então você está dizendo para usar esse método em vez do bitmasking?
Erebel55 17/02
1
Sim, a máscara de bits é útil se todo o conteúdo em 2D for significativo, mas seus mapas parecem ser de nível único, uma superfície horizontal de altura variável.
Peteris 17/02
Isso faz sentido, as "montanhas" terão alturas variadas e fluirão uma para a outra. Então, essencialmente, será uma montanha contínua que muda de altura à medida que você avança. É como uma onda cosseno / senoidal que tem magnitudes aleatórias em diferentes pontos. Devo mover da esquerda para a direita ou de cima para baixo ao gerar o mapa?
Erebel55 17/02
6

Você já pensou em usar uma função de ruído 1D Perlin ou simplex? Há várias vantagens nisso, incluindo:

  1. Infinito (dentro do domínio da precisão de ponto flutuante), terreno não repetitivo

  2. Pode ser gerado em tempo real (mesmo em um shader, que é rápido ) ou antecipadamente e armazenado em texturas, como no seu exemplo

  3. As bordas correspondem automaticamente, pois o Perlin e o simplex são contínuos.

  4. Embora o terreno em si seja pseudo-aleatório, é fácil aplicar uma função de envelope ou simplesmente reduzir o número de oitavas em áreas onde você precisa de áreas planas ou outros recursos específicos do terreno.

Veja este link para uma explicação bastante completa da implementação 1D Perlin.

Um envelope é basicamente um campo escalar ou função que é multiplicada pela função de ruído antes de salvar ou exibir sua saída.

insira a descrição da imagem aqui

(Imagem inicial emprestada do artigo acima mencionado.)

Neste exemplo, a linha vermelha representa uma função por partes definida como

x < 0.3 : y = (0.3-x)/0.3)
x < 0.5 : 0
x < 0.7 : (x - 0.5) / 0.2
else    : 1

... que pode ser melhor definido usando uma função suave. Nesse caso, apenas reduz as coisas para 0 antes do platô e depois volta para 1 depois.

Atualizar

Aqui está um exemplo de um "terreno" 3D simplex de um dos meus projetos, com iluminação especular difusa aplicada, gerada inteiramente dentro de um tubo de sombreamento vert + tess + frag. Para sua situação, eu usaria uma fatia vertical para obter a inclinação do terreno.

insira a descrição da imagem aqui

E uma vista ortográfica de cima para baixo:

insira a descrição da imagem aqui

3Dave
fonte
Esta é uma técnica para gerar as próprias imagens de bloco reais?
Erebel55
1
@ erebel55 Sim. Você pode usar uma função 2D para decidir onde (com base no seu exemplo) colocar diferentes filhos de plantas na imagem e também para gerar o terreno inclinado. Eu usei isso em 3D com ótimos resultados.
3Dave
Parece um método interessante, mas não tenho certeza se quero seguir esse caminho, pois já tenho minhas imagens criadas.
erebel55
@ erebel55 sim, não há razão para jogar coisas existentes, se estiver funcionando para você.
3Dave
Bem, eu ainda não tenho a geração aleatória funcionando, mas espero;) Eu dei a você um voto positivo para esse método, pois foi interessante e eu posso usá-lo em algum momento no futuro. Obrigado
erebel55