Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpriteKit - Creating a timer

How can I create a timer that fires every two seconds that will increment the score by one on a HUD I have on my screen? This is the code I have for the 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];     } } 
like image 574
user3578149 Avatar asked Jun 01 '14 08:06

user3578149


1 Answers

In Sprite Kit do not use NSTimer, performSelector:afterDelay: or Grand Central Dispatch (GCD, ie any dispatch_... method) because these timing methods ignore a node's, scene's or the view's paused state. Moreover you do not know at which point in the game loop they are executed which can cause a variety of issues depending on what your code actually does.

The only two sanctioned ways to perform something time-based in Sprite Kit is to either use the SKScene update: method and using the passed-in currentTime parameter to keep track of time.

Or more commonly you would just use an action sequence that starts with a wait action:

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

And to run the code repeatedly:

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

Alternatively you can also use performSelector:onTarget: instead of runBlock: or perhaps use a customActionWithDuration:actionBlock: if you need to mimick the SKScene update: method and don't know how to forward it to the node or where forwarding would be inconvenient.

See SKAction reference for details.


UPDATE: Code examples using Swift

Swift 5

 run(SKAction.repeatForever(SKAction.sequence([      SKAction.run( /*code block or a func name to call*/ ),      SKAction.wait(forDuration: 2.5)      ]))) 

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])) 

And to run the code repeatedly:

runAction(SKAction.repeatActionForever(SKAction.sequence([wait, run]))) 
like image 112
LearnCocos2D Avatar answered Sep 22 '22 23:09

LearnCocos2D