Comment gérer un Block World comme Minecraft

9

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?

danijar
la source
2
Minecraft charge le monde en cubes assez gros appelés Chunks, pas tous à la fois. Je ne suis pas sûr des détails exacts. La source Minecraft est assez facile à obtenir si vous voulez voir comment cela s'est passé.
ratbum
Jetez un œil au wiki de Minecraft: minecraftwiki.net/wiki/Chunk
Tom Van Green
Je connaissais déjà des morceaux dans Minecraft, mais de toute façon merci.
danijar
Il s'agit d'une question complexe qui ne convient pas à la portée de ce blog.

Réponses:

9

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.

Thomas Marnell
la source
Je vous remercie! Il n'y a rien sur l'IA car j'écris un client pour un MMO. Le calcul des PNJ est effectué par le serveur. Un ajout: le moteur graphique n'a pas besoin de "chaque bloc pas complètement entouré d'autres blocs non transparents". S'il y a des grottes, le joueur ne peut pas voir qu'elles sont sans importance. ;-)
danijar
2
À propos des grottes que le joueur ne peut pas voir ... Je pense qu'il utilise moins de performances pour simplement dessiner les grottes que pour déterminer si la grotte a été complètement bloquée. Et si vous ne dessinez pas de grottes, si vous supprimez un bloc, vous devrez potentiellement générer à nouveau le maillage pour plusieurs morceaux au lieu d'un seul. Ce serait cool de trouver un moyen d'exclure les grottes, je ne peux pas penser à un moyen de le faire efficacement: D.
Thomas Marnell
3

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

Mungoid
la source
3
Marching Cubes consiste à visualiser des voxels. Et Minecraft ne l'utilise même pas; il dessine simplement des cubes, ce qui est exactement ce que Marching Cubes ne veut pas faire.
Nicol Bolas
Merci pour votre explication! Je n'avais jamais entendu parler de Voxels auparavant et cela semble très important pour mon projet. Mais il me reste une question.
danijar
Je comprends la création d'un tableau de morceaux proches où chaque élément contient un tableau des voxels de ce morceau. Mais ensuite, je dois gérer la modification du tableau de blocs lorsque le joueur se déplace dans le monde. Dois-je lire les morceaux nécessaires dans le fichier de sauvegarde? Ou existe-t-il un bon moyen de les garder en mémoire?
danijar
2
@danijar Juste quelques anecdotes, pixel est l'abréviation de "élément d'image", le voxel est formé de la même manière à partir de "l'élément de volume". Ce n'est pas important pour rien, mais comme vous n'aviez pas entendu le terme voxel avant, je pensais que cela pourrait vous intéresser.
Daniel Carlsson
1

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.

Gandalf
la source