Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'd like to simplify the way I preload image resources in my Cocos2d based iOS apps. I've created a small object the just wraps a few of CCTextureCache's methods. It looks like this:

@interface TextureHelper : NSObject
+ (void) preloadTextures;
+ (CCTexture2D *) textureForImageNamed:(NSString *) imageName;
@end

@implementation TextureHelper
+ (CCTexture2D *) textureForImageNamed:(NSString *) imageName {
    return [[CCTextureCache sharedTextureCache] textureForKey:imageName];
}

+ (void) preloadTextures {
    // or could read from a directory...
    NSArray *imageNames = @[
    @"myImage1.png",
    @"myImage2.png"
    ];

    for (NSString *imageName in imageNames)
        [[CCTextureCache sharedTextureCache] addImage:imageName];
}
@end

The goal is to preload all images at start-up. Then during game play any sprites created on the fly won't cause images to be read from disk. What are some other more common and/or more effective patterns for achieving this?

share|improve this question

1 Answer 1

I think that the answer to this question is quite dependent on the structure of your game (level based? infinite runner?)

However in general in my experience you don't want to load ALL of your textures at startup. There are a few reasons for this:

  1. The iOS application sandbox only allows a certain amount of RAM to be used and once you reach that threshold, any more texture loaded kicks out other textures out of RAM (cocos2d manages this for you I believe.) However in the worst case the application will crash if it does not have enough memory to run. So load only the textures you immediately need.
  2. You're holding a lot of unused textures in memory which is inefficient.
  3. iOS WILL clear your game out of RAM if it needs it. So if your game has a lot of textures loaded (using up a lot of RAM) and the player multi-tasks out to another memory intensive app and iOS needs more memory for that app? Your app will be killed and your memory cleared. The next time the player switches back to your app, they will start from the beginning. You can avoid this situation by not using more RAM than you really need to.
  4. Cocos2d also will clear out unused textures when it receives a memory warning. You may end up faced with a situation where the textures you thought you loaded, are no longer in memory and your application will crash when trying to create a CCSprite using the texture.

I would recommend lazily loading textures as and when you need them. This also means you have to do a few things:

  1. Figure out how to package your sprite sheets so they are logically separated by when you need the textures within a single sprite sheet. For example, if your game is level based or is a children book, I would bundle textures that are part of the same level or the same page together. In this case you can load "level-02-textures.png" when the player is about to finish level 01 and by the time they are at level 02, the textures are loaded and ready to be used without disrupting gameplay.
  2. Figure out the best place to load your texture so it does not disrupt gameplay. Like the previous example, you know when the player will advance to a new level and therefore can start the loading process asynchronously before they need it to create an illusion of continuous gameplay without any disruption to load the textures. In the case of a book, I would have 3 pages loaded at any one time: Previous Page, Current Page, and Next Page. Anything outside that should be cleared from memory to give yourself more room.
  3. Clear any textures that you are not immediately using as much as you can. This is important. If iOS determines that your application is using too much memory, it will abort the application quite brutally so get into the good habit of freeing any memory that you can. This gives you more flexibility.
  4. Balance efficiency vs. flexibility. My suggestion in #1 of this list means that you may run into a decision you'd have to make. "If this texture is used in both level 1 AND level 2, should I split that into it's own sheet or lump it into the sheet with level 1 and again in level 2?" This choice affects the complexity of your code (with more than 1 file you might need per level, you'll have to have a more elaborate system of determining which texture is required for a particular level) and the space usage of your application (duplicating textures increases file size, but splitting textures also increases file size... which is worse? That depends on how complex your texture is.) The decision may be easy if a texture is only used in 2 levels, you might just bite the bullet and duplicate it in both level textures. But what if it is used in 5 levels or 10 levels? Then it would make more sense to split it out into its own sheet.

In the end of the day, as you can probably tell by now, it all really depends on your game, how many assets you have, how you organize your levels, how you designed your animations and textures, and a bunch of other factors. However, I hope this gives you a general idea of what to consider when you look at the problem of texture management.

share|improve this answer
    
Great answer! Much appreciated. I'm fascinated by the idea of having level-specific sprite sheets. I imagine doing this sort of optimization when version one or the beta of a game is close to shipping and it's clear which assets go with which levels. –  SundayMonday Jan 13 '13 at 1:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.