cocos2d dynamically changing animation speed with

2019-03-31 14:52发布

问题:

In a simple game, a character has a walking animation of around 15 frames. Based on the accelerometer is speed in either direction changes. I wanted the animation to speed up or slow down accordingly. I realize that once the animation is initialized, you can't change the delay speed, and instead you need to create a new animation. But since the speed changes almost constantly, if I kept reseting the animation, it would always be stuck on the same frame.

Is there a way to find which frame an animation is currently in, stop it, then create a new animation with the same frame but starts at which the last animation ended?

Otherwise does anybody have an idea of how you could go about implementing a dynamically changing animation delay time?

EDIT:

I have tried using CCSpeed to do this from an example in Learn Cocos2d 2. Here is the code:

CCRepeatForever *walkLeftRepeat = [CCRepeatForever actionWithAction:[CCAnimation animationWithSpriteFrames:walkLeftFrames]];

self.walkLeft = [CCSpeed actionWithAction:walkLeftRepeat speed:animationWalkingSpeed];

I get the following warning: Incompatible pointer types sending 'CCRepeatForever *' to parameter of type 'CCActionInterval *'

Here is the example I am following from:

CCRepeatForever* repeat = [CCRepeatForever actionWithAction:rotateBy];
CCSpeed* speedAction = [CCSpeed actionWithAction:repeat speed:0.5f];

Second EDIT:

Then I tried this:

CCAnimation *walkLeftRepeat = [CCAnimation animationWithSpriteFrames:walkLeftFrames];
CCAnimate *temp = [CCAnimate actionWithAnimation:walkLeftRepeat];
CCAnimate*temp2 = [CCRepeatForever actionWithAction:temp];
self.walkLeft = [CCSpeed actionWithAction:temp2 speed:animationWalkingSpeed];
[_guy runAction:_walkLeft];

Final edit. This problem of it not showing up was fixed by adding a delay to ccanimation.

This doesn't give any error's but nothing happens. Thanks!

回答1:

No need to recreate the animation. Use a CCSpeed action with the CCAnimate action as its inner action. Then you can modify the CCSpeed action's speed property to speed up or slow down the animation.

The alternative is to advance frames yourself. It's easy to do, you only need a scheduled update and a timer that tells you when to change to the next frame. You speed up or slow down the animation by simply changing how much you add to the timer every frame. If the timer is > than a specific value you change frames and reset the timer to 0.



回答2:

You can do it in Cocos2d Game:

-(void)preLoadAnim
{
     CCAnimation* animation = nil;
    animation = [[CCAnimationCache sharedAnimationCache]  animationByName:@"ANIMATION_HERO"];

    if(!animation)
    {
        CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];

        NSMutableArray *animFrames = [NSMutableArray array];

        for( int i=1;i<=4;i++)
        {
            CCSpriteFrame *frame = [cache spriteFrameByName:[NSString stringWithFormat:@"HeroRun_%d.png",i]];
            [animFrames addObject:frame];
        }

        animation = [CCAnimation animationWithSpriteFrames:animFrames];

        animation.delayPerUnit = 0.5f; 
        animation.restoreOriginalFrame = NO;

        [[CCAnimationCache sharedAnimationCache] addAnimation:animation name:animName];
    }
}

-(void)runHeroSlowMode
{
     CCAnimation* animation = nil;
    animation = [[CCAnimationCache sharedAnimationCache]  animationByName:@"ANIMATION_HERO"];

    animation.delayPerUnit = 1.0f; 

    CCAnimate *animAction  = [CCAnimate actionWithAnimation:animation];
    CCRepeatForever *runningAnim  = [CCRepeatForever actionWithAction:animAction];
    runningAnim.tag = kTagHeroRunAction;

    [self stopActionByTag: kTagHeroRunAction];

    [heroSprite runAction:runningAnim];

}


-(void)runHeroFastMode
{
     CCAnimation* animation = nil;
    animation = [[CCAnimationCache sharedAnimationCache]  animationByName:@"ANIMATION_HERO"];

    animation.delayPerUnit = 0.1f; 

    CCAnimate *animAction  = [CCAnimate actionWithAnimation:animation];
    CCRepeatForever *runningAnim  = [CCRepeatForever actionWithAction:animAction];
    runningAnim.tag = kTagHeroRunAction;

    [self stopActionByTag: kTagHeroRunAction];
    [heroSprite runAction:runningAnim];

}


回答3:

I was also facing the same problem. In my game whenever I collect something my speed increases. at that time I paused my animation at the current frame changed its delay time and then resumed it.... Now its working