1
\$\begingroup\$

I am trying to replicate a chunk loading system, in C, for my own minecraft like game, though I don't know how. Once chunks are loaded, are they placed in an array, or are there a bunch of variables for each loaded chunk?
In my game, once I load chunks using fread, what should I use to store them? My problem for a two dimensional array for storing chunks, is that the loaded chunks might be separate and not start at zero. Are there any suggestions for storing loaded chunks?

I have a code fragment, solely so you guys will not yell at me for not including code:

    char ChunkFilePath[strlen(CurrentWorld)+32];
    sprintf(ChunkFilePath, "%s/ChunkData/%ld %ld", CurrentWorld, X, Z);
    FILE *ChunkFile;
    if ((ChunkFile = fopen(ChunkFilePath, "r"))) {
        //chunk file exists, Read Chunk file to ???
    }
    if ((ChunkFile = fopen(ChunkFilePath, "w")) == NULL) {
        fputs("Error Loading Chunk (File Not Found)", stderr);
        return;
    }
        /*Chunk does not exist, but any other errors would have been caught 
        at this point, so Generate chunk, write generated results to ???*/

Note: The game I am trying to make is purely for my personal use, not for any commercial use.

Edit:

The problem is just an array will not work. Suppose there is a player at 1000000 and another one at -1000000 They would only render 6 chunks around them, but if they shared an array, all the 2000000 blocks worth of chunks that aren't loaded would be taking up memory. I would refer to chunks like LoadedChunk[1000]. How can I handle that?

\$\endgroup\$
5
  • \$\begingroup\$ A struct? How is your data structured? What have you tried so far? Did you generate chunks yourself? \$\endgroup\$ – Ocelot Jul 16 '19 at 20:05
  • \$\begingroup\$ @Ocelot What do you mean \$\endgroup\$ – user124120 Jul 16 '19 at 20:07
  • 1
    \$\begingroup\$ There is not enough context provided so question makes no sense to me. Code is irrelevant and there is almost no information related to the structure of chunks and their layout rules. What does "loaded chunks might be seperate and not start at zero" even mean? \$\endgroup\$ – Ocelot Jul 16 '19 at 20:22
  • \$\begingroup\$ @Ocelot Each chunk would be a 3 dimensional array of blocks, and what that means is if I store chunks as a 2 dimensional array of 3 dimentional arrays, I cannot guarantee that all chunks will be together, and of the player is far from chunk 0, 0, the 2 dimensional array would not start at 0. \$\endgroup\$ – user124120 Jul 16 '19 at 20:28
  • \$\begingroup\$ So your chunk layout is a 2D grid. What stops you from moving chunks around in the array? You know how to use pointers, right? Make an array of pointers of your chunks, so you can move them around in the array. Then you would be able to displace chunks in the grid in a way that the chunk player is standing on will be the chunk in the center of the grid and then you would be able to load additional chunks at the the edges of the grid when needed. \$\endgroup\$ – Ocelot Jul 16 '19 at 20:43
6
\$\begingroup\$

If you don't want a 2d array of chunks indexed by world position because the player might get very far away from the world origin or you might have negative indexes, then it might be worth to look at other data structures.

  • A hash table with the coordinates as keys
  • A 2-d tree which you auto-balance so that the root is always at the player (can also be useful for render order determination, collision detection and many other purposes)
  • A 2d array of pointers to chunks, where the indices are not relative to the world origin but relative to the player position. If the player moves to a different chunk, you need to shift that array so that the center point of the array is again the chunk the player is in (which doesn't mean that you rebuild the chunks, just that you move the pointers to chunks in the 2d array).
  • A graph where each chunk has pointers to its four neighbors (as suggested by PSquall in the comments).
\$\endgroup\$
8
  • \$\begingroup\$ Another useful strategy is to use a modulo operator (or bitmasking for power-of-two sizes) to convert the chunk's world position into its position in the loaded array. This effectively makes your loaded cache a torus, with a contiguous square of loaded chunks centered on the player roaming & wrapping around that torus. \$\endgroup\$ – DMGregory Jul 17 '19 at 11:48
  • \$\begingroup\$ Also, in C you need to determine the array length. The render distance might vary, so how can I handle that? \$\endgroup\$ – user124120 Jul 17 '19 at 15:14
  • \$\begingroup\$ @JulianTiemann If you only know the size of an array at runtime, then you can allocate it at runtime using malloc(sizeInBytes). If you want to resize an array at runtime, you can use realloc. \$\endgroup\$ – Philipp Jul 17 '19 at 15:24
  • 1
    \$\begingroup\$ In addition to the 2d-tree, you could go for a modified 4d tree. The root is the current chunk, the leaves are the 4 adjacent chunks and every leaves has the 4 adjacent chunks as his childen leaves. Changing chunks would mean to make one of the 1st level leaves the root and its missing leaf becomes the old root. When N is your view distance in chunks, this tree would have a depht of N (better N+1 because of the corner chunks). \$\endgroup\$ – PSquall Jul 17 '19 at 16:11
  • 1
    \$\begingroup\$ @psquall that's not a tree and certainly no 4-dimensional one. I would call that a 2d double-linked list or a matrix-shaped graph. \$\endgroup\$ – Philipp Jul 17 '19 at 16:53
0
\$\begingroup\$

I'd bridge to C++ and use a std::map() and abstract away the process of accessing these voxels, so they can be called by C

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy