At the weekend I started a new project, an entry for July’s Experimental Gameplay theme “Disintegrate”. I was quite pleased with the progress I made over the short time so far (show below), but I’ve run into a major problem and I’ve been mulling possible solutions over in my head. Going to sound the problem, and one of the solutions, out here and see what happens, if by the time I’m done it sounds ridiculous then this post will probably never see the light of day. ;)
Currently my class for the spreading corruption keeps 2 arrays, effectively 2 tilemaps. One of these is for its visual representation and the other is a much simpler array of integer values that is used for raycasting, collision detection etc. Currently each tile in the corruption has a “corrupted” value, and when it is high enough it will start increasing the “corrupted” value of its adjacent tiles. This isn’t a straight forward increment, there are some seeded random values, and other considerations to be taken into account, that can speed up or slow down the corruption process.
This works quite well at current settings, and a world size of 1024×768 pixels, (each corruption tile is 8×8). The framerate starts to drop when the world size is increased beyond this. I want my game world to be considerably (+10x) larger than this.
My viewport is currently 800×600, so obviously not every tile is on the screen at once, so the next conclusion is that I don’t need to be generating the spread of corruption in realtime for non-visible areas. This seems trivial, but for one thing. I want the spread of corruption in the game to be a constant threat for the player. If the player leaves an area, where their buildings/resources/assets are, and travels a great distance away, I want the spread to be in their mind the whole time. When they return I want the shape, size and spread of the area to be in accordance with their expectations.
So, using the above statement I can say I regenerate the area as the player approaches it. However, what if I want the player to received alerts when their base of operations is being overrun? This will mean I need to keep the generation going in at least a semi realtime fashion.
The solution that currently has prime position in my mind is as follows…
First I drop the game’s viewport to 640×480 (a much more acceptable geometry for a flash game anyway). This will decrease the number of tiles on the screen at any given instant. Next, I break the world map down into viewport sized areas. Each of these areas themselves a tilemap of 8×8 corruption squares, essentially the same as my current single 1024×768 corruption class.
Now I take this new area class and I make some changes to its generation procedures. Lets, for the sake of argument, say we have 4 levels of generation.
1) Real-time. As the player views it, same as all generation is currently.
2) Semi-real-time. This will have the full generation procedure operating at a reduced rate, but using increased values. This will take less grunt to run, but will look jerky and horrible.
3) Deferred. These areas do not generate at all, they simply store the time elapsed since last time generation ran and run an efficient, less accurate, “catch-up” generation, regularly. (or when the player approaches them).
4) None. These areas have not yet been approached or witnessed by the player, they will be randomly created and pushed to one of the above modes when the player approaches them.
So, each 640×480 tilemap, will be pushed into one of these generation modes based upon the players position and current velocity. There will only ever be a max of 4 of these areas on-screen. So these 4 will be in mode 1, real-time. A player heading towards a corner will be approaching, at max, 3 other areas, these areas will be in mode 2, semi-real-time. All other tiles that the player has witnessed at least once will be in mode 3, deferred, with the remainder in mode 4.
It may be useful to actually insert another mode after semi-real-time, semi-demi-real-time if you will. This would be the areas just outside the real time areas, but not being approached by the player. That way we could handle sudden changes in direction smoothly.
Erm… yeah so that the idea, as fuzzy as it is.
Does it make sense?
