Como lidar com um mundo de blocos como o Minecraft

9

Eu quero escrever um jogo simples com um mundo de blocos como no Minecraft. Minha pergunta teórica é qual é a melhor maneira de lidar com as informações deste bloco durante o jogo. Minha primeira idéia foi uma variedade enorme, mas isso causará falta de memória, eu acho. Talvez eu tenha que carregar apenas os blocos perto do player.

Como posso lidar com o carregamento das informações de bloco necessárias de um arquivo e a retenção apenas das necessárias na memória?

danijar
fonte
2
O Minecraft carrega o mundo em cubos bastante grandes chamados Chunks, não todos de uma vez. Não tenho certeza dos detalhes exatos. A fonte do Minecraft é muito fácil de encontrar, se você quiser dar uma olhada em como isso aconteceu.
Rat24,
Dê uma olhada no minecraft wiki: minecraftwiki.net/wiki/Chunk
tom van green
Eu já sabia sobre pedaços no Minecraft, mas de qualquer maneira obrigado.
31512 danijar
Essa é uma pergunta complexa, não apropriada para o escopo deste blog.

Respostas:

9

Existem algumas maneiras diferentes de armazenar os dados para um jogo com blocos como o Minecraft.

A maneira como eu acredito que o Minecraft faz isso é dividir o mundo nos pedaços 16x16x256. Os pedaços ao redor do jogador são carregados na memória quando o jogador inicia o jogo; em seguida, um thread em segundo plano é carregado mais à medida que você caminha. Aqui está um vídeo que mostra: http://www.youtube.com/watch?v=oR_ZdJH9eho .

Outra maneira de fazer isso é dividir o mundo em um Octree. Michael Goodfellow escreveu um blog sobre a implementação de um mundo de cubos com essa estrutura de dados: http://www.sea-of-memes.com/LetsCode1/LetsCode1.html . O Octree é bom porque oferece compactação embutida, mas provavelmente será um pouco mais difícil trabalhar com um Array.

Sobre manter os "únicos necessários na memória"? Isso é um pouco mais difícil, pois você precisa perguntar o que é "necessário". Se você tem NPCs que vivem em outra parte do mundo com IA que interage com o ambiente, então "precisa" muito mais do mundo para estar na memória. Os dados mundiais da Voxel podem ficar muito grandes muito rapidamente, por isso é melhor tentar manter a menor quantidade possível de memória. (IE, só tem NPCs perto do jogador).

O mecanismo gráfico "precisará" de todos os blocos não completamente cercados por outros blocos não transparentes. A maneira usual de renderizar o mundo é construir uma única malha que contenha os vértices para cada bloco visível. É muito mais rápido desenhar, pois você está fazendo apenas uma chamada para os métodos de desenho para 65.536 blocos (em pedaços de tamanho do Minecraft). Como o mecanismo gráfico precisará criar essa malha, ele geralmente precisa conhecer todos os cubos em um pedaço. Observe que é por isso que, quando você vê no Minecraft, grande parte do mundo é invisível. Isso ocorre porque todo bloco cercado nos seis lados é ignorado. Acredito que o Minecraft também reduz o número de vértices combinando lados horizontais do mesmo tipo de textura em uma caixa com a textura repetindo.

Meu conselho seria ir com os pedaços de 16x16x256. Armazene-os em uma matriz, pois você precisará de iteração e edição rápidas devido à construção da malha e da lógica do jogo (detecção de colisão, adição / remoção de blocos, ect). Em seguida, carregue o maior número possível de pedaços em círculo ao redor do player. Escale o número de pedaços para cima ou para baixo para computadores melhores ou piores.

O carregamento de Chunks será um enorme impacto no desempenho, portanto, coloque-o em um encadeamento que o executa com o tempo. Faça com que você possa carregar completamente três novos Chunks durante o tempo que o jogador percorrer de uma extremidade a outra.

Thomas Marnell
fonte
Obrigado! Não há nada sobre IA porque estou escrevendo um cliente para um MMO. O cálculo de NPCs é feito pelo servidor. Uma adição: nem "todo bloco não completamente cercado por outros blocos não transparentes" é necessário pelo mecanismo gráfico. Se houver cavernas, o jogador não poderá ver que não tem importância. ;-)
danijar
2
Sobre cavernas que o jogador não pode ver ... Acho que ele usa menos desempenho para desenhar as cavernas do que para determinar se a caverna foi completamente bloqueada. E se você não desenhar cavernas, se você remover um bloco, poderá gerar novamente a malha para vários pedaços em vez de apenas um. Seria legal encontrar uma maneira de excluir cavernas, simplesmente não consigo pensar em uma maneira de fazê-lo com eficiência: D.
Thomas Marnell 30/07/2012
3

Talvez eu não tenha a melhor maneira de explicar isso, mas vou tentar.

Eu acho que a melhor maneira de entender como torná-lo mais eficiente é entender os Voxels. O Minecraft é baseado em voxel, apenas usa cubos em vez de esferas, etc., etc.

Basicamente, um voxel é uma forma 3D que pode ter um volume alterado dinamicamente e, quando o volume muda, o mesmo ocorre com a forma. Um pedaço é um conjunto de voxels X por X por X. Por exemplo, você pode ter um pedaço com voxels de 16x16x16 e, em seguida, pode ter um número X de pedaços. Você terá uma distância definida, que, se o jogador estiver mais longe do que N dos pedaços, não os inclua em seus cálculos. Isso é semelhante às distâncias de recorte, mas precisaria se aplicar a cada parte também. Dessa forma, você pode tê-lo para que você possa sempre ter o seu jogador no Chunk central de um, por exemplo, um conjunto de Chunks 3x3.

Então, o que você teria é uma classe para lidar com os Voxels individuais. Vamos chamá-lo de Voxel_cl. E então você teria uma classe para lidar com a parte dos voxels, chamada Chunk_cl. E então você teria uma classe mundial que gera todos os pedaços que gerariam os voxels, chamados World_cl.

Portanto, agora, em vez de uma enorme variedade de tudo, você teria uma variedade de 9 Chunks a qualquer momento e, na classe chunk, teria uma matriz de 4096 voxels.

Observe que esta é uma explicação bastante simples. Atualmente, estou trabalhando em algo usando voxels, então pensei em incluir minha entrada = -)

Para mais informações sobre voxels, consulte http://en.wikipedia.org/wiki/Marching_cubes

Mungoid
fonte
3
Marching Cubes é sobre a visualização de voxels. E o Minecraft nem o usa; apenas desenha cubos, o que é exatamente o que a Marching Cubes não faz.
Nicol Bolas
Obrigado pela sua explicação! Eu nunca ouvi falar de Voxels antes e parece muito importante para o meu projeto. Mas eu tenho uma pergunta agora.
31712 danijar
Eu entendo a criação de uma matriz de pedaços próximos, onde cada elemento contém uma matriz dos voxels desse pedaço. Mas então eu preciso lidar com a mudança da matriz de partes quando o jogador se move pelo mundo. Preciso ler os pedaços necessários do arquivo salvo? Ou existe uma boa maneira de mantê-los na memória?
31712 danijar
2
@danijar Apenas algumas curiosidades, pixel é a abreviação de "elemento de imagem", voxel é formado da mesma maneira a partir de "elemento de volume". Não que isso importe para nada, mas desde que você não tinha ouvido o termo voxel antes, pensei que lhe poderia interessar.
Daniel Carlsson
1

Você pode tentar apenas renderizar as superfícies visíveis, o computador lida com os dados do bloco em segundo plano, enquanto o renderizador trabalha apenas com o que vê. Pedaços 8x8 seriam mais fáceis de manusear.

Gandalf
fonte