Geramos níveis de ladrilhos e ocultamos quadrados do jogador


Geração de nível no inexplorado 2


Estamos muito orgulhosos do gerador de nível de jogo Unexplored 2, este é um programa que atende a todos os requisitos modernos. Em um post, falarei sobre como os níveis de jogo são criados.

Não tivemos que reinventar a roda. No Unexplored 1, já criamos técnicas que influenciaram muito o sucesso do primeiro jogo. O 2 inexplorado apenas continuou o que foi iniciado. A base de nossa tecnologia consiste em duas partes: usamos a geração de vários estágios, que quase simula um processo muito semelhante ao trabalho de um projetista de nível de vida. Além disso, usamos uma técnica chamada " geração de masmorra cíclica ", que é muito melhor para gerar níveis de aparência natural do que a maioria dos aplicativos de criação de conteúdo generativo padrão. Neste post vou falar sobre o primeiro aspecto. A adaptação da geração cíclica de masmorras ao Unexplored 2 será o tópico de um post futuro.

Imitação de design de nível "humano"


O gerador de nível divide o processo de geração de nível em um conjunto inteiro de estágios controlados. Vai do planejamento de alto nível para um mapa de nível detalhado de baixo nível. De fato, ele primeiro cria um esboço do nível e começa a adicionar detalhes até que o nível seja concluído e preenchido.

Em cada estágio individual deste processo, usamos gramáticas generativas para transformar o nível gerado nos estágios anteriores. Em particular, usamos gramáticas de blocos e gramáticas gráficas, que são variedades de gramáticas de string mais gerais que simplesmente pesquisam e substituem partes de strings por outras, como as expressões regulares. Se você não estiver familiarizado com os conceitos de gramáticas generativas e expressões regulares, recomendo que você procure exemplos na Internet (ou apenas continue lendo - você não precisará de conhecimento aprofundado para entender o significado desta publicação).

A primeira etapa do nível é relativamente simples. Usamos um bitmap de baixa resolução para localizar os princípios básicos do nível. No exemplo abaixo, o nível é inicialmente muito simples: consiste apenas na entrada (e) à esquerda, na entrada à direita e na conexão do caminho direto. A maioria das outras peças é indefinida (u) ou bloqueada (B) porque estão nas bordas do nível.


Figura 1: Um esboço simples do nível

Na próxima etapa, são adicionados detalhes: um grupo de salas aparece, conectado por portões, projetados para passar em uma determinada direção:


Figura 2: Estrutura adicionada

Os mapas de blocos são ótimos para criar geometria de nível, mas é mais prático trabalhar com gráficos para gerar estruturas e lógica de jogo. Isto é o que o gerador faz a seguir:


Figura 3: Gráfico base

No gráfico, alguns nós contêm subnós; no nosso caso, a maioria dos portões é marcada como perigosa (H), e alguns são marcados como abertos (O).

Com base em uma análise bastante simples e em regras generativas, novos elementos são adicionados ao gráfico. Por exemplo, o ponto final (G) está localizado em um local distante o suficiente das entradas. Além disso, pequenos perigos são adicionados ao gráfico para tornar o nível mais ameaçador.


Figura 4: Novos itens adicionados ao gráfico.

Enquanto isso, um mapa de blocos de baixa resolução é convertido usando várias funções de ruído em um mapa de blocos de alta resolução para dar uma aparência mais natural:


Figura 5: Mapa de blocos de alta resolução

Em seguida, as informações do gráfico são usadas para decorar o mapa de blocos e adicionar novos elementos:


Figura 6: Placa decorada.

O mapa como é é gerado apenas para apresentação na jogabilidade. Ladrilhos brancos indicam espaços abertos, e quase todos os outros ladrilhos indicam elementos de jogabilidade muito específicos, por exemplo, uma passagem secreta pelos arbustos (círculos verdes), “portões nos matagais” (quadrados verdes e faixas lilás) ou locais de reprodução para amarrar árvores (círculos vermelhos com letra s). A parte principal do nível ainda está indefinida e, neste estágio, o gerador assume que essas áreas devem ser preenchidas para bloquear o movimento do jogador.

Ele executa essa tarefa em várias camadas: a camada inferior indica o nível de altura e tipo de superfície, a segunda adiciona água em determinados locais e a terceira camada adiciona vegetação e outras decorações.


Figura 7: Tipos de superfície terrestre (grama, lama e pedras)


Figura 8: Água


Figura 9: Vegetação e outras decorações

Essas camadas são adicionadas ao arquivo de dados do nível final, ao qual são adicionados mais alguns detalhes. O jogo usa esses dados para colocar ativos e aumentar o nível que você vê. Existem muitos truques nesta fase. Por exemplo, você pode perceber que os ladrilhos de terra na figura acima têm formas estranhas. Esses formulários são usados ​​para criar “blocos” no solo de tal maneira que o player não percebe que os dados de origem eram um mapa de blocos. Vou falar sobre isso na segunda parte do artigo.


Figura 10: Nível Pronto

Adicionando jogabilidade


Há muitos benefícios nesse método de geração de nível. O estágio de conversão de um nível em um gráfico é especialmente importante para simplificar o "raciocínio" sobre a jogabilidade para o gerador. No exemplo mostrado acima, não fizemos nada com isso, exceto para verificar se as metas de nível são criadas a alguma distância das entradas. Mas para outros níveis nesses estágios, mais tarefas são executadas.

Tomemos, por exemplo, um mapa de cavernas em um estilo de masmorra mais clássico (comparado ao nível da floresta do exemplo acima). O gráfico base deste nível possui apenas uma entrada e alguns novos tipos de portão. Um par está fechado (L): alguns portões prendem o jogador de um lado (T) e verde escuro eu chamo de “válvula”: esse tipo de portão permite que o jogador siga apenas uma direção.


Figura 11: Contagem de bases da caverna

A estrutura desse nível permite que o gerador crie uma missão muito mais complexa. Por exemplo, a única maneira de chegar a esse nível é através de uma "válvula", forçando o jogador a procurar outra saída. A chave para abrir a saída (canto inferior esquerdo) está localizada atrás do perigo no canto superior esquerdo, e o alvo está localizado atrás dos portões que prendem o jogador. Um exemplo desse objetivo seria uma passagem que cai atrás de um jogador. Em geral, isso cria uma caverna que é interessante explorar por conta própria, mas o Unexplored 2 também tem a capacidade de adicionar criaturas e eventos que se misturam no tempo de execução.


Figura 12: Fechaduras e chaves adicionadas à caverna

Usando o processo descrito acima, o gráfico é usado para gerar e preencher um mapa de blocos totalmente detalhado. A aplicação de vários parâmetros que refletem a natureza da caverna desse nível leva a resultados muito variados com estruturas subterrâneas destruídas (quadrados azuis marcados com a letra c) e abismos amplos com espigas (círculos lilás):


Figura 13: Nível da caverna em detalhes completos

Resumir


Espero que você tenha uma idéia geral de como abordamos a geração de níveis no Unexplored 2. Esse é um processo complexo de várias etapas, sobre o qual pretendo escrever mais no futuro próximo. Pelo menos eu já prometi escrever sobre a aplicação da geração cíclica de masmorras. Mas você pode contar muito mais, desde técnicas generosas de narrativa, linhas de renderização e métodos de sombreamento até o longo processo de design que usamos para criar o sistema de sorte, além de outros aspectos.

Parte 2. Dos ladrilhos às curvas, ou diversão com as contagens de Voronoi



O gerador de conteúdo inexplorado 2 gera mapas de blocos. Um resultado típico é assim:


Esses cartões de blocos são empilhados um sobre o outro e usam blocos diferentes para indicar os tipos de superfície da terra (neste exemplo, grama ou sujeira), além de várias decorações. Nesse caso, existem vários arbustos (grandes círculos verdes), pedras (círculos pretos), plantas (pequenos círculos verdes), flores (círculos brancos) e texturas decorativas (quadrados cinza). Também existem peças especiais que indicam dados do jogo, por exemplo, pontos de reprodução marcados com a letra "s". Além disso, os ladrilhos podem ser marcados com informações adicionais, por exemplo, nível de altura ou subtipos especiais.

Os mapas lado a lado são uma estrutura de dados conveniente para geradores. Mas, ao mesmo tempo, é bastante direto, e a grade é frequentemente perceptível no jogo. No entanto, depois de carregar os dados no jogo e colocar os ativos, o resultado fica assim:


Acho que escondemos muito bem os azulejos, e foi assim que conseguimos.

Voronoi Magic


O truque é que blocos individuais correspondem a células no diagrama de Voronoi. Este diagrama pode ser usado para gerar formas com aparência muito mais natural. O diagrama de Voronoi é criado semeando o plano com pontos aleatórios e dividindo-o em células de forma que cada ponto no plano pertença à célula correspondente ao ponto inicial mais próximo. Na geração de conteúdo procedural, os diagramas de Voronoi podem ser usados ​​de várias maneiras interessantes.

Um diagrama típico de Voronoi é criado a partir de uma distribuição aleatória, mas bastante uniforme, dos pontos geradores, que se parece com isso:


No Unexplored 2, usamos um tipo diferente de distribuição de pontos geradores. Primeiro, geramos um ponto para cada bloco. Portanto, podemos ter certeza de que cada bloco no mapa de blocos corresponderá a uma célula no diagrama de Voronoi.

Se colocarmos os pontos de geração no meio de cada célula, obteremos uma grade reta que se parece exatamente com um mapa de blocos (para esta e outras imagens abaixo, criei uma versão de xadrez na qual metade dos blocos é renderizada em amarelo para que você possa se sair um pouco melhor veja padrões):



A maneira mais fácil é melhorar o gráfico, simplesmente randomizando a posição de cada ponto de geração. Ao mover pontos, vale a pena verificar se o ponto não vai além do bloco original.

O resultado é algo como isto:



Já é melhor, mas muito barulhento e, portanto, não recebe linhas sinuosas bonitas. A imagem pode ser aprimorada executando o "relaxamento" dos diagramas de Voronoi (essa é uma técnica padrão para eles, que não discutirei aqui). Mas ainda assim permanecerá um pouco barulhento e é difícil prever efetivamente os números em uma escala que excede a escala de blocos individuais.

Para resolver esse problema, precisamos não apenas mover-nos aleatoriamente, mas abordar isso de maneira mais inteligente. Diferentes tipos de movimento podem ter um efeito muito diferente. Por exemplo, ao usar o ruído Perlin, são obtidos cartões de curvas interessantes. Ou você pode transformar toda a grade em blocos hexagonais, movendo simplesmente cada segunda linha dos pontos de geração para a esquerda:



Fizemos um grande avanço quando começamos a mover os pontos geradores em certos padrões para criar cantos arredondados. A primeira etapa deste processo já está sendo realizada dentro do gerador de níveis. Os ângulos entre os diferentes tipos de superfície da Terra são reconhecidos e os ladrilhos dos cantos são marcados com figuras diferentes, indicando a forma como eles são deformados para gerar um ambiente mais bonito:


Nesse caso, a diferença nos níveis de elevação também faz com que os ângulos apareçam no mapa de blocos. É por isso que você vê cantos arredondados adicionais na grama, no canto superior direito e no canto inferior esquerdo, onde as inclinações foram geradas.

O jogo usa essas informações para mudar os pontos de geração do gráfico Voronoi. Cada canto arredondado muda a localização do ponto de origem (veja a imagem abaixo). Além disso, também muda os pontos geradores de seus quatro vizinhos ortogonais. Esse processo é cumulativo; os pontos geradores podem se mover várias vezes se estiverem próximos de vários ângulos. No entanto, após o processamento de todas as compensações, os pontos de geração são um pouco aleatórios (cerca de 10% da largura do ladrilho em cada direção) e o deslocamento final é limitado a um máximo de 40% da largura do ladrilho.


O resultado já está ficando de alta qualidade:



Mas ainda não terminamos ...

Decore sabiamente


A forma geral ficou melhor, mas as bordas ainda são muito retas e parecem meio irregulares. Esconderemos isso colocando ativos curvos nas bordas onde as cores diferem. No entanto, o verdadeiro truque é que uma curva é frequentemente colocada em duas arestas e seus ângulos entre si são usados ​​para determinar a direção da curva.


O resultado fica assim:


Em seguida, usamos recursos 3D para adicionar recortes de textura:


Por fim, adicionamos outro ativo para preencher o nível. A localização desses ativos é determinada pelos dados de nível gerados anteriormente e, em geral, segue princípios simples. Usamos pequenos ativos ao redor dos maiores para criar transições naturais e bonitas. Em particular, vale a pena notar que pedras são adicionadas ao pé das falésias, criando variabilidade e suavizando visualmente as encostas verticais necessárias para a jogabilidade:


Variabilidade local


Os ângulos não são o único tipo de deslocamento que usamos. Em particular, queremos que as arestas sejam mais retas ao lado das estruturas artificiais (por exemplo, as paredes destruídas mostradas abaixo):


Em nosso sistema, esse efeito é fácil de obter. Simplesmente adicionamos outra regra de deslocamento, que proíbe o deslocamento de ladrilhos com estruturas artificiais. O gerador usa pequenos quadrados para marcar essas peças e o jogo garante que todas as compensações sejam simplesmente ignoradas:



Se você olhar para o chão, poderá ver claramente que certas áreas são retas, enquanto outras se curvam mais naturalmente:


Não é lindo?

Existem outras regras que podem ser facilmente adicionadas usando essa técnica. Por exemplo, às vezes forçamos os ladrilhos para criar um padrão hexagonal, de modo que os caminhos estreitos permaneçam largos o suficiente para se moverem ao redor deles. Estou certo de que encontraremos outros usos para outros padrões.

Essa é uma das muitas razões pelas quais eu amo os diagramas de Voronoi. Em outra ocasião, escreverei sobre como os usamos para gerar e decorar os mapas do mundo Unexplored 2.

Source: https://habr.com/ru/post/pt457766/


All Articles