动画不能正常工作(Cocos2d)

Posted

技术标签:

【中文标题】动画不能正常工作(Cocos2d)【英文标题】:Animations are not working properly(Cocos2d) 【发布时间】:2011-10-12 07:03:24 【问题描述】:

我的问题是动画在精灵移动期间无法正常工作。 下面是我正在使用的代码

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event     

    [selSprite resumeSchedulerAndActions];
    CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
    [self selectSpriteForTouch:touchLocation];   
    return TRUE;    


- (void)selectSpriteForTouch:(CGPoint)touchLocation  

 CCSprite * newSprite = nil;

    for (CCSprite *sprite in movableSprite) 
        if (CGRectContainsPoint(sprite.boundingBox, touchLocation))             
            newSprite = sprite;
            break;
        
        
    if (newSprite != selSprite) 
        [selSprite stopAllActions];

        selSprite = newSprite;

        _MoveableSpritetouch = TRUE;
    

    if(_MoveableSpritetouch==TRUE)
    
      movement=0;
CGRect selRect=CGRectMake((SpriteX)-20.0,(SpriteY)-20.0,40.0,40.0);
        if(CGRectContainsPoint(selRect, touchLocation))
          
            [selSprite stopAllActions];


        
 if((selSprite==MarshallCar)&& (!(CGRectContainsPoint(selRect, touchLocation)))) 
        
            movement=1;
            [self reorderChild:selSprite z:5];


            NSMutableArray *MarshallCarWalkAnimFrames = [NSMutableArray array];
            for(int i = MarshallCarTouchStartFrameIndex; i <= MarshallCarTouchEndFrameIndex; ++i) 
                [MarshallCarWalkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"mcar_move_%d.png", i]]];
            
            MarshallCarWalkAnim = [CCAnimation animationWithFrames:MarshallCarWalkAnimFrames delay:MarshallCarTouchFrameDelay];
            walkMarshallCar = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:MarshallCarWalkAnim restoreOriginalFrame:NO]];


            [selSprite runAction:walkMarshallCar];
        



- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event        


    if(gameState == TRUE)


        CGPoint point = [touch locationInView:[touch view]];
        point = [[CCDirector sharedDirector] convertToGL:point];
        if (moveDifference.x>0)
                     
                        selSprite.flipX = YES;
                     

                    else 
                        selSprite.flipX = NO;
                     
         [selSprite setPosition:point];


     
  

-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
   
    movement=0;
if(selSprite==MarshallCar)
     
        [selSprite setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"mcar_idle.png"]];

    
[selSprite pauseSchedulerAndActions];

移动的动画帧不是每次都在移动时播放,有时会播放,有时不播放。当您第一次触摸和移动精灵时,它会正常播放,但如果触摸另一个精灵然后再次移动前一个精灵,则不会播放移动动画。

有人知道为什么会这样吗? 请告诉我删除此错误的正确代码。 谢谢!!!

【问题讨论】:

【参考方案1】:

我相信你的问题是 if/else if 构造:

if (_MoveableSpritetouch==TRUE)

        CGRect selRect = CGRectMake(SpriteX - 20, SpriteY - 20, 40, 40);
        if(CGRectContainsPoint(selRect, touchLocation))
          
            [selSprite stopAllActions];
        
        else if(...) 
        
            ...
            [selSprite runAction:walkMarshallCar];
        

如果您没有立即看到它:如果触摸位置在 selRect 内,则您在所选(新)精灵上调用 stopAllActions 并且不执行任何其他操作。仅当触摸位置不在该矩形内时,您才会运行动画操作。

我认为“矩形内”检查是多余的,因为您已经在上面几行调用了 stopAllActions。

请允许我对您的代码进行一些一般性评论:

“selectSpriteForTouch”方法告诉我你正在选择一个新的精灵。该功能就是这样做的。但它并不宣传播放动画。您可能希望将其重构为单独的“playAnimationOnSelectedSprite”方法。

您多次编写了 20.0 和 40.0。这意味着您实际上将双精度(8 字节浮点数据类型)传递给采用浮点数(4 字节浮点)的 CGPoint。严格来说,使用带有后缀“f”的 20.0f 将其表示为浮点数据类型,或者使用整数,因为您不使用浮点部分。

我不清楚为什么将 (SpriteX) 放在括号中,如果您想提高可读性,您可以通过在逗号和操作数后添加空格来实现更多目标。

在 Objective-C 中,使用 YES 和 NO 宏代替 TRUE 和 FALSE。

布尔变量 _MoveableSpritetouch 似乎是多余的,除非在其他地方需要。在任何情况下,您都应该将以下 if(_MoveableSpritetouch==TRUE) 块移动到您将 _MoveableSpritetouch 变量设置为 TRUE 的位置,因为它只会通过设置变量使您的代码更难阅读,留下您所在的代码块( if(selSprite != newSprite) ) 只是为了跳转到您已经知道无论如何都会运行的另一个代码块 ( if(_MoveableSpritetouch==TRUE) )。

【讨论】:

我已经编辑了代码 [ if((selSprite==MarshallCar)&& (!(CGRectContainsPoint(selRect, touchLocation) ] 现在告诉我有什么问题。【参考方案2】:
if((selSprite==MarshallCar)&& (!(CGRectContainsPoint(selRect, touchLocation)))) 
        
            movement=1;
            [self reorderChild:selSprite z:5];


            NSMutableArray *MarshallCarWalkAnimFrames = [NSMutableArray array];
            for(int i = MarshallCarTouchStartFrameIndex; i <= MarshallCarTouchEndFrameIndex; ++i) 
                [MarshallCarWalkAnimFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:[NSString stringWithFormat:@"mcar_move_%d.png", i]]];
            
            MarshallCarWalkAnim = [CCAnimation animationWithFrames:MarshallCarWalkAnimFrames delay:MarshallCarTouchFrameDelay];
            walkMarshallCar = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:MarshallCarWalkAnim restoreOriginalFrame:NO]];


            [selSprite runAction:walkMarshallCar];
        

我添加了 [selSprite stopAllActions]; 它开始正常工作,因为在触摸结束方法中我暂停了动作 但没有恢复它们,所以当我第二次触摸精灵时,它没有播放动画,因为动作暂停了。

【讨论】:

以上是关于动画不能正常工作(Cocos2d)的主要内容,如果未能解决你的问题,请参考以下文章

从时间轴播放 Spritebuilder 动画 - Cocos2d

Cocos2D 动画问题

Cocos2D 弃用的动画方法

UITableViewController 滚动引起的cocos2d动画暂停问题的解决

Sprite 帧动画 Cocos2d 3.0

cocos2d 动画从后台返回时停止