Feeling good enough to do some design today!
As you saw in the video, the game world was limited to just what was on the screen, and anything that left that area would immediately be destroyed. That isn’t how things should be. Instead, the world should technically be able to go in all 4 directions infinitely. I still want to have worlds that wrap around, so I’ll take care of that as well.
One method I’ve seen to provide that “infinite” feel is to divide the world into loadable chunks. The idea behind this is fairly simple: For any chunk of the world that hasn’t yet been seen, it should be generated by the in-game chunk generator. For any chunk of the world that HAS been seen, load it from disk.
If we had an infinite amount of ram, then we would be able to keep every chunk in a great big array. I’m developing and playing my game on what would be considered a low-end machine, and that means my resources are limited. I need to build around those limitations. I suspect that even the highest-end machines don’t have infinite ram either.
Since ram is limited, I have to consider a way that will use a limited amount of ram but still have it seem like the world is endless. In order to do this, I only want a certain number of chunks around the player to be active at any given time. When the player has moved in such a way as to make any chunks inactive (they’re out of the player’s view radius) then they are saved to disk and unloaded. At the same time, when the player should be able to see new chunks, they either have to be created (not yet seen the chunk) or loaded from disk (have seen and has already been saved).
When and how to create/load and unload
I’m going to divide the world into even-sized box shapes, each frame I can check to see if the player is in a different chunk than he was in the last frame. If so, we would move all chunks that are now outside of the new viewable area into a “cleanup chunks” list, and then add new empty chunks to a “new chunks” list.
Each frame afterward, we would save one chunk from the “cleanup chunks” list, and load or create one chunk in the “new chunks” list.
When the game is quit, all active chunks would be saved to file before we exit.
Dealing with wraparound
I like the idea of an infinite amount of play space, but it really isn’t needed. I have tried to go to The End Of The World in Minecraft, and I gave up long before I got close. There’s just no need to have that much space. I’m not going to be doing that.
An entire world will be a large rectangular map. Right now, I’m generating chaotically random worlds – there’s no rhyme or reason to the placement of anything, Anywhere Is Fine. I don’t have to deal with the placement of things yet, but I do have to deal with world wraparound. Since the world has a set size, chunks at X= 0 and 255 will share an edge, and objects will have to be able to see each other from one side to the other.
I plan on setting it up so that when the player reaches the new chunk, he will be suspended in space and the chunk under him will be replaced with the one that he’s moving into, and then he’ll be shoved back the entire width of the chunk. This will keep him in the 0..chunk_width play space – and he will never actually leave it. When he has “left” it, everything moves in such a way as to keep him within it. Chunks at the world’s edge are treated as a relatively positioned chunk, the same way as non-bordered chunks are. This saves me the trouble of having to deal with tricky math at the seams, since everything is positioned relative to the player rather than in absolute world coordinates.
Looking forward, I’m going to eventually be restricting placement of resources to a grid, and afterward I’ll be making the world into a 2d blockmap. Once these systems are in place, I’ll be once again looking at libnoise to generate ‘pretty’ worlds, and I’ll have to deal with world-edge seams. I’ll deal with that when I get there.
It seems pretty straightforward now that I’ve written it all out. After a break, I’m gonna get started on the code.