0
votes

Alright so I'm building a sprite kit game where I need to delay an enemy spawn func repeatedly.

I've managed to generate random Doubles using this function:

func randomDelay()->Double {
        var randLower : UInt32 = 1
        var randUpper : UInt32 = 50
        var randDelayTime = arc4random_uniform(randUpper - randLower) + randLower
        var randDelayTimer = Double(randDelayTime) / 10
        //var randDelay = randDelayTimer * Double(NSEC_PER_SEC)
        //var newTime = dispatch_time(DISPATCH_TIME_NOW, Int64(randDelay))

        println(randDelayTimer)

        return randDelayTimer
    }

I know this works because I printed randDelayTimer out several times and it does in fact generate random Doubles.

Here is where I try to spawn my enemies after the random delay repeatedly:

runAction(SKAction.repeatActionForever(
            SKAction.sequence([
                SKAction.waitForDuration(NSTimeInterval(randomDelay())),
                SKAction.runBlock({self.spawnEnemy1()})))

This works, but only the first time it is run. Whatever random Double is generated by randomDelay() the FIRST TIME the sequence is cycled through is applied to every enemy that is spawned after that. For example if when the game is run, randomDelay() = 3.5, a 3.5 sec delay is repeated forever.

I know that randomDelay() is only being run that first time also because nothing is printed to the console after the first time.

How can I fix this?

1

1 Answers

2
votes

You should use the following static method on SKAction:

class func waitForDuration(_ sec: NSTimeInterval,
                 withRange durationRange: NSTimeInterval) -> SKAction

From the SKAction documentation:

Each time the action is executed, the action computes a new random value for the duration. The duration may vary in either direction by up to half of the value of the durationRange parameter.

In your case, with a minimum duration of 1 second and a maximum duration of 50 seconds, you'd use:

// A mean wait of 25.5 seconds. The wait can vary by 24.5 seconds above and below the mean.
let waitAction = SKAction.waitForDuration(25.5, withRange: 49)

It's a little inconvenient to manually calculate the mean and range from the maximum and minimum waiting time, so you could use an extension on SKAction to do the work for you:

extension SKAction {
    static func waitForDuration(minimum min: NSTimeInterval, maximum max: NSTimeInterval) -> SKAction {
        return SKAction.waitForDuration((max + min) / 2, withRange: abs(max - min))
    }
}

Usage:

let waitAction = SKAction.waitForDuration(minimum: 1, maximum: 50)