When you embark on a project, the first thing a developer ought to do is to run some basic math. Especially if you already have some specs regarding the number and sizes of assets. Because otherwise you may end up trying hard to work around a memory related issue which perhaps even modern desktop computers would struggle with.

So today, I’ll do some math for you, the things you should consider before starting a project or adding one more of those big new shiny features to your app. Kind of like an addendum to my popular article about memory optimization and reducing bundle size.

How much wood texture would a woodchuck choke on if a woodchuck could choke on wood textures?

A texture is an in-memory representation of an image made up of individual pixels. Each pixel uses a certain amount of memory to represent its color. A texture’s memory size is therefore simply the product of width * height * sizeof(color).

Before I go any further, I like to stress it again: the size of an image file is much smaller than the size of the texture generated from the image. Don’t use image file sizes to make memory usage estimations.

Most common are 32-Bit and 16-Bit textures which use 4 and 2 Bytes respectively per pixel. A 4096×4096 image with 32-Bit color depth therefore uses 64 MB memory. Let that sink in for a moment …

At 16-Bit it only uses half of that, though without color dithering (TexturePacker does this for you) this might not look too good depending on the image.

This is pretty much what you’re stuck with unless you export textures as .pvr.ccz. Not only does this format load tremendously faster than PNG (not to speak of JPG which are unbearably slow to load in cocos2d), the .pvr.ccz format also reduces the texture memory size because the texture can stay compressed in memory.

It’s extremely difficult to estimate how much smaller a PVR texture’s memory footprint will be without actually giving it a try. But you can expect anywhere between 10% to 50% reduction.

To the non-power-of-two!

Continue reading »

Due to technical issues (blank page) I had to split the previous article (now focuses only on memory optimization) in two. This is the second part which (mostly) focuses on reducing the app bundle size.

Loading Assets In Sequence

Here’s the code that I use to load textures or other assets asynchronously (in background, on another thread).

Imagine loadAssetsThenGotoMainMenu being a scheduled method that runs every frame or perhaps less often. The assetLoadCount and loadingAsset variables are declared in the @interface as int and BOOL respectively.

When this method runs the first case statement is executed. To avoid accidentally loading the same image multiple times every time the selector runs, the loadingAsset flag is set to YES. When the texture cache has completed loading this texture, it will call the increaseAssetLoadCount. This then ensures that the next case statement is executed the next time loadAssetsThenGotoMainMenu runs.

The cool thing about this solution is that you can easily add more switch statements to add more textures to load. Because the default case is where the scene changes, and that only happens if there are no more switch cases to process.

Be sure not to skip a number in the switch cases because that will also run the default case.

Decreasing the size of your app

Besides the memory usage advantage, reducing the color bit depth of textures to 16 bit will also significantly reduce their size. But there are other options that will allow you to reduce your app’s size, perhaps significantly.

TexturePacker PNG Optimization

If for some reason you still want to use PNG files instead of the highly recommended .pvr.ccz file format, TexturePacker has a slider named “Png Opt Level” to help reduce the size of PNGs (doesn’t affect loading time though):

As far as I understand it, it tries a given number of optimizations and picks the one that creates the smallest file size. The downside is that the maximum level can take very long for large texture atlases, in some cases 10 to 20 minutes on a Late 2009 27″ iMac. The task is multi-threaded, so it should be a lot faster on quad core systems.

Fortunately there’s really no need to do this unless you’re ready to release the app. Question is, how much can it reduce the size of PNG files?

Continue reading »

I’m currently completing one last contract project. One of the last things I had to deal with was to optimize the game’s memory usage.

In today’s iDevBlogADay article I’ll explain how I was able to cut down memory usage by about 25-30 MB (down to 90-95 MB, ie fixing memory warning related crashes) as well as reducing the size of the app bundle from around 25 MB to below 20 MB (which would have been more awesome if Apple hadn’t already increased the over-the-air download limit from 20 MB to 50 MB some time ago).

I’ll also explain how to animate the loading screen while you’re loading resource files, and I’ll add some best practices and common wisdom too.

What’s using 90% of the memory?

Take a guess.

In almost all cases, it’s textures that consume most of the app’s memory. So textures is where you look to optimize first and foremost if you’re having memory warning troubles.

Avoid loading PNG/JPG Textures one after another

The problem with texture loading in cocos2d is that it happens in two steps: first, a UIImage is created from the image file. Then a CCTexture2D object is created from that UIImage. This means while a texture is being loaded, it will consume twice as much memory for a short time period.

The problem used to be so bad that if you loaded 4 textures one after another in the same method, at the end of the method each texture would still consume twice as much memory as it ought to, probably because of the way autorelease works.

I’m not sure if this is still the case, or whether this only applies to manual reference counting but not ARC. I made it a habit to load textures in sequence, waiting at least one frame before trying to load another. This will allow any texture loading overhead to be released from memory. Besides, as you’ll see later, if you want to load textures and other assets in the background this asset-load-sequencing is something you’ll do anyway.

Continue reading »

What is a Sprite Sheet?

On June 21, 2012, in tools, by Steffen Itterheim

A Sprite Sheet is of course a Texture Atlas (see Wikipedia). Simple, right?

Oh you wanted to know details? Like, why you should use sprite sheets? What the benefits are? How sprite sheets save memory?

Then watch the vividly animated “Sprite Sheets – The Movie, Part 1” (aka Essential Facts Every Game Developer Should Know) courtesy of Andreas Löw:

You can find the transcript of the video on this page and the tool that can do all that (and more) is TexturePacker.

Tagged with:  

Cocos2D Webcam Viewer, Part 2: Asynchronous Texture Loading

On February 23, 2012, in idevblogaday, by Steffen Itterheim

I updated the Cocos2D Webcam Viewer project from a previous article to download a file from the web asynchronously, and then load its texture asynchronously as well. You can now switch between the two modes to see how asynchronous operations almost completely removed the pauses the app experiences in synchronous mode. Just tap the screen to switch modes.

To visualize the lag I added a constantly moving sprite at the bottom. This makes the lag easier to spot than a framerate counter. I also removed all error checking code from this article to make the code easier to read. As always you can find the Cocos2D Webcam Viewer source code with full error checking on the LearnCocos2D github repository.

Continue reading »

Cocos2D Sprite-Batch Performance Test

On September 8, 2011, in cocos2d, idevblogaday, Kobold2D, by Steffen Itterheim

While writing the Learn Cocos2D book I was surprised to find that Cocos2D’s CCSpriteBatchNode was only able to increase the performance of several hundred bullet sprites on screen by about 10-15% (20 to 22.5 fps). I wanted to re-visit that scenario for a long time because as far as I understood, the more sprites I was drawing the greater the impact of CCSpriteBatchNode should be.

But even Cocos2D’s own sprite performance tests (compare columns 9 and 10) revealed a performance difference of under 20% (39 to 42 fps). It’s only when all sprites are scaled and rotated, or most of them are outside the screen area, that sprite batching seems to have a bigger impact (25 to 60 fps). Surely that scenario is not applicable to most games. So I started investigating.

Continue reading »