【问题标题】:Animations in cocos2dcocos2d 中的动画
【发布时间】:2011-08-08 08:21:54
【问题描述】:

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

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

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

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

为了简单起见,我将展示一些基本代码,没有复杂的检查和 for..in 循环(我想知道谁决定将所有帧以 cc2d 动画格式存储为数组并使用frame_%d 加载它们,而不是作为字典结构Animations->Idle->FramesAnimations->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 文档或网络上的其他教程中解决这个简单的问题。

【问题讨论】:

    标签: iphone cocos2d-iphone


    【解决方案1】:

    由于您使用辅助方法而不是 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 方法中做,或者当你完成它时在其他地方做)。

    【讨论】:

    • 哦,我已经使用objective-c 有一段时间了,但仍然陷入这些保留/释放陷阱......我知道正确的答案就在拐角处:) 非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 2014-05-11
    相关资源
    最近更新 更多