How to implement a SpriteKit timer?

2019-03-15 13:41发布

问题:

I am currently trying to implement a timer for my sprite kit game, but I don't get it working. The initial value of the timer always remains the same.

I am assuming I need to update the label somehow/somewhere, but I don't know HOW and WHERE :? I don't get the point. Any ideas?

Here is my code within my GameScene Class

    let levelTimerLabel = SKLabelNode(fontNamed: "Chalkduster")
var levelTimerValue: Int  = 500

var levelTimer = NSTimer()

func startLevelTimer() {

    levelTimerLabel.fontColor = SKColor.blackColor()
    levelTimerLabel.fontSize = 40
    levelTimerLabel.position = CGPoint(x: size.width/2, y: size.height/2 + 350)
    addChild(levelTimerLabel)

    levelTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("levelCountdown"), userInfo: nil, repeats: true)

    levelTimerLabel.text = String(levelTimerValue)

}

func levelCountdown(){

    levelTimerValue--

}

回答1:

I would stick to SKActions for these kind of tasks in SpriteKit due to fact that NSTimer is not affected by scene's, or view's paused state, so it might lead you into troubles. Or at least, it will require from you to implement a pause feature in order to pause your timers in certain situations, like when user pause the scene, or receive a phone call etc. Read more here about SKAction vs NSTimer vs GCD for time related actions in SpriteKit.

import SpriteKit

class GameScene: SKScene {

var levelTimerLabel = SKLabelNode(fontNamed: "ArialMT")

//Immediately after leveTimerValue variable is set, update label's text
var levelTimerValue: Int = 500 {
    didSet {
        levelTimerLabel.text = "Time left: \(levelTimerValue)"
    }
}

override func didMoveToView(view: SKView) {



levelTimerLabel.fontColor = SKColor.blackColor()
levelTimerLabel.fontSize = 40
levelTimerLabel.position = CGPoint(x: size.width/2, y: size.height/2 + 350)
levelTimerLabel.text = "Time left: \(levelTimerValue)"
addChild(levelTimerLabel)

    let wait = SKAction.waitForDuration(0.5) //change countdown speed here
    let block = SKAction.runBlock({
        [unowned self] in

        if self.levelTimerValue > 0{
            self.levelTimerValue--
        }else{
            self.removeActionForKey("countdown")
        }
    })
    let sequence = SKAction.sequence([wait,block])

    runAction(SKAction.repeatActionForever(sequence), withKey: "countdown")
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    //Stop the countdown action

    if actionForKey("countdown") != nil {removeActionForKey("countdown")}
}
}


回答2:

Sounds like you need to update the label everytime levelTimerValue is changed. The easiest way would be something like this.

func levelCountdown(){
    levelTimerValue--
    levelTimerLabel.text = String(levelTimerValue)
}