The main performance tweaks involved a bunch of changes to the particle engine which pretty much necessitated a complete refactoring of this part of the game code. This took several days and, whilst I know I have further optimisations to do, the result is an architecture that’s much more flexible and seems to run very well to boot. It could still be improved though. As this was kind of a generic topic I wrote a separate post on it here.
Other performance tweaks involved various memory optimisations, particularly implementing object pooling for commonly used objects. Again, as this was a pretty generic topic I wrote a separate post on it here.
The last thing to be optimised was collision detection and for the record I’ll list the main optimisations I made below. Though these are pretty specific to the way the gameplay and game physics work in Jetboard Joust they could be applied to a bunch of 2D games.
1. Ignore The Real World
Jetboard Joust implements a pretty simple physics model but it is still a physics model – therefore anything that exists in the game world is treated as being constantly under the influence of gravity (ie always falling) unless ‘pushed’ up by another object. This means that a collision check has to be run each frame for each object against any other object that might get in its way. Even though I use a segmented approach for the terrain this can still prove expensive.
When I ran my first diagnostic tests I was shocked to see that around 8.5% of the CPU time in my update loop was taken up by collision detection on the ‘pickup’ items (there are a lot of these created in the game and they can hang around a long time). As these pickup items are stationary most of the time this was clearly a complete waste of cycles!
So what I did was effectively disable the physics on the pickup items once they have come to rest. I can get away with this because I know that once they have come to rest the object on which they rest won’t be removed at any point – all that can happen to them is that they get picked up by the player or disappear if they hang around too long.
This simple optimisation took the CPU useage for this section of the code down to around 0.23% – a pretty hefty saving!
2. Apply Basic Logic, Stupid!
The next chunk of cycles were eaten up by collision detection on the enemies against the terrain. There were a couple of simple optimisations I could make here. Firstly I now keep a record of the highest point the terrain reaches when the level is constructed, if an enemy is higher than this point (as they often are) I know I don’t need to bother checking against the terrain at all. Similarly, if an enemy is travelling right I know I don’t need to bother checking against the right side of terrain objects and the same for the other directions.
3. Cache Me If You Can
I have my own Rectangle class that I use in my code and there were quite a few key places where I was using Rectangle.Width/2, Rectangle.Height/2. I replaced these with a HalfWidth and HalfHeight property that is cached and only updated when the Width or Height of the Rectangle is set – this has potentially saved me many thousands of division calculations per frame.
The game seems to be maintaining close to a 60fps framerate now in most situations though the fact I’m testing on a virtual PC running on a seven-year-old Mac Pro makes it kind of hard to tell for sure. I get occasional juddering but I think this is due to running on an emulated OS.
Oh yeah, I also decided that having the enemy mutations happen offscreen was kind of a cop out (as well as being annoying gameplay-wise) so we now have onscreen mutations!
Dev Time: 5 days
Total Dev Time: approx 42.5 days

Enemy Mutations Now Happen Onscreen
Badly Filmed – But Gives And Idea Of How Smooth Things Feel
Optimisations Don’t Always Go To Plan!