Ios 在我恢复一个场景之前,我如何倒计时?
我有一个暂停的Ios 在我恢复一个场景之前,我如何倒计时?,ios,sprite-kit,Ios,Sprite Kit,我有一个暂停的SKScene。当用户要求这样做时,我希望恢复场景。但是,我想在游戏开始前给用户几秒钟的准备时间。为此,当用户要求恢复游戏时,我希望先从3开始倒计时,然后恢复场景 我目前有一个SKLabel来指示计数。当用户单击resume时,我使用一个NSTimer从3开始倒计时,每秒更新标签的内容,并在计数结束时继续游戏 但是,由于游戏暂停,SKLabel不会每秒更新;它只在游戏恢复后的最后更新一次。我正在寻找解决这个问题的方法。在游戏场景中使用一个通用变量,指示游戏是否暂停,例如isGame
SKScene
。当用户要求这样做时,我希望恢复场景。但是,我想在游戏开始前给用户几秒钟的准备时间。为此,当用户要求恢复游戏时,我希望先从3开始倒计时,然后恢复场景
我目前有一个SKLabel
来指示计数。当用户单击resume时,我使用一个NSTimer
从3开始倒计时,每秒更新标签的内容,并在计数结束时继续游戏
但是,由于游戏暂停,
SKLabel
不会每秒更新;它只在游戏恢复后的最后更新一次。我正在寻找解决这个问题的方法。在游戏场景中使用一个通用变量,指示游戏是否暂停,例如isGamePaused
。在更新:
方法中,您将拥有:
if(!isGamePaused){
//Do all game logic
}
您可以使用isGamePaused
暂停和取消暂停游戏。现在,让我们倒计时。我将创建一个子类SKNode
,在那里添加SKLabel
,并设置一个委托,以便我们知道倒计时何时完成。例如,在倒计时.h
中:
@protocol SKCountDownDelegate <NSObject>
-(void)countDown:(id)countDown didFinishCounting:(BOOL) didFinishCounting;
@end
@interface SKCountDown : SKNode
@property (assign, atomic) id<SKCountDownDelegate> delegate;
-(instancetype)initCountDownWithSeconds:(int)seconds andColor:(UIColor *) color andFontName:(NSString *)fontName;
@end
因此,无论您想在何处添加此倒计时
,都可以执行以下操作:
-(void)startCountDown{
self.countDown = [[SKCountDown alloc] initCountDownWithSeconds:3 andColor:self.countdownFontColor andFontName:self.countdownFontName];
self.countDown.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
self.countDown.delegate = self;
self.countDown.zPosition = 20;
[self addChild:self.countDown];
}
-(void)countDown:(id)countDown didFinishCounting:(BOOL)didFinishCounting{
isGamePaused = NO;
}
这是一个这样做的例子。希望有帮助 在游戏过程中暂停整个场景对我来说似乎有点太直截了当了,因为您通常希望更新节点层次结构中的某些内容
一个简单的解决方案是区分游戏节点和UI节点。您只需将两个节点(game
和ui
)添加到场景中,并在场景调用[self addChild]
时选择要将它们添加到的节点。
稍后,您可以暂停游戏
节点,仍然可以更新UI
SKScene
- SKNode "game" // <-- pause this one
- SKSpriteNode "goodGuy"
- SKSpriteNode "badGuy"
- SKSpriteNode "mehGuy"
- ...
- SKNode "ui"
- SKLabelNode "countdownLabel"
- SKSpriteNode "resumeButton"
- SKSpriteNode "pauseButton"
- ...
SKScene
-SKNode“game”/我更喜欢简单地暂停更新方法的各个部分,而不是暂停整个场景。创建布尔属性:
@property (nonatomic) BOOL runUpdateMethod;
构建更新方法以确定哪些部分暂停:
-(void)update {
if(runUpdateMethod) {
// code to be paused
}
// code not to be paused
}
您可以使用SKAction块运行倒计时并恢复定期更新:
-(void)countdown {
__block SKLabelNode *labelNode0;
SKAction *wait0 = [SKAction waitForDuration:1.0];
SKAction *block0 = [SKAction runBlock:^{
labelNode0 = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
labelNode0.text = @"5";
labelNode0.fontSize = 100;
labelNode0.fontColor = [SKColor redColor];
labelNode0.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
labelNode0.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
labelNode0.position = CGPointMake(self.screenWidth/2, self.screenHeight/2);
labelNode0.zPosition = 955;
labelNode0.alpha = 0.4;
[self addChild:labelNode0];
}];
SKAction *block1 = [SKAction runBlock:^{
labelNode0.text = @"4";
}];
SKAction *block2 = [SKAction runBlock:^{
labelNode0.text = @"3";
}];
SKAction *block3 = [SKAction runBlock:^{
labelNode0.text = @"2";
}];
SKAction *block4 = [SKAction runBlock:^{
labelNode0.text = @"1";
}];
SKAction *block5 = [SKAction runBlock:^{
[labelNode0 removeFromParent];
self.runUpdateMethod = YES;
}];
[self runAction:[SKAction sequence:@[block0, wait0, block1, wait0, block2, wait0, block3, wait0, block4, wait0, block5]]];
}
我没有暂停游戏,而是将SKScene
的speed
属性设置为0,同时将SKPhysicsWorld
的speed
属性设置为0。如果游戏没有暂停,我还必须稍微修改我的update
功能,只执行代码的某些部分
这产生了与暂停整个游戏相同的效果,同时也允许我更新标签的内容。关于将NSTimer与SpriteKit@Whirlwind一起使用时可能出现的问题,在这种情况下这不是问题;这就是我使用NSTimer
而不是SKAction
的原因。我需要一种方法来忽略游戏的暂停状态。我只是说“可能”,让你意识到随之而来的问题。通常将NSTimer与SpriteKit一起使用是一个坏主意。搜索以便了解原因(NSTimer也与内存泄漏有关)。无论如何,要做到这一点,你可以取消暂停的场景,并延迟游戏开始使用SKAction与完成块(或只是使用序列)。。。在该完成块中,更改某些自定义变量的值(建议使用isGamePaused)并在倒计时结束时启动游戏。此外,正确地使计时器无效将避免潜在的泄漏,但SKActions仍然更安全。
-(void)countdown {
__block SKLabelNode *labelNode0;
SKAction *wait0 = [SKAction waitForDuration:1.0];
SKAction *block0 = [SKAction runBlock:^{
labelNode0 = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
labelNode0.text = @"5";
labelNode0.fontSize = 100;
labelNode0.fontColor = [SKColor redColor];
labelNode0.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
labelNode0.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
labelNode0.position = CGPointMake(self.screenWidth/2, self.screenHeight/2);
labelNode0.zPosition = 955;
labelNode0.alpha = 0.4;
[self addChild:labelNode0];
}];
SKAction *block1 = [SKAction runBlock:^{
labelNode0.text = @"4";
}];
SKAction *block2 = [SKAction runBlock:^{
labelNode0.text = @"3";
}];
SKAction *block3 = [SKAction runBlock:^{
labelNode0.text = @"2";
}];
SKAction *block4 = [SKAction runBlock:^{
labelNode0.text = @"1";
}];
SKAction *block5 = [SKAction runBlock:^{
[labelNode0 removeFromParent];
self.runUpdateMethod = YES;
}];
[self runAction:[SKAction sequence:@[block0, wait0, block1, wait0, block2, wait0, block3, wait0, block4, wait0, block5]]];
}