Astrum
Astrum

Reputation: 375

Changing the time interval of a Timer in swift spritekit

So, I have this timer that is setup to run a specific function (which are both shown below) on a time interval variable called 'frequency' when I try and change the timeinterval variable frequency to a lower number based on the score number it doesn't seem to change the rate at which it fires it just seems to fire at the same time even if the frequency is changed to a lower number

override func didMove(to view: SKView) {

   Timer.scheduledTimer(timeInterval: frequency, target: self, selector: #selector(GameScene.spawnFallingOjects), userInfo: nil, repeats: true)

}


func spawnFallingOjects() {

    if (GameState.current == .playing || GameState.current == .blackstone) {

        guard usingThirdEye == false else { return }

        let scoreLabel = childNode(withName: "scoreLabel") as! Score
        let lane = [-100, -50 , 0, 50, 100]
        let duration = 3.0

        switch scoreLabel.number {

                case 0...50:
                    frequency = 6.0
                    print("frequency has changed: \(frequency)")
                case 51...100:
                    frequency = 4.5
                    print("frequency has changed: \(frequency)")
                case 101...200000:
                    frequency = 1.1
                    print("frequency has changed: \(frequency)")

                default:
                    return
        }

        let randomX = lane[Int(arc4random_uniform(UInt32(lane.count)))]

        let object:Object = Object()
        object.createFallingObject()
        object.position = CGPoint(x: CGFloat(randomX), y: self.size.height)
        object.zPosition = 20000
        addChild(object)


        let action = SKAction.moveTo(y: -450, duration: duration)
        object.run(SKAction.repeatForever(action))

     }

  }

How do I make the timer fire faster when the frequency number changes to a lower number? should I recreate the timer at the end of the function?

Upvotes: 0

Views: 1595

Answers (2)

Knight0fDragon
Knight0fDragon

Reputation: 16837

You should actually avoid using Timer, Sprite kit has its own time functionality, and Timer does not work well with it and is a real pain to manage.

Instead, use SKAction's to wait and fire:

let spawnNode = SKNode()
override func didMove(to view: SKView) {
   let wait = SKAction.wait(forDuration:frequency)
   let spawn = SKAction.run(spawnFallingObjects)
   spawnNode.run(SKAction.repeatForever(SKAction.sequence([wait,spawn])))
   addChild(spawnNode)
}

Then to make it faster, just do:

switch scoreLabel.number {

            case 0...50:
                spawnNode.speed = 1
                print("speed has changed: \(spawnNode.speed)")

            case 51...100:
                spawnNode.speed = 1.5
                print("speed has changed: \(spawnNode.speed)")

            case 101...200000:
                spawnNode.speed = 2
                print("speed has changed: \(spawnNode.speed)")

            default:
                return
    }

Upvotes: 2

OOPer
OOPer

Reputation: 47896

The timeInterval property of Timer is a readonly property. (And your code is not trying to write a new frequency into the property...)

should I recreate the timer at the end of the function?

Nearly yes. Just you have no need to do it at the end.

With changing your method header like this:

func spawnFallingOjects(_ timer: Timer) {

You can access the fired Timer through the parameter timer, so you may need to write something like this just after switch scoreLabel.number {...}:

        if frequency != timer.timeInterval {
            //Invalidate old Timer...
            timer.invalidate()
            //And then allocate new one
            Timer.scheduledTimer(timeInterval: frequency, target: self, selector: #selector(GameScene.spawnFallingOjects), userInfo: nil, repeats: true)
        }

You can modify the fireDate property of an existing Timer (in case which still isValid), but recreating a Timer instance is not a heavy operation (comparing to creating an SKSpriteNode instance), so recreating a new Timer seems to be a little bit easier.

Upvotes: 0

Related Questions