Improving the Performance of Animating Sprites in cocos2d
cocos2d has proven to be invaluable in enabling us to get our iPhone game up and running fast. But when we started playing with animated sprites, we noticed some performance problems. If you are like us and have many sprites that have to have repeating animations, you may have noticed the same thing.
Conventional wisdom (aka the sample code) says that you would create a RepeatForever action using an Animate action to animate an AtlasSprite. When we tried this, however, we noticed that at the end of each animation cycle, the action would deallocate an AtlasSpriteFrame. This is a by-product of the Animate action being able to restore the original frame of animation once the animation has finished playing. This is also what was causing the performance issues.
To resolve this, we created a cut-down version of the Animate action called FastAnimate. It is very similar to the Animate action with the exception that it does not support restoring the original frame of animation. From what we’ve seen, this simple change greatly increases the performance of animating sprites in cocos2d.
FastAnimate.h:
#import "cocos2d.h" @interface FastAnimate : IntervalAction <NSCopying> { Animation *animation; } +(id) actionWithAnimation:(id<CocosAnimation>) a; -(id) initWithAnimation:(id<CocosAnimation>) a; @end
FastAnimate.m:
#import "FastAnimate.h" @implementation FastAnimate +(id) actionWithAnimation: (id<CocosAnimation>)anim { return [[[self alloc] initWithAnimation:anim] autorelease]; } -(id) initWithAnimation: (id<CocosAnimation>)anim { NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); if( (self=[super initWithDuration: [[anim frames] count] * [anim delay]]) ) { animation = [anim retain]; } return self; } -(id) copyWithZone: (NSZone*) zone { return [[[self class] allocWithZone: zone] initWithAnimation: animation]; } -(void) dealloc { [animation release]; [super dealloc]; } -(void) startWithTarget:(id)aTarget { [super startWithTarget:aTarget]; } -(void) stop { [super stop]; } -(void) update: (ccTime) t { NSUInteger idx=0; ccTime slice = 1.0f / [[animation frames] count]; if(t !=0 ) idx = t/ slice; if( idx >= [[animation frames] count] ) { idx = [[animation frames] count] -1; } id<CocosNodeFrames> sprite = (id<CocosNodeFrames>) target; if (! [sprite isFrameDisplayed: [[animation frames] objectAtIndex: idx]] ) { [sprite setDisplayFrame: [[animation frames] objectAtIndex:idx]]; } } @end
What Caught Our Eye This Week – July 26 to August 1, 2009
Here’s a look at just some of the things that we kept our eye on this week:
- Why nobody hates software more than software developers. Hint: it’s because we know the volumes of bad code that get poured into it.
- Google Voice applications got rejected from the iPhone’s App Store. This is causing a lot of concern among both developers and users of the iPhone platform. Michael Arrington even declared that he’s “quitting” the iPhone.
- Two researchers announced they had discovered a way to virally infect and hijack the functions of every iPhone on earth. Thankfully, none of Get Set Games’ devices were affected once they unveiled the exploit on Thursday. Apple was quick to release a patch.
- In a bid to keep iPhone jailbreaking illegal, Apple claimed in a filing that jailbreaking would turn the iPhone into a weapon against cell-phone towers.
- We watched in amazement as Yahoo! committed seppuku this week, making it a historic week in online search.
If you’d like to keep track of what we read and join in on the discussion, join our FriendFeed room.







