Update time again ... recent work has concentrated on polishing and debugging code linked to map or level streaming. As previously mentioned instead of discrete levels the world is one continuous entity which is loaded on the fly ... basically there is a 3x3 grid of map sections loaded at any one time. When the player moves from one section to another the game loads the sections needed and cleans up the map sections no longer in use.
Simple in theory ... but a little more complex in practice. The first issue was linked to the player revisiting map sections. Here the concept of persistent game objects was needed. To give a simple example, imagine a player collecting a coin and then wandering off to explore a different part of the world. The map section is cleaned up and the coin is forgotten. Later the player comes back, the map section reloads and the coin is recreated - and the player gets even richer. Making the coin persistent (where it is never forgotten) means that once it is collected it cannot reappear.
That's a low impact example - more complex examples include moving objects (if a lift moves to a certain floor and stops then it should be at the same floor when the player comes back), switches and doors (an unlocked door should remain unlocked) and finally monsters (if it's dead then it should stay dead!). Without keeping a track of these would result in certain parts of the map becoming blocked off and inaccessible to the player.
Then to add another layer still, I needed to consider what would happen if a player does something (for example activates a lift) and then dies. When the player respawns should an object be persistent or not? This has involved changes to the respawn process (it now needs to be a full game reload rather than a simple move of the player back to the last respawn point).
All of this was a fairly predictable aspect of the map streaming system. Something that was much harder to narrow down and deal with was the collision detection. To give a bit of background every game object (wall, coin, lift, platform) may have a series of collision polygons to identify where the player and monsters can move, where they can't, where they will be moved automatically (on conveyor belts for example) and where they will trigger some kind of event (collect an object, trigger a switch or another event). The result is as shown in the screenshot below (to the left is the normal game view, to the right the debug view with collision zones highlighted).
The tricky bit ... objects are linked to map sections and the collision detection code iterates through the different map sections to check for collisions (there are probably better ways to do this but the collision code is the bedrock of the whole game, implemented early on and not easy to change). In general this works fine - the object is fully in a map section, the player or monster in the same map section and the collision detection works a dream. Unfortunately there are certain objects that slightly overlap the edges of a map section - bridges are a typical example of this where effectively the bridge links one map section to another. To deal with these cases I had the choice of always making sure objects didn't overlap ... which would lead to restrictive level design or update the code to handle overlaps. So I updated the code and it worked fine 99.9% of the time. Unfortunately occasionally it would break (anywhere on the map when objects overlapped in a certain way) and the collision detection would effectively switch off and the player would fall through the floor. Eventually after a lot of debugging the source of the problem was found – the overlap checking where, for some reason, I had got distracted and forgotten to add the last two lines of code. Two lines, probably 20 characters missing and as a result probably 2 weeks of on and off debugging … sometimes I need to be reminded why I enjoy developing games