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?
c++
voxels
minecraft-modding
data
danijar
fonte
fonte
Respostas:
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.
fonte
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
fonte
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.
fonte