1

我有一个 GameScene(这里称为 ShooterScene),然后我退出到 MainMenu。我确实使用加载到纹理缓存中的精灵表。有各种动画正在进行(背景元素、敌人、玩家等......)。几个月来,我遇到了一个问题,即 Enemies 的“setTexture”方法断言失败。我通过在替换场景之前暂停共享 CCDirector 解决了这个问题。这具有停止动画的效果。但是我只部分解决了这个问题。游戏不再在 Enemy setTexture 上崩溃,但现在在 AnimatedBackgroundElement setTexture 方法上崩溃。

背景元素被添加到精灵批处理节点,该节点是作为子元素添加到 GameScene 的 Background 类的子节点。我确实想知道,由于某些层次结构的原因,暂停调用的传播是否存在一些延迟,或者“暂停”线程和背景元素的 CCAnimate->setTexture 线程之间是否存在一些并发问题。

有什么建议/想法吗?

PS:我检查了“[[CCDirector sharedDirector] stopAnimation]”,它说:

CCLOG(@"cocos2d: Director#stopAnimation. Override me");

我是否打算“覆盖”此方法来解决上述问题?我想这将是一个通过递归调用真正停止所有孩子的所有动画的好地方,但同样,由于随后的“replaceScene”方法可能并发,我不确定延迟。我可以通过使用一系列回调(CCSequence with action1 = call stop animation and action2= replace scene)来解决这个问题,但我不能 100% 确定 action2 的调用只会在调用结束后发生停止动画(action1)。我可以为(所有孩子)写一个递归并将其放在replaceScene之前。或者延迟回调replaceScene(这不是一个优雅的解决方案,因为它是半任意的)..

-(void) restartLevel
{
    [self resetSharedData];
    [[CCDirector sharedDirector] pause];
    LevelName currentLevel = [GameController sharedGameController].currentlyPlayedLevelName;
     [[CCDirector sharedDirector] replaceScene:[ShooterScene sceneWithLevelName:currentLevel]];
}


-(void) exitToMainMenu
{
    [self resetSharedData];
    [[CCDirector sharedDirector] pause];
    [[CCDirector sharedDirector] replaceScene:[MainMenu scene]];
}

PPS:我看到有很多关于试图阻止一个场景的相关帖子。我猜其他人可能有类似的问题,所以可能有一个最先进的解决方案/设计模式。

编辑:我已经尝试实现这一点,但它仍然失败。

-(void) restartLevel
{
    [self resetSharedData];
    [[CCDirector sharedDirector] pause];
    LevelName currentLevel = [GameController sharedGameController].currentlyPlayedLevelName;

    [self stopAllActions];   //Does this actually stopAllActions and Animations for ALL child nodes?
    [self unscheduleAllSelectors];
    //Do I need something else here?
     [[CCDirector sharedDirector] replaceScene:[ShooterScene sceneWithLevelName:currentLevel]];
}
4

2 回答 2

1

愚蠢的问题,为什么是 [self stopAllAnimations]; 不工作?我称之为 [self unscheduleAllSelectors]; 在场景更改之前,它会破坏整个图层中的每个动画对象和计时器,这应该可以确保在没有断言失败的情况下安全地切换场景。

关于暂停的事情,我知道!!说真的,整个暂停的事情真的很烦躁,它似乎暂停了一些东西,但它并不总是暂停一些东西。据我所知,当你暂停时:计时器停止(并且 dt 没有增加),加速度计和触摸仍然有效,动画对象和移动对象停止移动,菜单按钮仍然有效,函数内的所有代码由菜单按钮调用的仍然运行。此外,它完成了调用暂停的函数内的所有代码,因此如果您暂停然后取消计时器并在一个函数中更改场景,您仍然会收到分配错误。

这是我所做的,更具体地说: - 停止所有动画 - 停止所有计时器 - 将变量“gameRunning”设置为 false,并在 gameLogic 的第一行 if(!gameRunning) return; - 将计时器设置为 0.1 秒,以仅触发一次以调用 makeTransition 函数 - 在计时器内进行实际场景更改。

于 2013-06-14T12:20:42.110 回答
1

[自我停止所有行动]; 并没有真正停止添加到图层子节点的所有操作。您需要在特定节点上手动调用 stopAllActions。

-(void)onExit
{
   [self.gameHeroSprite  stopAllActions]; //call this for all animated sprite
   [self stopAllActions];
   [super onExit];
}
于 2013-06-21T14:04:46.460 回答