Properly detect completion of simultaneous SKActions

148 Views Asked by At

I'm pretty new to native programming on iOS. I have a function in my Game Scene which moves an array of SKSpriteNodes. After each move is completed, its node should be removed from the scene. The function also has a completion function which should be called AFTER removing all the SKNodes. My question is, if there is a cleaner way to just add a little extra time to the duration of the the moveAction until the completion function is called (see below). I also played around with action sequences, but couldn't come up with a working solution...

Every help will be appreciated!

func animateNodes(nodes: Array<SKSpriteNode>, completion:() -> ()) {
    let duration = NSTimeInterval(0.5)
    for (_, node) in nodes.enumerate() {
        let point = CGPointMake(node.position.x - 80, node.position.y + 80)
        let moveAction = SKAction.moveTo(point, duration: duration)
        let fadeOutAction = SKAction.fadeAlphaTo(0, duration: duration)
        node.runAction(SKAction.group([moveAction, fadeOutAction]), completion: {
            node.removeFromParent()
        })
    }
    runAction(SKAction.waitForDuration(duration + 0.1), completion:completion)
}
1

There are 1 best solutions below

1
On BEST ANSWER

Add a variable count that keeps track of how many nodes are currently alive. In each node's completion, decrement that count and check to see if it was the last one (count == 0) and run the completion action if it is:

func animateNodes(nodes: Array<SKSpriteNode>, completion:() -> ()) {
    var count = nodes.count
    let duration = NSTimeInterval(0.5)
    for (_, node) in nodes.enumerate() {
        let point = CGPointMake(node.position.x - 80, node.position.y + 80)
        let moveAction = SKAction.moveTo(point, duration: duration)
        let fadeOutAction = SKAction.fadeAlphaTo(0, duration: duration)
        node.runAction(SKAction.group([moveAction, fadeOutAction]), completion: {
            node.removeFromParent()
            count--
            if count == 0 {
                completion()
            }
        })
    }
}

I haven't compiled or run this, so there may be errors, but this should work