8
\$\begingroup\$

I want to write a simple game with a block world like in Minecraft. My theoretical question is what is the best way to handle this block informations during playing. My first Idea was a huge array but this will cause running out of memory I think. Maybe I have to only load the blocks near the player.

How can I handle the loading of needed block informations from a file and the holding only of needed ones in memory?

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Minecraft loads the world in fairly large cubes called Chunks, not all at once. I'm not sure of the exact details. The Minecraft source is pretty easy to get hold of if you want to have a look at how that's gone. \$\endgroup\$
    – ratbum
    Commented Jul 24, 2012 at 10:27
  • \$\begingroup\$ Take a look at the minecraft wiki: minecraftwiki.net/wiki/Chunk \$\endgroup\$ Commented Jul 24, 2012 at 10:52
  • \$\begingroup\$ I already knew about chunks in Minecraft, but anyway thanks. \$\endgroup\$
    – danijar
    Commented Jul 28, 2012 at 12:17
  • \$\begingroup\$ This is a complex question not appropriate for the scope of this blog. \$\endgroup\$
    – user27536
    Commented Mar 18, 2013 at 1:04

3 Answers 3

8
\$\begingroup\$

There are a couple different ways to store the data for a game with blocks like Minecraft.

The way I believe Minecraft does it is breaks the world up in the 16x16x256 Chunks. The chunks around the player are loaded into memory when the player starts the game, then a background thread loads more as you walk around. Here is a video that shows it: http://www.youtube.com/watch?v=oR_ZdJH9eho.

Another way to do it is to break the world up into an Octree. Michael Goodfellow wrote a blog about implementing a cube world with this data structure: http://www.sea-of-memes.com/LetsCode1/LetsCode1.html. The Octree is nice because it gives you some built in compression, but it will probably be a little harder to work with then an Array.

About keeping the "only needed ones in memory?" This is a little harder since you have to ask what is "needed". If you have NPCs that live in another part of the world with AI that interacts with the environment then you "need" a lot more of the world to be in memory. Voxel world data can get very large very fast, so it is best to try to keep the least possible amount in memory. (IE, only have NPCs near the player).

The graphics engine will "need" every block not completely surrounded by other non-transparent blocks. The usual way to render the world is to build a single mesh that contains the vertices for every visible block. This is much faster to draw since you are only making 1 call to the draw methods for 65,536 blocks (in Minecraft size chunks). Since the graphics engine will need to build this mesh, it generally needs to know all the cubes in a chunk. Note that this is why when you see through the floor in Minecraft, a lot of the world is invisible. This is because every block that is surrounded on all six sides is skipped. I believe Minecraft also reduces the number of vertices by combining horizontal sides of the same kind of texture into one box with the texture repeating.

My advice would be to go with the 16x16x256 chunks. Store them in an Array since you will need fast iteration and editing due to building the mesh and game logic (collision detection, adding/removing blocks, ect). Then load as many chunks in a circle around the player as you can. Scale the number of chunks up or down for better or worse computers.

The loading of Chunks will be a huge hit on performance, so put it in a thread that runs it over time. Make it so you can completely load 3 new Chunks during the time it takes a player to walk from one end of a chunk to the other.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you! There is nothing about AI because I am writing a client for an MMO. Calculating NPCs is done by the server. One addition: Not "every block not completely surrounded by other non-transparent blocks" is needed by the graphics engine. If there are caves the player can't see they are unimportant. ;-) \$\endgroup\$
    – danijar
    Commented Jul 28, 2012 at 12:31
  • 2
    \$\begingroup\$ About caves that the player can't see... I think it uses less performance to just draw the caves than to determine if the cave was completely blocked off. And if you don't draw caves then if you removed a block you would potentially have to re generate the mesh for multiple chunks instead of just one. It would be cool to find a way to exclude caves, I just can't think of a way to do it efficiently :D. \$\endgroup\$ Commented Jul 30, 2012 at 19:58
2
\$\begingroup\$

I may not have the best way of explaining it but I will try.

I think the best way to understand how to make it more efficient is to understand Voxels. Minecraft is voxel based, it just uses cubes instead of spheres, etc, etc.

Basically a voxel is a 3D shape that can have a dynamically changed volume and when the volume changes, so does the shape. A Chunk is an X by X by X set of voxels. So for example, you can have a chunk that has 16x16x16 voxels and then you can have X number of chunks. You will have a distance set, that if the player is further than N away from any chunks, don't include them in your calculations. This is kinda similar to clipping distances but would need to apply to each chunk as well. This way, you can have it so that you can always have your player in the center Chunk of a, say, 3x3 set of Chunks.

So what you would have is a class to handle the individual Voxels. We will call it Voxel_cl. And then you would have a class to handle the chunk of voxels, called Chunk_cl. And then you would have some world class that generates all the chunks that would generate the voxels, called World_cl.

So now instead of a huge array of everything, you would have an array of 9 Chunks at any time and in the chunk class, you would have an array of 4096 voxels.

Please note that this is a pretty simple explanation. I am currently working on something using voxels so I figured I would throw in my input =-)

For some more info on voxels, check http://en.wikipedia.org/wiki/Marching_cubes

\$\endgroup\$
4
  • 3
    \$\begingroup\$ Marching Cubes is about visualizing voxels. And Minecraft doesn't even use it; it just draws cubes, which is exactly what Marching Cubes is about not doing. \$\endgroup\$ Commented Jul 24, 2012 at 23:05
  • \$\begingroup\$ Thanks for your explanation! I never heard of Voxels before and it seems very important for my project. But I have a question left now. \$\endgroup\$
    – danijar
    Commented Jul 28, 2012 at 12:22
  • \$\begingroup\$ I understand creating a array of near chunks where each element contains an array of the voxels of this chunk. But then I need to handle changing the chunk array when the player moves around in the world. Do I have to read the needed chunks from the save file? Or is there a good way to keep them in memory? \$\endgroup\$
    – danijar
    Commented Jul 28, 2012 at 12:25
  • 2
    \$\begingroup\$ @danijar Just some trivia, pixel is short for "picture element", voxel is formed in the same way from "volume element". Not that it matters for anything, but since you hadn't heard the term voxel before I thought it might be of some interest to you. \$\endgroup\$ Commented Feb 14, 2015 at 12:41
1
\$\begingroup\$

You could try to just make visible surfaces render, the computer handles block data in the background, while the renderer only works with what you see. 8x8 chunks would be easier for it to handle.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .