当我试图在动画中间停止它时,Cocos2D与僵尸崩溃

时间:2011-01-24 12:54:04

标签: iphone cocos2d-iphone

我试图在我的iPhone应用程序中切换回基于UIView的视图之前让iPhone上的Cocos2D“自我清理”,但它过度释放(或者,过度释放什么东西和崩溃,我不能做它的正面或反面。

这有点长,但我已经尽力组织它。

我的节点层次结构如下所示,括号表示“每个节点中有什么内容”:

  1. CCScene(菜单)
  2. CCLayer(角色)
  3. CCLayer(整体动画)
  4. CCSprite, CCSpriteBatchNode(部分动画,每种类型可以有很多种)
  5. 因此,当“角色”运行不同的动画时,我从“角色”CCLayer中删除“动画”CCLayer,创建一个新的“动画”CCLayer,并将其添加为孩子。到目前为止,这没有造成任何问题。

    最后,CCScene上有一个按钮,“结束”应用程序的Cocos部分。当我点击“结束”按钮时,我想返回UIKit-land。

    然而,在我回到UIView-land之前,我想在Character上运行一个最终动画,当THAT结束时,终止。为此,我像这样在角色CCLayer上“注册”一个处理程序。我调用“最终”动画,然后在最终动画完成后回调到CCScene(使用KVO):

    - (void) doEndWithHandler:(id<LWECharacterDelegate>)handler
    {
      // Handler is the CCScene, "self.parent" could work but I want it loosely coupled
      self.endOfSessionHandler = handler;
    
      // Tell character to start final animation -- this creates a new CCLayer,
      // starts the animation, and assigns that CCLayer into self.animatedSequence
      [self changeCharacterActionTo:END_ANIMATION key:nil]];
    
      // The "animation" CCLayer has a property called "moving" -- observe it
      [self.animatedSequence addObserver:self forKeyPath:@"moving" options:NSKeyValueObservingOptionNew context:NULL];
    }
    

    然后我的观察代码,当“移动”变为NO(=动画结束)时回调:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
      if ([keyPath isEqualToString:@"moving"])
      {
        BOOL movingStatus = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
        if (movingStatus == NO)
        {
          // Stop observing
          [object removeObserver:self forKeyPath:@"moving"];
    
          // Stop all animations on this level
          [self.animatedSequence stopAnimation];
          [self removeChild:self.animatedSequence cleanup:YES];
          [self removeFromParentAndCleanup:YES];
    
          // Handler callback
          if (self.endOfSessionHandler && [self.endOfSessionHandler respondsToSelector:@selector(characterDidFinishSession)])
          {
            [self.endOfSessionHandler characterDidFinishSession];
          }
        }
      } // if key = moving
    }
    

    现在,你可以说,

      

    你不知道你可以在最后使用CCCallFunc作为动画添加回调,所以你知道你什么时候移动了吗?

    是的,我确实知道 - 但关键是CCScene“知道”何时按下结束按钮 - 而不是任何一个特定的动画。当按下结束按钮时,CCAction已经开始运动,所以我想告诉所有精灵停止动画并销毁。

    我的动画CCLayer有一些特殊代码告诉我精灵何时停止移动。该代码运行良好 - 我在每个动画结束时使用CCCallFunc回调来告诉我的“动画”CCLayer类已经完成了。

    为什么它似乎是一个问题,但是,在Cocos2D动作堆栈跟踪解除之前,我得到了“移动”已经改变的KVO通知。我很确定我的问题就在那里,因为只要KVO通知发出,我就会尝试停止一切(参见上面的代码)。然而,并非一切都停止,因为Cocos2D框架在尝试“包裹”堆栈跟踪时崩溃(过度发布)。

    是否无法在CCCallFunc回调中停止动画,这是一个动画相同精灵的动作?

    对于你真正的科科斯 - 那里,崩溃的确切线是:

    if( currentTarget->currentActionSalvaged ) {
      // The currentAction told the node to remove it. To prevent the action from   
      // accidentally deallocating itself before finishing its step, we retained
      // it. Now that step is done, it's safe to release it.    
        [currentTarget->currentAction release];
    

    ..位于CCActionManager.m的第327行。

1 个答案:

答案 0 :(得分:0)

好吧,我自己解决了这个问题。这里的关键教训是:

如果你正在“清理”一个Cocos会话,你应该可以从Cocos回调(CCCallFunc)做到这一点,但是在你的Cocos回调堆栈跟踪之前不要调用[[CCDirector sharedDirector] end]退绕。

就是这样。