Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to loop a dynamically delayed sequence of SKActions

I need to run an unknown amount (from an Array of Dictionaries) of SKAction sequences that are dynamically created and offset in a loop using a delay that increases as I go through the loop. printed output of the loop should appear in the following order

show line 5
hiding everything
show line 6
hiding everything
show line 2
hiding everything

to obtain this functionality I use this code

func display(winningLines: [Int : AnyObject]) {

    var delay = 0.0
    var actions = [SKAction]()

    let hideAction = SKAction.run {
        print("hiding everything")
    }

    for winningLine in winningLines {

        let displayAction = SKAction.run {
            print("line \(winningLine.key)")
        }

        let wait = SKAction.wait(forDuration: delay)            
        var action: SKAction!

        //repeatForever = true
        if !repeatForever {
             action = SKAction.sequence([wait, displayAction, SKAction.wait(forDuration: 1.0), hideAction])
        }
        else {
            let seq = SKAction.sequence([wait, displayAction, SKAction.wait(forDuration: 1.0), hideAction])
            action = SKAction.repeatForever(seq)
        }
        self.run(action)

        delay += 1.0
    }
}

If the sequence only needs to occur once than it outputs as expected, however there are times that I need the sequence to just keep repeating forever (until the user stops the action). Putting a repeat forever around the action doesn't work because it repeats each individual sequence and messes up the order. The first sequence will repeat every 1 second, the second sequence will repeat every 2 seconds...etc.

Any suggestions on how to get this to loop properly forever?

line 5
hiding everything
line 5
line 6
hiding everything
line 5
hiding everything
line 2
hiding everything
line 5
line 6
hiding everything
hiding everything
line 5
hiding everything
hiding everything
line 5
line 6
line 2
hiding everything
line 5
hiding everything
hiding everything

I've also tried appending the actions to an Array of SKActions and looping through them at the end but it didn't work

var actions = [SKAction]()

...

actions.append(action)

for action in actions {
    self.run(action)
}
like image 472
Ron Myschuk Avatar asked Apr 05 '17 17:04

Ron Myschuk


1 Answers

If your only concern is to repeat forever, the unknown amount of sequences, you can do the following:

  • create all required sequences
  • put them in another sequence
  • loop that forever

So for example, this code will create four boxes, and will apply fade in/out (displayAction/hideAction from your code) sequentially to every box, and will repeat that forever:

import SpriteKit

class GameScene: SKScene {

var boxes:[SKSpriteNode] = []

override func didMove(to view: SKView) {

    let distance:CGFloat = 10

    for i in 0...3 {

        let box = SKSpriteNode(color: .purple, size: CGSize(width: 50, height: 50))
        box.name = String(i) //name == index
        box.position.x = CGFloat(i) * (box.size.width + distance)
        box.alpha = 0.0
        addChild(box)
        boxes.append(box)

    }
}

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

    var actions:[SKAction] = []

    let action = SKAction.sequence([

        SKAction.fadeIn(withDuration: TimeInterval(1)),
        SKAction.fadeOut(withDuration: 0),
    ])

    for index in 0...boxes.count {

        let sequence = SKAction.sequence([
            SKAction.run(action, onChildWithName: String(index)),
            SKAction.wait(forDuration: 1)
        ])

        actions.append(sequence)

    }

    self.run(SKAction.repeatForever(SKAction.sequence(actions)))
}
}
like image 159
Whirlwind Avatar answered Nov 01 '22 21:11

Whirlwind