我在游戏中实现了“暂停菜单”。当用户点击屏幕左上角的暂停按钮时,我运行以下代码:
- (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
仍在此之上,托管不同的对话框:“已暂停”,“确认退出”,“确认重新启动”)。