SpriteKit – 创build一个计时器

我如何创build一个计时器,每隔两秒钟触发一次,将屏幕上的HUD上的分数递增1? 这是我对HUD的代码:

@implementation MyScene { int counter; BOOL updateLabel; SKLabelNode *counterLabel; } -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { counter = 0; updateLabel = false; counterLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"]; counterLabel.name = @"myCounterLabel"; counterLabel.text = @"0"; counterLabel.fontSize = 20; counterLabel.fontColor = [SKColor yellowColor]; counterLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter; counterLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeBottom; counterLabel.position = CGPointMake(50,50); // change x,y to location you want counterLabel.zPosition = 900; [self addChild: counterLabel]; } } 

在Sprite Kit中,不要使用 NSTimerperformSelector:afterDelay:或Grand Central Dispatch(GCD,即任何dispatch_...方法),因为这些计时方法忽略节点的场景或视图的paused状态。 而且你不知道游戏循环中的哪一点会被执行,这可能会导致各种问题,这取决于你的代码实际上做了什么。

在Sprite Kit中执行基于时间的事件的唯一两种方法是使用SKScene update:方法并使用传入的currentTime参数来跟踪时间。

或者更常见的是,您只需使用一个以等待操作开始的操作序列:

 id wait = [SKAction waitForDuration:2.5]; id run = [SKAction runBlock:^{ // your code here ... }]; [node runAction:[SKAction sequence:@[wait, run]]]; 

并重复运行代码:

 [node runAction:[SKAction repeatActionForever:[SKAction sequence:@[wait, run]]]]; 

或者,您也可以使用performSelector:onTarget:而不是runBlock:或者使用customActionWithDuration:actionBlock:如果您需要模仿SKScene update:方法,并且不知道如何将其转发到节点或转发将不方便。

有关详细信息,请参阅SKAction参考 。


更新:使用Swift的代码示例

Swift 3

 let wait = SKAction.wait(forDuration:2.5) let action = SKAction.run { // your code here ... } run(SKAction.sequence([wait,action])) 

Swift 2

 let wait = SKAction.waitForDuration(2.5) let run = SKAction.runBlock { // your code here ... } runAction(SKAction.sequence([wait, run])) 

试着重复运行代码:

 runAction(SKAction.repeatActionForever(SKAction.sequence([wait, run]))) 

在Swift中可用:

 var timescore = Int() var actionwait = SKAction.waitForDuration(0.5) var timesecond = Int() var actionrun = SKAction.runBlock({ timescore++ timesecond++ if timesecond == 60 {timesecond = 0} scoreLabel.text = "Score Time: \(timescore/60):\(timesecond)" }) scoreLabel.runAction(SKAction.repeatActionForever(SKAction.sequence([actionwait,actionrun]))) 

我已经采取了上面的快速示例,并添加了时钟的前导零。

  func updateClock() { var leadingZero = "" var leadingZeroMin = "" var timeMin = Int() var actionwait = SKAction.waitForDuration(1.0) var timesecond = Int() var actionrun = SKAction.runBlock({ timeMin++ timesecond++ if timesecond == 60 {timesecond = 0} if timeMin / 60 <= 9 { leadingZeroMin = "0" } else { leadingZeroMin = "" } if timesecond <= 9 { leadingZero = "0" } else { leadingZero = "" } self.flyTimeText.text = "Flight Time [ \(leadingZeroMin)\(timeMin/60) : \(leadingZero)\(timesecond) ]" }) self.flyTimeText.runAction(SKAction.repeatActionForever(SKAction.sequence([actionwait,actionrun]))) } 

下面的代码创build一个新的线程并等待2秒钟,然后在主线程上做一些事情:

 BOOL continueIncrementingScore = YES; dispatch_async(dispatch_queue_create("timer", NULL);, ^{ while(continueIncrementingScore) { [NSThread sleepForTimeInterval:2]; dispatch_async(dispatch_get_main_queue(), ^{ // this is performed on the main thread - increment score here }); } }); 

每当你想停止它 – 只需将continueIncrementingScore设置为NO