Much to report! The last few days have been fruitful – now we have a minimap, stars, a better sky gradient, textured ground, and some optimization.
Minimap:
The minimap is a simple but effective — it is actually a scaled down version of the map picture from the previous post, with a little box that shows the current location. It really helps show the scale of the world while you are flying around in it.
Stars:
The stars were taken almost straight from MUA Space, a demo game for the framework. They are randomly placed in the sky tiles, with more stars per tile the higher it goes, until the top (black) tiles are quite ‘starry’. The stars vary slightly in size and twinkle. Simple, but nice.
Ground Texture:
Next, I replaced the old placeholder ground code that made that boring brown texture. Now, the generated terrain becomes an alpha image used as a mask with the underground image to texture the tile. It works really well and the entire operation only takes about .01 seconds. I botched the ground texture itself — it doesn’t exactly wrap right, but otherwise you can see it working nicely here.
Optimization:
This was a big one. After adding the new things, particularly the texturing, the on-the-fly generation of tiles I was doing was causing tiny little blips in the FPS. It wasn’t much, but it WAS noticeable. I have a pretty good machine, so I knew I needed to iron this out. I cut out ugly parts of code where I could, but the operations themselves are pretty heavy (terrain generation, texturing, converting from PIL images to Pyglet textures), so I needed to take it a step further. Two steps actually – I approached the optimization in 2 ways.
First, and by far the most important, was splitting up the loading tasks into distinct phases and spreading them out across frames. Before I was loading the entire tile (for a ground tile this means generating the terrain heightmap, applying the ground texture via a mask, generating the sky color and applying it, then converting it to a Pyglet sprite) when it was initialized, which was way too slow. Each of the surface tiles were taking about .03 seconds, and I am loading 3 tiles at a time (I briefly had some code to only load 2 at a time, but I took that out because it was poorly written. If I need to, I’ll go back and do that again).
So, I wrote a new tile class that handles all its own loading. The idea is simple enough – each tile has a stack of ‘steps’ it needs to do to be fully loaded. Some require just one step like underground tiles (copy the cached underground texture), and some require a long series of them like surface tiles (generate terrain array, create terrain mask, apply background sky texture, use mask to apply ground texture over terrain, convert image to texture for rendering). On the very first step, the tile gets its tile type from the main map and sets the necessary steps accordingly. Now, each frame, if there are still steps left in the todo stack, it pops one off and processes it. The tile comes a little closer to being fully loaded, and it only takes as much time as one step, instead of all of them together. When the to-do stack is empty, the tile is finished, and it just renders itself like normal.
While that took care of my frame lag problem, my design made me worried about wasting some loading. Here is my MS Paint explanation of the how the map loads tiles as the player moves.
In the situation above, the player is now on the far left of the new center tile (f). If it moves just one pixel back to the left, the process happens again in reverse – dropping the JKL column and reloading the tiles for ADG. So wasteful!
Solution: Caching. Now the map keeps around the last handful of tiles it drops. When the user crosses to the right and ADG gets dropped, they get saved. If the user then comes back to the left (without going too much further away), those tiles are still available and the map can just use the saved copies (fast) instead of generating new ones (very slow).
Map tasks still ahead:
- clouds
- platforms
- regions & their specific terrain
- foilage
- wrapping the world





