SKAction完成块内的代码未按预期工作

时间:2014-04-07 15:26:39

标签: ios objective-c-blocks sprite-kit skaction

我在游戏中实现了“暂停菜单”。当用户点击屏幕左上角的暂停按钮时,我运行以下代码:

- (void) pauseGame
{
    // Blur the game's contents:
    [_effectNode setShouldEnableEffects:YES];

    // Apply cover:
    [_pauseLayer addChild:_pauseCover]; // (_pauseLayer sits just above _effectNode)

    // Start from fully transparent...
    [_pauseCover setAlpha:0.0f]; // Start from fully transparent...

    // ...and animate to near-opaque:
    [_pauseCover runAction:[SKAction fadeAlphaTo:0.85f duration:0.125f]];
}

取消暂停,我这样做:

- (void) unpauseGame
{
    // Un-blur game contents
    [_effectNode setShouldEnableEffects:NO];

    // Fade cover out
    [_pauseLayer runAction:[SKAction fadeAlphaTo:0.0f
                                        duration:0.125f]
                completion:^(void){
                    // The following lines are executed, but still 
                    // the button below doesn't receive any more touches

                    [_pauseLayer removeAllChildren];// Neither
                    [_pauseCover removeFromParent]  // of these
                    [_pauseLayer setHidden:YES];    // makes a difference

                }];
}

取消暂停后,节点层次结构与之前完全相同(我记录了它)。但是,暂停按钮一旦被_pauseLayer(类型SKNode)及其子_pauseCover(类型SKSpriteNode)覆盖,就不再接收触摸输入(游戏场景本身) ,确实)。

如果不是删除淡入淡出动作完成块上的封面,我会立即执行,或使用-performSelector:withObject:afterDelay:,如下所示:

- (void) unpauseGame
{
    // Un-blur game contents:
    [_effectNode setShouldEnableEffects:NO];

    // Fade cover out to fully transparent:
    [_pauseLayer runAction:[SKAction fadeAlphaTo:0.0f
                                        duration:0.125f]];

    [_pauseLayer performSelector:@selector(removeAllChildren) 
                      withObject:nil
                      afterDelay:0.25]; // a bit longer than fade, just in case
}

...然后,在恢复之后,该按钮就像以前一样工作......我知道SKSpriteNode实例会阻止触摸事件(即使使用setUserInteractionEnabled:NO),但精灵不再存在!令人费解!

注意我必须强调完成块执行执行(断点停在那里),并在之后记录已删除的子项给出正确的计数(0)。但是,暂停按钮(实现-touches*: withEvent:方法的sprite子类)不再接收触摸。


解决方案: 的 我从来没有完成我想要的任务:让一堆“占位符”节点充当固定深度的层(层),然后根据需要添加/删除子节点(在这种情况下,封面精灵/对话框) 。我想以这种方式实现它,因为SKNode没有-insertChild:aboveChild:insertChild:belowChild:方法,并且获取目标索引并插入有一点容易出错/混淆(现有节点在哪个方向)得到“推”?)。

然而,我放弃了,并决定按需添加/删除父层,只是跟踪顺序(先进先出,保留预期的图层顺序)。

足够的谈话,我解决的代码是:

#define GameSceneDefaultSingleFadeDuration 0.125f

- (void) pause:(id) sender
{
    [_effectNode setShouldEnableEffects:YES];

    [self addChild:_pauseLayer];
    [_pauseLayer addChild:_pauseCover];
    [_pauseCover setAlpha:0.0f];

    [_pauseCover runAction:[SKAction fadeAlphaTo:0.85
                                        duration:GameSceneDefaultSingleFadeDuration]
                completion:^(void){
                }];

    [self addChild:_dialogLayer];
    [_dialogLayer addChild:_pauseDialog];


    for (Button* button in [_pauseDialog children]) {
        [button setAlpha:0.0f];
        [button runAction:[SKAction fadeAlphaTo:1.0f
                                       duration:GameSceneDefaultSingleFadeDuration]];
    }
}

- (void) resume:(id) sender
{
    // Unblur, fade white cover out and remove

    [_effectNode setShouldEnableEffects:NO];

    [_dialogLayer runAction:[SKAction fadeAlphaTo:0.0f
                                         duration:GameSceneDefaultSingleFadeDuration]
                 completion:^(void){

                     [_dialogLayer removeAllChildren];
                     [_dialogLayer setAlpha:1.0f];
                     [_dialogLayer removeFromParent];
                 }];

    [_pauseCover runAction:[SKAction fadeAlphaTo:0.0f
                                        duration:GameSceneDefaultSingleFadeDuration]
                completion:^(void){

                    [_pauseCover removeFromParent];
                    [_pauseLayer removeFromParent];
                }];
}

_pauseLayer在模糊的游戏内容之上,_dialogLayer仍在此之上,托管不同的对话框:“已暂停”,“确认退出”,“确认重新启动”)。

0 个答案:

没有答案