cocos2d中的动画

时间:2011-08-08 08:21:55

标签: iphone cocos2d-iphone

我想知道是否有人可以解释我如何在cocos2d中重复使用动画?我习惯于所谓的通常方式:我创建一个“游戏对象”,加载动画,之后只需调用我的动画,如gameObj->idle();gameObj->walkToPoint(); ......

我知道这些辅助方法应该由我自己定义,我也研究过很多关于CC2d的指南,并以不同的方式使用动画,但是这些指南过于简单,并没有拍摄真实案例。

所以目前我编写了从plist和png纹理加载动画的方法,将此纹理添加到父图层并将第一个精灵分配给'Game Object'精灵。但我有一些问题 - 我仍然找不到播放动画的方法。

情况对我来说更难(但我知道这是通常的情况:) :)动画应该分配给'动作',应该有不同类型的动作。例如 - 空闲动作永远播放,死亡播放一次并停留在最后一帧并且拍摄动作播放一次并恢复前一帧 - 空闲的一帧。

为了简单起见,我将展示一些基本代码,包括复杂的检查和for..in循环(我想知道是谁决定将所有以cc2d动画格式存储的帧存储为Array并使用frame_%d加载它们,而不是作为具有结构Animations->Idle->Frames Animations->Shoot->Frames的字典,但这不是主要观点:))

//These things are global
CCAnimation *idleAnim; 
CCAction * idleAction; // idle animation should be played forever 

CCAnimation *deathAnim;
CCAction * deathAction; // death animation should be played once and stop at last frame

CCAnimation *shootAnim; 
CCAction * shootAction; // shoot animation should be played once and idle frame restored


    // loading animations with simple for loops
    - (id)init {
  self = [super initWithColor:ccc4(255,255,255,255)];
if (self) {     

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
     @"player.plist"];
    CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode 
                                      batchNodeWithFile:@"player.png"];

    [self addChild:spriteSheet];

    NSMutableArray *idleAnimFrames = [NSMutableArray array];
    for(int i = 1; i <= 20; ++i) {
      [idleAnimFrames addObject:
       [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
        [NSString stringWithFormat:@"hero_idle01_%04i_Layer-%i.png", i-1, i]]];
    }

    idleAnim = [CCAnimation animationWithFrames:idleAnimFrames delay:0.1f];

    idleAction = [CCRepeatForever actionWithAction:
                   [CCAnimate actionWithAnimation:idleAnim restoreOriginalFrame:NO]];



    NSMutableArray *deathAnimFrames = [NSMutableArray array];
    for(int i = 0; i <= 30; ++i) {
      [deathAnimFrames addObject:
       [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
        [NSString stringWithFormat:@"hero_death01_%04i_Layer-%i.png", i, i+1]]];
    }

    deathAnim = [CCAnimation animationWithFrames:deathAnimFrames delay:0.1f];

    deathAction =  [CCAnimate actionWithAnimation:deathAnim restoreOriginalFrame:NO];





    NSMutableArray *shootAnimFrames = [NSMutableArray array];
    for(int i = 0; i <= 19; ++i) {
      [shootAnimFrames addObject:
       [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
        [NSString stringWithFormat:@"hero_idleshoot02_%04i_Layer-%i.png", i, i+1]]];
    }

    shootAnim = [CCAnimation animationWithFrames:shootAnimFrames delay:0.1f];

    shootAction = [CCAnimate actionWithAnimation:shootAnim restoreOriginalFrame:YES];



    self.player = [CCSprite spriteWithSpriteFrameName:@"hero_idle01_0000_Layer-1.png"];        

    self.player.position = ccp(20, self.size.height/2);

    [self.player runAction:shootAction];

    [spriteSheet addChild:self.player];

    [self.player runAction:[CCRotateTo actionWithDuration:0.0f angle:45]];



    [self schedule:@selector(gameLogic:) interval:1.0];
    }
    return self;
}

此代码正确运行(加载空闲动画并永久播放)但我找不到很好地在动作和动画之间切换的方法。我见过的方法,例如当有人不拍动画时,他删除原始精灵从拍摄中获取第一个精灵,播放拍摄,删除拍摄精灵,恢复原始精灵。但是如果精灵旋转了怎么办?一个人应该从原始精灵中传递所有参数,例如翻转,旋转,比例等,在精灵之间往返?通常Game Objects是从CCSprite继承的,所以这个方法通常意味着应该一直删除和恢复主游戏对象?这对我来说并不清楚。

我尝试了下一步,但它们对我不起作用,程序只是暂停,没有任何内容写入调试(我访客是因为错误发生在其他线程中,负责触摸处理的那个)。

// somewhere after touch happened in [shootToPoint:(CGPoing)point] method
  [idleAction stop];  
  [shootAction startWithTarget:self.player];
  [self.player runAction:[CCSequence actions:
                            shootAction,
                             [CCCallFuncN actionWithTarget:self selector:@selector(shooted)],
                             nil]];

shooted方法中,我又称之为:

    [shootActino stop]; // or [self.player stopAllActions] - doesn't matter I guess
    [idleAction startWithTarget:self.player];
     CCSprite *sprite = (Bullet *)sender; // remove bullet sprite from memory
    [self removeChild:sprite cleanup:YES]; // remove bullet sprite from memory
    // other routines...

那么有人可以解释一下如何用辅助方法创建游戏对象来切换动画吗?请不要将我发送给cc2d文档,因为目前还不清楚如何从网络上的cc2d文档或其他教程中解决这个简单的问题。

1 个答案:

答案 0 :(得分:2)

由于您使用辅助方法而不是alloc / initWith创建实例...它们正在自动释放,这就是您崩溃的原因。

例如,您的空闲动画应该像这样创建:

NSMutableArray *idleAnimFrames = [[NSMutableArray alloc] init];
for(int i = 1; i <= 20; ++i) {
    [idleAnimFrames addObject:
     [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
      [NSString stringWithFormat:@"hero_idle01_%04i_Layer-%i.png", i-1, i]]];
}

CCAnimation *idleAnimation = [[CCAnimation alloc] initWithFrames:idleAnimFrames delay:0.1f];
[idleAnimFrames release];

CCAnimate *idleAnimate = [[CCAnimate alloc] initWithAnimation:idleAnimation restoreOriginalFrame:NO];
[idleAnimation release];

idleAction = [[CCRepeatForever alloc] initWithAction:idleAnimate];
[idleAnimate release];

这样你就可以多次使用这个动作,直到你释放它(你应该在你的dealloc方法中,或者在你完成它的时候在其他地方)。