Side-scroller / Endless Runner Performance Tips

When building a twitch based game like The Four Hats, it is important that the game never lags. Losing from a hiccup in performance is infuriating as a player. In order to avoid mid-play lag we employed a few simple strategies that we would like to share. These can be used in a sidescroller or an endless runner like Temple Run.

Reduce Draw Calls

Try to reduce the number of draw calls made. If you are using cocos2d the easiest way to do this is to take advantage of CCSpriteBatchNode. CCSpriteBatchNode will batch draw all of its children. It must be initialized with a texture and all the CCSprites children must use that texture. Check out the documentation here.

Reduce Memory via Pixel Format

By using RGBA4444 rather than RGBA8888 you greatly reduce the amount of memory used for textures.

[CCTexture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA4444];

RGBA4444 may cause issues with gradient heavy artwork but if you are using TexturePacker then you can change your dithering settings to FloydSteinburg+Alpha or whichever format works best for your artwork.

Depending one what style of art you have you can try out other pixel formats and see what works best for balancing size, memory, and quality. An old but good post on understanding pixel formats can be found here.

Pruning / Delayed-Placement

If we loaded the entire level into memory at once we would spend a lot of time simulating objects far offscreen that might never being encountered. We would also waste clock cycles and memory on objects that have been passed by and will never be seen again. In order to reduce the number of objects that are part of the simulation, we wait to add them to the simulation until they are close to being on screen and we remove them from the simulation once then cannot be returned to. In Four Hats we can use the position of the approaching horde of fans to determine a safe point beyond which the character will never return.

Pre-allocation / Object Pool

Constantly adding and removing objects from the simulation in a naive way could cause a large number of allocations and deallocations while playing. This is something you should avoid to prevent random hiccups in game play. To solve this problem we used an object pool. We attempt to pre-allocate all of the objects we will need before starting the level. As objects are added and removed from the simulation they are swapped in and out of the object pool. This required game objects to have a reset method to clear any accumulated state. We built Four Hats using Obj-C and cocos2d, but if we were working in pure C++ then would likely have followed the methodology laid out by Noel Llopis on pre-allocation here. Our approach was unfortunately a bit messier.

In an endless runner it is difficult to predict exactly how many of any one type of object will be needed on screen at a time. In this case pre-allocation is difficult, but an object pool can still be used.

The End

Hopefully the work we put into avoiding slow downs will save a few iPhone from being thrown at us! If you have any other techniques that you have used, please share them in the comments.