0
votes

I am creating an app which has around 15 different animations. Some animations are played on button taps while some are played on certain event. As I am new to cocos2d I just cannot figure out how to initialize these animations. I have separate sprite sheets for each animation. What I have done is created a convenience class that has as a data member, a CCSprite object. And in the init function I have placed all the code to create animations. But as soon as the init function is called I get memory warning.

I even tried to initialize the animations only when the request for playing the animation is sent, but I still get the memory warning. Also if I do so the animation doesn't play until the whole sprite sheet is loaded.

Please check the following code for reference

    - (void)initEntryAnimation
    {
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"entry.plist"];
        CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"entry.png"];
        [self.sardarSprite addChild:spriteSheet];

        NSMutableArray *entryFrames = [NSMutableArray array];
        for(int i = 0; i < 77; i++) {

            if([[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
            [NSString stringWithFormat:@"enter in scene%04i.png", i+1]])
            [entryFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
            [NSString stringWithFormat:@"enter in scene%04i.png", i+1]]];
        }

        self.entryAnimation = [CCAnimation animationWithFrames:entryFrames delay:0.05f];
    }

    - (void)playEntryAnimation
    {
        [CCSpriteFrameCache purgeSharedSpriteFrameCache];

        [self.sardarSprite runAction:[CCAnimate actionWithAnimation:self.entryAnimation restoreOriginalFrame:NO]];
    }

I have created similar functions for all the 15 animations. I call all the initialization functions one after another. And the play functions are called whenever a request for the animation is sent.

I desperately need some expert advise. Any help would be highly appreciated.

2
How large are the frames of your animation?Nick Bull
The images that I used for creating the sprite sheets are 320*480, does that matter as I putting them in a sprite sheet by occupying all the transparent areas.Hammad
Putting them in a sprite sheet will only reduce the storage space on disk and then memory usage if the sprites are small. How large are your sprite sheets and how many do you have? Unless you have only a very small image with lots of transparent space on a 320x480, you're still going to use a lot of memory.Nick Bull
Most of the sprite sheets are 2048*2048 as almost all of the animations have a lot of frames in them some even 300+. So for animations with 300+ frames I have split the animations into multiple sprite sheets that makes more than 15 sprite sheets. I am thinking that using sprite sheets is not a good approach in my case. Nick would suggest any solution other than sprite sheets?Hammad
There's your problem. Every sprite sheet is 2048x2048x8 in memory. You are limited to the amount of memory you have (don't confuse memory with disk space and the size of your sprite sheet on disk is different to in memory). You can try using a different format (see texture packer for example which has options for that), or break up your animation into just the bits that move and animate them. Without knowing the exact animation, it's difficult to advise.Nick Bull

2 Answers

0
votes

Try adding NSAutoreleasePool like this

- (void)initEntryAnimation
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"entry.plist"];
        CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"entry.png"];
        [self.sardarSprite addChild:spriteSheet];

        NSMutableArray *entryFrames = [NSMutableArray array];
        for(int i = 0; i < 77; i++) {

            if([[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
            [NSString stringWithFormat:@"enter in scene%04i.png", i+1]])
            [entryFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
            [NSString stringWithFormat:@"enter in scene%04i.png", i+1]]];
        }

        self.entryAnimation = [CCAnimation animationWithFrames:entryFrames delay:0.05f];
        [pool release];
    }
0
votes

The problem is the size of your sprite sheets. The sprite sheet file size (the size of the png) may be very small, but that is the size on disk. Once your app has loaded that into memory, it is stored uncompressed so that's 2048x2048x8 per sprite sheet.

You can reduce the colour depth to RGBA4444, for example which may help. See TexturePacker for more details. There are other tools available (I am not affiliated with TexturePacker in any way).

Other options you have are to reduce the colour depth further or to use one of the other formats available. You could also look at your animations and see if there is any way to break them down into more discrete components. For example, if you have an animation of a man running, perhaps instead of having the full screen frames, you could have one frame of the torso and then different leg animations and arm animations which you then use.

Without knowing the exact animation, it's difficult to advise.