2

Edit no.2 , Ok, I think I have boiled this right down to the point now. I have used all your advice, and tested with breakpoints, so thank you.

The last bit I need to do, is run this wait action.

if (timerStarted == YES) {

    [countDown runAction:[SKAction waitForDuration:1]];
    if (countDownInt > 0) {
    countDown.text = [NSString stringWithFormat:@"%i", countDownInt];
    countDownInt = countDownInt - 1.0;
    [self Timer];

    }else{
        countDown.text = [NSString stringWithFormat:@"Time Up!"];
    }

The runAction: section doesn't seem to work. I am guessing this is because I have selected the wrong node to put in the place of the (SKLabelNode "countDown"). Which node could I use to run this code?

Thank you everyone who has helped so far

  • 1
    What's wrong? Well as long as timeLeft is > 0 you create an entirely new label node *every frame* without removing the old one(s). After one second you end up with around 60 labels. You should have one label, and update only that label's text property. – CodeSmile Nov 29 '14 at 15:22

2 Answers2

4

Here's an example of how to implement a countdown timer in SpriteKit.

First, declare a method that creates 1) a label node to display the time left and 2) the appropriate actions to update the label, wait for one second, and rinse/lather/repeat

- (void) createTimerWithDuration:(NSInteger)seconds position:(CGPoint)position andSize:(CGFloat)size {
    // Allocate/initialize the label node
    countDown = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    countDown.position = position;
    countDown.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
    countDown.fontSize = size;
    [self addChild: countDown];
    // Initialize the countdown variable
    countDownInt = seconds;
    // Define the actions
    SKAction *updateLabel = [SKAction runBlock:^{
        countDown.text = [NSString stringWithFormat:@"Time Left: %ld", countDownInt];
        --countDownInt;
    }];
    SKAction *wait = [SKAction waitForDuration:1.0];
    // Create a combined action
    SKAction *updateLabelAndWait = [SKAction sequence:@[updateLabel, wait]];
    // Run action "seconds" number of times and then set the label to indicate
    // the countdown has ended
    [self runAction:[SKAction repeatAction:updateLabelAndWait count:seconds] completion:^{
        countDown.text = @"Time's Up";
    }];
}

and then call the method with the duration (in seconds) and the label's position/size.

CGPoint location = CGPointMake (CGRectGetMidX(self.view.frame),CGRectGetMidY(self.view.frame));
[self createTimerWithDuration:20 position:location andSize:24.0];
0x141E
  • 12,613
  • 2
  • 41
  • 54
1

I would not use the update method. Use SKActions to make a timer. For an example

id wait = [SKAction waitForDuration:1];
id run = [SKAction runBlock:^{
    // After a second this is called
}];
[node runAction:[SKAction sequence:@[wait, run]]];

Even though this will only run once, you can always embed this in an SKActionRepeatForever if you want to be called every second or whatever time interval. Source: SpriteKit - Creating a timer

Community
  • 1
  • 1
SierraMike
  • 1,539
  • 1
  • 11
  • 18
  • I am not sure how I can implement this with the code above –  Nov 29 '14 at 15:02
  • So where ever you want to start your timer. Create an action that waits (with whatever time interval you want). Then the second action is what you want to do once you have waited x amount of time. You could place your setting of the countdown label code inside that run block and decrease an int somewhere that holds the current time. Then make another action that repeats those actions forever. Have a check inside the same code block as your label that says if currentTime <= 0, then stop the actions. – SierraMike Nov 29 '14 at 15:05
  • Wait sorry for bothering you, what object should I put as the node? –  Nov 29 '14 at 15:38
  • The scene you are currently in. – SierraMike Nov 29 '14 at 15:59