Saturday, December 25, 2010

Cocos2D support new and old devices textures

Got a new iPhone game project going - an opportunity to learn some new things which is always fun.
I am using the cocos2d framework, which really saves me a lot of work.
I still would like to get deeper into OpenGL ES some time later, but for this project it will be enough to have cocos2d handle the low level details.

One issue I struggled with is that I need to create fairly detailed animation of the scene background.

Due to the limit on OpenGL ES texture size (especially on older devices where the texture is limited to 1024x1024 pixels), I am faced with two options:

  • Limit the number of frames (In a 1024x1024 texture I can get 9 frames of size 320x340 which is the size of my background area in the game).
  • Construct the background area from multiple animations and compose them programmatically. While possible, this makes the design work more cumbersome as the designer needs to supply the needed graphics and their location.
Using a larger texture size of 2048x2048 gives me enough room for 36 frames, which is sufficient for quite a nice background animation loop, but should I give up all older devices (prior to iPhone 3Gs)?

There are millions of those!

So this leads me to the current solution I am going to use, which is:

Use a 2048x2048 texture for newer devices, and substitute that for a smaller 1024x1024 texture on older devices in run time.

But how should I decide which texture to use?

Well, I will save you all my google searches, as the answer was found right under my nose:

Cocos2d CCConfiguration class!

Here's the code:

    NSString *plistFile;
    int numFrames;
    if ([[CCConfiguration sharedConfiguration] maxTextureSize] < 2048)
    {
        plistFile = @"highQualityAnimation.plist"];
        numFrames = 36;
    }
    else
    {
        plistFile = @"highQualityAnimation.plist"];
        numFrames = 9;
    }
   
    // cache the frames to the sharedSpriteFrameCache
   
    CCSpriteFrameCache * cache = [CCSpriteFrameCache sharedSpriteFrameCache];
    [cache addSpriteFramesWithFile:plistFile];

    // create the animation
    CCAnimation * animation = [[CCAnimation alloc] initWithName:@"animation" delay:0.1];    // set the frame rate as needed
    for ( int i=1; i <= numFrames; ++i )
    {
        NSString * fname = [NSString stringWithFormat:@"animation_frame_%i.png", i];
        [animation addFrame:[cache spriteFrameByName: fname]];
    }

    CCSprite *backgroundSprite = [CCSprite spriteWithSpriteFrameName:[NSString stringWithFormat:@"animation_frame_1.png"]];
    id action = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:animation]];
    [backgroundSprite runAction:action];

    // add the sprite to the scene layer

    [self addChild:backgroundSprite];

That's easy enough, gives good animation on newer devices, and still reasonably support for older devices.

No comments:

Post a Comment