With Apologies to Nethack
I took a few hours today to rework parts of the prototype I'm working on. I altered my "cursor" code to allow arbitrary leaps across the tile grid. Then, I augmented the console shell app to visualize where my cursor was, like so:
{2} TileGrid 137 {1} TileGrid 1 @ [16,16] {0} Tile 649 @ [14,30] ############################ # # # # ############ # # # ######### # ### # # ### ######### #### # ###### # # # #### # ## #### # # ##### # # ######## ## # # # ## ##### # # ########## ## ### # # ## # # ## ####### ## # ## # ### # # # ## ######### # ## # # # # # ########## ### # # # # # # # @ # # # # # # # ## # #
This shell app lets me use the cursor keys to move around the boundless playfield, digging tunnels as I go. Pretty neat. Each hash mark above is a Tile instance, and all the Tiles are held in TileGrids. The only thing stopping me from putting a U-clamp on an arrow key and letting it go all night is memory. With any luck, that won't be a hurdle for much longer.
The next steps, I think, are to solve serialization and facilitate garbage collection. Every tile grid (the view above is a single grid which may have others adjacent to it) needs to be serializable to disk, but because grids can be nested, serialization and deserialization need to be recursive. Also, because I want tile grids to fetch their children or parent on an as-needed basis, I don't want to just serialize the entire object tree starting from the top-most tier. Instead, I want to serialize a grid as a series of references to other serialized objects. The serializer would decide what parts of the TileGrid graph can be "culled", then write those to disk and reclamate their memory. The deserializer would lookup and deserialize only the grids it thought it needed to satisfy a particular view.
If I can get that IO working, then I need to figure out how/if to apply WeakReferences to the linkages between grids and tiles, so that the garbage collector is free to collect tiles that, for whatever reason, are deemed "unnecessary" for rendering. Experimenting with applying garbage collection to this kind of playfield is something I'm itching to do. Building a playfield manager (playfield = memory) that's smart enough to know what needs to be held and what can be released will be a fun challenge; I haven't done that before.
I can envision a solution that involves a mark & collect approach: start with the grid on which the player cursor resides, and climb the TileGrid tree, marking each TileGrid until the top is reached. Then allow the serializer to write out all "unseen" tilegrids to disk. The approach could be tweaked with different heuristics that aim to keep in-memory a working set of TileGrids relevant to the player's view or movement direction.