Je veux écrire un jeu simple avec un monde de blocs comme dans Minecraft. Ma question théorique est quelle est la meilleure façon de gérer ces informations de bloc pendant la lecture. Ma première idée était un énorme tableau, mais cela entraînera un manque de mémoire, je pense. Peut-être que je n'ai qu'à charger les blocs près du lecteur.
Comment puis-je gérer le chargement des informations de bloc nécessaires à partir d'un fichier et la conservation uniquement de celles nécessaires en mémoire?
c++
voxels
minecraft-modding
data
danijar
la source
la source
Réponses:
Il existe plusieurs façons de stocker les données d'un jeu avec des blocs comme Minecraft.
La façon dont je crois que Minecraft le fait est de diviser le monde en morceaux de 16x16x256. Les morceaux autour du joueur sont chargés en mémoire lorsque le joueur démarre le jeu, puis un fil d'arrière-plan se charge plus pendant que vous vous promenez. Voici une vidéo qui le montre: http://www.youtube.com/watch?v=oR_ZdJH9eho .
Une autre façon de le faire est de diviser le monde en octree. Michael Goodfellow a écrit un blog sur l'implémentation d'un monde de cube avec cette structure de données: http://www.sea-of-memes.com/LetsCode1/LetsCode1.html . L'Octree est agréable car il vous donne une compression intégrée, mais il sera probablement un peu plus difficile de travailler avec un tableau.
A propos de garder les "seuls nécessaires en mémoire?" C'est un peu plus difficile car il faut se demander ce qui est "nécessaire". Si vous avez des PNJ qui vivent dans une autre partie du monde avec une IA qui interagit avec l'environnement, alors vous "avez besoin" de beaucoup plus de monde pour être en mémoire. Les données du monde Voxel peuvent devenir très volumineuses très rapidement, il est donc préférable d'essayer de garder le moins de mémoire possible. (IE, seuls les PNJ sont proches du joueur).
Le moteur graphique "aura besoin" de chaque bloc pas complètement entouré par d'autres blocs non transparents. La façon habituelle de rendre le monde est de construire un maillage unique qui contient les sommets de chaque bloc visible. C'est beaucoup plus rapide à dessiner car vous ne faites qu'un seul appel aux méthodes de dessin pour 65 536 blocs (en morceaux de taille Minecraft). Étant donné que le moteur graphique devra construire ce maillage, il doit généralement connaître tous les cubes d'un bloc. Notez que c'est pourquoi lorsque vous voyez à travers le sol dans Minecraft, une grande partie du monde est invisible. C'est parce que chaque bloc qui est entouré sur les six côtés est ignoré. Je crois que Minecraft réduit également le nombre de sommets en combinant les côtés horizontaux du même type de texture dans une seule boîte avec la répétition de la texture.
Mon conseil serait d'aller avec les morceaux 16x16x256. Stockez-les dans un tableau car vous aurez besoin d'une itération et d'une édition rapides en raison de la construction du maillage et de la logique du jeu (détection de collision, ajout / suppression de blocs, etc.). Chargez ensuite autant de morceaux que possible dans un cercle autour du lecteur. Augmentez ou diminuez le nombre de blocs pour des ordinateurs meilleurs ou pires.
Le chargement des morceaux sera un énorme coup sur les performances, alors mettez-le dans un thread qui l'exécute au fil du temps. Faites en sorte que vous puissiez charger complètement 3 nouveaux morceaux pendant le temps qu'il faut à un joueur pour marcher d'un bout à l'autre d'un morceau.
la source
Je n'ai peut-être pas la meilleure façon de l'expliquer, mais je vais essayer.
Je pense que la meilleure façon de comprendre comment le rendre plus efficace est de comprendre Voxels. Minecraft est basé sur le voxel, il utilise simplement des cubes au lieu de sphères, etc., etc.
Fondamentalement, un voxel est une forme 3D qui peut avoir un volume modifié dynamiquement et lorsque le volume change, la forme aussi. Un morceau est un ensemble de voxels X par X par X. Ainsi, par exemple, vous pouvez avoir un bloc qui a des voxels 16x16x16 et ensuite vous pouvez avoir un nombre X de morceaux. Vous aurez une distance définie, que si le joueur est plus loin que N de tout morceau, ne les incluez pas dans vos calculs. Ceci est un peu similaire aux distances de découpage mais devrait également s'appliquer à chaque morceau. De cette façon, vous pouvez l'avoir afin que vous puissiez toujours avoir votre joueur dans le bloc central d'un, disons, un ensemble de 3x3 morceaux.
Donc, ce que vous auriez, c'est une classe pour gérer les Voxels individuels. Nous l'appellerons Voxel_cl. Et puis vous auriez une classe pour gérer le bloc de voxels, appelée Chunk_cl. Et puis vous auriez une classe mondiale qui génère tous les morceaux qui généreraient les voxels, appelés World_cl.
Alors maintenant, au lieu d'un énorme tableau de tout, vous auriez un tableau de 9 morceaux à tout moment et dans la classe des morceaux, vous auriez un tableau de 4096 voxels.
Veuillez noter qu'il s'agit d'une explication assez simple. Je travaille actuellement sur quelque chose en utilisant des voxels, donc je me suis dit que je mettrais mon entrée = -)
Pour plus d'informations sur les voxels, consultez http://en.wikipedia.org/wiki/Marching_cubes
la source
Vous pouvez essayer de simplement rendre les surfaces visibles, l'ordinateur gère les données de bloc en arrière-plan, tandis que le rendu fonctionne uniquement avec ce que vous voyez. Des morceaux 8x8 seraient plus faciles à manipuler.
la source