Next: | Graph Rewrite: May 2022 |
Previous: | Re-re-refactor: March 2022 |
I kicked April off with adding a ton of crash prevention code. The reason I avoid this for so long is so I immediately know when the game crashes. Instead of fixing the crash, I work on fixing the cause of the crash. This is helpful, for example, because I could have used the wrong key when accessing a hash table. Or maybe I forgot to fill out the variable. I want to fix these issues before preventing the game from crashing (for legitimate reasons). The second step is to handle cases where it's possible that the variable could be NULL, which is what focused on today (April 1st). At this point, I wrapped up the first iteration of road output code, so most (legal) combination of roads could be placed/connected.
The rest of the week was dedicated to finishing up the lane connections and edge node output, and allowing road extensions (thus deleting the nodes left in the middle of the extension and recreating the edges).
By the second week of April, I had a huge list of road placement bugs to go through, which stayed the same size for awhile even as I was squashing bug after bug. I should mention, when I say something is "done", I don't actually mean that. I'm just reference my logs from November - May. It just means a subset of the problem space has been completed. The next step in the road placement was to allow mixed tile size intersections (e.g. a 2x2 edge and three 1x1 edges in a four way intersection).
Another chunk of my time was again dedicated to refactoring the code base. I attempted to organize and partially automate some of the road graphics output (remember, I started with hard coding every possible solution).
By mid April, all possible intersection combinations have been implemented into the game. This was followed up by lots of path finding bug fixes to work with the newer road network. I also added some debug road output (basically just massive grids) so I can begin to test the path finding code at scale.
Another huge step forward was implementing pregenerated tile atlases. I haven't mentioned this yet, but SFML's built in zoom is AWEFUL. If you zoom out and pan around the map, pixels will pop in and out of existence, causing the screen to flicker. Imagine the road paint lines disappearing and reappearing. Since there is no documented way to fix or work around this issue, I had to take the last option and create a tile atlas for each zoom level. This means when zoom is at 1.00, I use the 32 x 32 tile set (for roads/grass/etc) and 16 x 16 tile set (for rooms/units/objects/...). When I zoom out (in square root of 2 increments) one level, the game engine needs to load the 24 x 24 and 12 x 12 tile sets. Zooming out again loads the 16 x 16 and 8 x 8 tile sets... and so on until we hit the 2 x 2 and 1 x 1 tile sets. I created a script to resize and output the tile atlases for each zoom level, and then I adjust the smaller sprites as needed.
The benefit to this is that I can modify the graphics at each zoom level (e.g. saturation, or I could change the some building graphics to icons when zoomed out far enough). The downside is this will briefly stall the game in between zooms. I temporarily fixed this issue by outputting larger base level sprites (e.g. 10 x 10 tiles of grass as one sprite, which I generate on game load). However, once the map is filled up with user placed tiles, this issue will rear its ugly head again. I intend to solve this by either only loading the graphics in chunks, and/or using multi-threading to load the graphics concurrently. On my machine, it's only an issue around one million tiles or more.
Another huge mile stone was reimplementing path finding preferences (as shown in my YouTube videos). This means among all the shortest paths available between two points, the unit will take the path that matches their preference (whether it be for beauty, history, tourism, commercial area, etc). I also played around with different hash tables for my path finding code. C++'s std::unordered_map is quite a resource hog. I tried phmap's and robin_hood's hash table implementations and they both crushed std::unordered_map. In another blog post, I'll talk about this more.
This month was also my first attempt at making media. I've never done something that exhausted me so quickly. Definitely not my thing, but it must be done. So I did it.
Published Date: 06/25/2022
Total Development Time: 5 months