iOS Development Optimizations Part 1 – Sprite Engine

Closed

In the time between Townrs Defender and Spires, I had the opportunity to rework the sprite engine to optimize performance in many ways. †You may remember that Townrs Defender had a number of, in particular, memory issues – on older devices it would frequently have to disable music to guarantee it would run. †So, memory usage was something I wanted to focus on for our version 2 of the engine.

One very common optimization, used in both 3d and 2d engines, is called atlasing. †Every texture change the render makes has overhead, so atlasing takes a series of textures and combines them into one big texture, on the assumption that if there are less textures, you’ll need to change them less frequently.

Sprite Sheet for an American Hero

Sprite Sheet for an American Hero

This is a great optimization, and very easy to parse – take the frame number you want, and treat it like an index into the image as a 2D array. †Creating it is as simple as downloading ImageMagick and running the ‘montage’ command from the commandline.

But †all that white space is a bummer, huh? †File compression will collapse a lot of it, but we have to expand the whole file and keep it in memory eventually. †We can try to crop the spite more tightly, but we’d always be limited by the largest sprite – an outstretched limb could wreck everything! †You can see it in this image alone – the sprites at the top where our mystery hero is running upward are much thinner then the ones at the bottom, where he runs sideways.

Well, I’m a programmer, so my fix is to write a new tool!

All we have to do is crop each individual sprite as tightly as we can, but when we do so, we have to remember how much we cropped from each side.

Our Hero Cropped Tightly

This allows us to push in from each side of the image without worrying about the center point of the image – by recording the edge offsets, we can re-align the sprite in-game with its original center point.

If we don’t record this information, the final sprite will bob around crazily!

Top-Left Aligned Sprite

Correctly Centered Sprite

Once we’ve cropped each sprite as tightly as we can, it’s time to pack them all together. †2D packing is a topic that has been extensively researched and implemented. †From my quick research and prototyping is seems that – at least for our rather simple ‘aligned rectangles packed within a square’ situation – a simple greedy algorithm gets us about 90% optimization. †Advanced algorithms can certainly boost that higher, but tend to take exponentially longer to run.

The result is quite nice. †Rather than using up a portion of a 1024×1024 sheet though, it makes more sense to split it into two 512×512 sheets:

Packed Sprite Sheet 1

Packed Sprite Sheet 2

1024 x 1024 sheet = 1048576 pixels

512x512x2 = 524288†pixels

That’s a 50% savings off the bat – and as you can see, we even have some leftover space to stuff more sprites into!

This entry is filed under Gaming, NicholasMTElliott.com, Programming, Prophetic Sky. And tagged with , , , , , , , , . You can follow any responses to this entry through RSS 2.0. Both comments and pings are currently closed.

Comments are currently closed.