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 »

Cocos2D Developer Survey Results

On November 16, 2012, in idevblogaday, by Steffen Itterheim

For the past two weeks I’ve been running a Cocos2D Developer Survey. As of today, 236 developers started the survey and 189 finished it completely. That’s 80% despite the many questions they had to answer.

Here are the results with my observations. I started the survey also to see if I was on track with KoboldTouch, and whether certain assumptions hold true. Specifically I had a hunch that cross-platform development is only perceived to have great value or appeal. Let’s see if I was right.

Click on each image for full resolution.

Who are you?

I was very curious how many cocos2d developers consider themselves to be hobbyists and indies compared to professionals, who either work for a mobile developer or are taking on freelance jobs as one.

Almost half of those who answered the survey are hobbyists. Nearly 30% consider themselves indies who make a living making mobile games. This is great!

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 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 »

The Complete (?) List Of Cocos2D Tools

On June 24, 2011, in book, cocos2d, tools, by Steffen Itterheim

For the second edition of the Learn Cocos2D book I compiled an alphabetically sorted list of tools that developers can use for cocos2d projects. Please let me know if there’s a tool missing from this list or if there’s one that won’t work anymore and hasn’t been updated in months.

The following tools can be used for development with cocos2d:

Bitmap Font Tools

BMFont (Windows)
Fonteditor
Glyph Designer
bmGlyph
Hiero
LabelAtlasCreator

Particle Editing Tools

ParticleCreator
Particle Designer

Physics Editing Tools

Mekanimo
PhysicsBench
PhysicsEditor
VertexHelper

Scene Editing Tools

CocosBuilder
Cocoshop
LevelHelper

Texture Atlas Tools

DarkFunction Editor
SpriteHelper
TexturePacker
Zwoptex

Tilemap Editing Tools

iTileMaps
Tiled Map Editor

Cocos2D Book Update: Progress Report

On May 29, 2011, in book, cocos2d, by Steffen Itterheim

It’s coming along great!

I completed the revisions on Chapter 1 through 5. The entire source code is now updated to use cocos2d-iphone v1.0.0 rc2. To make future code updates easier I also wrote a script that allows me to copy a newer cocos2d version to all projects, which essentially does Steps 1 & 2 described in the Updating Cocos2D in an Existing Project tutorial.

Most Notable Changes

Chapter 4 now includes a description of Glyph Designer for making Bitmap Fonts, and only mentions Hiero on the side. Glyph Designer is the better tool hands down.

Chapter 5 has seen a revision of the paragraph that explains subclassing from NSObject. I think I went too far off course here and subclassing from CCNode will make a lot of things easier while still giving the same benefits regarding class composition.

In Chapter 6 I decided to replace all descriptions of Zwoptex with TexturePacker as the preferred tool for making texture atlases.

For a while it looked like Zwoptex and TexturePacker would be competing on the same level. But recently Andreas Löw (TexturePacker & PhysicsEditor) made the move to work full-time on his tools, whereas Robert Payne is busy with a full-time job. I think the prospects are looking much better for TexturePacker now, and it is already leading in terms of features and update frequency.

That’s it for now.

A helpful CCSprite code gem …

On January 14, 2011, in cocos2d, Programming, by Steffen Itterheim

I often start out with new code using dummy graphics. Until I figure out what exactly I need and what is going to work, I work with single image files added to the project’s resources. Creating a texture atlas is always the last step I do, once everything is settled. Creating and updating a Texture Atlas adds just a few extra steps but I always strive to avoid any unnecessary extra steps during a creative working period. Especially while experimenting. Any repetitive task hampers creativity.

But eventually, I will have to go in and change every CCSprite initialization code from spriteWithFile to spriteWithSpriteFrameName. Except, I don’t.

The following is a simple extension category for CCSprite that extends CCSprite with a spriteWithSpriteFrameNameOrFile initializer. It looks for the given file name in the CCSpriteFrameCache. If it exists as CCSpriteFrame, it uses that sprite frame and otherwise it reverts back to loading the sprite from file. Very easy, very helpful.


// CCSpriteExtensions.h
#import "cocos2d.h"
@interface CCSprite (Xtensions)
+(id) spriteWithSpriteFrameNameOrFile:(NSString*)nameOrFile;
@end


// CCSpriteExtensions.m
#import "CCSpriteExtensions.h"
@implementation CCSprite (Xtensions)
+(id) spriteWithSpriteFrameNameOrFile:(NSString*)nameOrFile
{
  CCSpriteFrame* spriteFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:nameOrFile];
  if (spriteFrame)
  {
    return [CCSprite spriteWithSpriteFrame:spriteFrame];
  }
  
  return [CCSprite spriteWithFile:nameOrFile];
}
@end

Page 1 of 212