#003 - The World Loop
Recap
Time to finish this post up. In the last devlog, I started the discussion surrounding the world generation, through talking about the terrain itself, and how the world is built up with sectors. In this post, I'll go over the maintenance of the world that occurs as the player traverses it - that is, how new sectors are loaded and unloaded, the level of detail system, etc. This system is called the "world loop," and follows the following steps:
This chart gives a very basic overview of how the world loop works. You'll note that the tasks undertaken by the alt thread are the ones I went over last time, so I'll mainly be talking about the tasks being undertaken by the main thread in this loop. These tasks require far less explanation, I think.
Create, Build, Delete
When you first click "play" on the main menu, the world is initialized. The first thing that occurs is deciding where the player spawn is going to be, and this is done by plopping the player's position at a certain point and moving them until they're either just below the surface or just above the surface, at which point the player's collision system will self-correct.
The reason this is important to do first is that the player's position ultimately determines where the sectors are going to be - the world generates around the player.
This diagram shows the generation of sectors out from the player's position. Each level forms a cube around the player of individual sectors around the player. The first step checks the available spaces around the player at each level, and if a sector isn't present, creates a new one to fill that space in.
The second step then checks all of the sectors and makes sure one isn't out of place (outside of it's box), which routinely happens when the player moves into a new sector.
This process, of course, needs to happen at every level of detail, but only when the boundaries between those lower levels of detail are crossed, which is less often since those sectors occupy a much larger amount of space (as shown above). As you can imagine, depending on how many sector boundaries the player is crossing at a given time, the process of creating, generating, building (which is just verifying and compiling the sector meshes after they've been generated), and deleting sectors can take a bit of time.
And the most difficult challenge I've had to face in developing Beaconfall is figuring out the correct answer to the question: what happens when the player becomes too fast for it?
Levels Of Detail
To be entirely honest, the answer to that question is simple, at first. Currently, as of 0.1.1, the game measures the player's average speed over 30 frames, and uses that speed to determine at what maximum level of detail the world loop should be. The faster the player is going, the less high the level of detail needs to be. After all, when the player is going that fast, they don't really need to pay attention to all of the little details in the environment as much.
It's the transitions back downward, into higher levels of detail, that are causing problems.
You see, a tradeoff exists between two cases.
In one case, as the player is slowing down and the "maximum" LOD value begins dropping, I could have the engine wait until all of the sectors from that LOD value are loaded in before attempting to render it, in order to prevent those "white gaps" in the terrain from emerging due to the sector there not being fully loaded in yet.
But this causes issues with upward transitions, where the player is getting faster. The player's speed is calculated with an average of the last 30 frames, but that's not enough to prevent a nasty flickering between the two LODs from arising, where the player's speed crosses the boundary back and forth several times a second.
And that's not to mention cases of major axes being crossed, such as the one at the origin (literally 22-ish units away from the player's spawn) where many levels of detail suddenly become "incomplete" and the renderer jumps from rendering level 2 and above to just level 9.
In the other case, where I tell the engine to render the LOD if a certain percentage is ready, then those aforementioned gaps are due to appear in certain places. The higher the percentage, the more likely you are to run into the first issue, and the lower the percentage, the more likely you are to run into the second issue.
In the initial release of this game, 0.1, the terrain LOD system had some nasty issues that I attempted to rectify in the subsequent release of 0.1.1. Routinely, whenever the player would slow down, the entire ground below them would disappear. I leaned way hard into the latter case above since the flickering would be bad enough to hurt my eyes, particularly when it was flickering between nothing (white) and the terrain.
In 0.1.1, I addressed this issue with two changes.
First of all, in 0.1, each "layer" at each level of detail was smaller, only a 3x3x3 grid of sectors. This was a problem, since the render distance for each level is the side length of one sector at that level, meaning when you cross a boundary, even a little one, you'll likely get some gap appearing in your direction, even if it's for less than a second. I could've just lowered the draw distance, but I decided instead to increase the size of each level to 5x5x5.
This gives the renderer a bit more of a cushion to work with, since now the world loop can wait until the player crosses two boundaries at each level before worrying about gaps appearing on the screen. And, as a direct result, I could also reduce the percentage of the sectors required to render an LOD in the first place, since the levels are bigger now.
Having higher sized LODs does unfortunately require more memory, although I did optimize the drawing loop so that only 3x3x3 sectors are rendered at a time per level, but in the future this will probably be a setting that you can change. Speaking of settings, 0.1.2 is right around the corner, and with it comes my first pass on an options menu. It doesn't contain this setting right now, but I figured now was the best time to bring that up.
This solution is still imperfect, although it's definitely far better than where we were in v0.1. In the future, I'm probably going to abandon the system of determining the minimum LOD with the player's speed, and just have it move up or down with the world loop's pace of generation. That's certainly a more portable system, less likely of causing different issues machine-to-machine.
I might put some of these changes in 0.1.2, but they're more likely to go into a future update. Speaking of which...
The Great Canvas
This was a lot of talk for a bunch of samey-looking green fields and hills, wasn't it?
At the end of the day, my biggest goal with the world is to make it look, feel, and sound far more interesting than how it does right now (especially since there's no diagetic sound in the game at the moment). After all, the world itself is the main obstacle between you and the goal, and overcoming that obstacle should be fun and engaging.
Development on this game is still incredibly early, but I'm currently in the process of designing systems which will hopefully make this more of a reality.
One feature I'm going to be attempting to implement relatively soon is actual flora. Trees, mainly. These will no doubt be obstructions to players moving quickly, and will add an additional bit of challenge to moving around. I have other plans for them too, but I doubt I'll get to that when I first add them. I might nerf the wall in the meantime if the added challenge necessitates it.
Another reason for implementing them is to help decide how the hell this game is going to look. Back in Devlog 1, I made a promise that the terrain wouldn't keep it's current flat-color low-poly construction-paper-ass style for too long, and I intend to make good on that promise relatively soon. I've been thinking about a watercolor-esque style for quite some time now, and I'm going to spend the next few weeks trying to pull that off.
You'll likely see the first hints of these changes in the update following 0.1.2 (probably 0.1.3), as I intend to get a new style of grass rendering by then. I don't have much to show visually for it yet, but that update should be coming relatively soon.
That concludes my main discussion about the world loop, and about terrain generation. The systems I've described will likely undergo some major changes over the next few weeks and months, so this will not be the last time I bring either of these subjects up, but for now, this is all. Thanks for reading once again, and stay tuned, as 0.1.2 will be releasing very soon, by next Monday at the latest.
- 0de
Get Beaconfall
Beaconfall
Existential running simulator.
More posts
- v0.1.8 released.Jan 06, 2024
- v0.1.7 released.Dec 31, 2023
- v0.1.6 released.Dec 26, 2023
- #007 - It's Not Coming Out TodayDec 24, 2023
- #006 - Tree TimeDec 13, 2023
- v0.1.5 released.Dec 05, 2023
- v0.1.4 releasedNov 29, 2023
- #005 - Painted HillsNov 28, 2023
- #004 - Everything Is Made of IceNov 20, 2023
Leave a comment
Log in with itch.io to leave a comment.