I worked to port Tim Roadley's cocos2d-iphone example from (Box2D Driven Cocos2D Animation) to cocos2d-x to learn cocos2d-x for a project. It is all relatively simple to do, but I am suffering from one obstinate problem. When the ball speeds up, the animation gets very jerky. This problem does not exist in Tim's cocos2d example.
From my investigation and close watching of the animation, it skips frames at the end of the animation sequence when the speed is high (above 4 or 5 in my code).
Here is Tim's original code and some context:
// LOAD ANIMATION FRAMES FROM SPRITESHEET
NSMutableArray *rollFrames = [NSMutableArray array];
for(int i = 1; i <= 120; ++i) {
[rollFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"Ball%i.png", i]]];
}
// CREATE ANIMATION ACTION
speedAction = [CCSpeed actionWithAction:
[CCRepeatForever actionWithAction:
[CCAnimate actionWithAnimation:
[CCAnimation animationWithFrames:rollFrames delay:0.1]]] speed:3.5];
// CREATE BALL SPRITE
ball = [TRBox2D spriteWithSpriteFrameName:@"Ball1.png"];
[ball setPosition:ccp((screenSize.width/2), (screenSize.height/2))];
original = ball.position; // used to determine ball trajectory
[ball runAction:speedAction];
[ball setTag:isTheBall]; // used so we can pick out this sprite during the physics loop
[ball setScale:0.7];
Here is my translation, again with some context:
// LOAD ANIMATION FRAMES FROM SPRITESHEET
CCArray *spriteFrames = CCArray::create();
for (int i = 1; i <= 120; i++) {
std::stringstream spriteName;
spriteName << "Ball" << i << ".png";
CCSpriteFrame *spriteFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(spriteName.str().c_str());
spriteFrames->addObject(spriteFrame);
}
CCAnimation *animation = CCAnimation::createWithSpriteFrames(spriteFrames, 0.1);
CCAnimate *animate = CCAnimate::create(animation);
CCRepeatForever *repeat = CCRepeatForever::create(animate);
speedAction = CCSpeed::create(repeat, 3.5f);
spriteFrames->release();
// CREATE BALL SPRITE
ball = (PhysicsSprite *)PhysicsSprite::createWithSpriteFrameName("Ball1.png");
CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
ball->setPosition(ccp((screenSize.width/2), (screenSize.height/2)));
original = ball->getPosition();
ball->runAction(speedAction);
ball->setTag(1);
ball->setScale(0.7f);
Tim's example uses COCOS2D_VERSION==0x00010001 (v1.0.1) I am using COCOS2D_VERSION==0x00020100 (v2.1.0)
I dug through the CCSpeed, CCRepeatForever, and CCAnimate. The major difference I find is in CCActionInterval.cpp where CCAnimate was changed to use "new animation format that supports delays per frame" (commit d0ab4515a4736bdf31aaed6394d95f8ea02beea1). If I revert this change to the previous "animation format" which does not support delays per frame, the sprite animates flawlessly at higher speeds.
Now to my question, am I mis-interpreting how the animation actions are intended to work in cocos2d-x 2.1? Have I missed something that is causing my jerky animation? It does not seem like changing some of the core code is the right answer, though bugs do exist.