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中,不要使用 NSTimer
, performSelector: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