I want to group animations for multiple nodes. First I tried the solution above, combining all the actions in one, using runAction(_:onChildWithName:) to indicate which actions should be performed using node.
Unfortunately, there were problems with synchronization, because in the case of runAction(_:onChildWithName:) duration for SKAction instantaneous. So I have to find another way to group animations for several nodes in one operation.
Then I changed the code above by adding an array of tuples (SKNode,SKActions) .
The modified code presented here adds a function to start an operation for several nodes, each of which has its own actions.
For each action, a node executes its own block inside it, added to the operation using addExecutionBlock . When the action is completed, a completion block is executed that calls checkCompletion() to join them all. When all actions are completed, the operation will be marked as finished .
class ActionOperation : NSOperation { let _theActions:[(SKNode,SKAction)] // The list of tuples : // - SKNode The sprite node on which an action is to be performed // - SKAction The action to perform on the sprite node var _finished = false // Our read-write mirror of the super read-only finished property var _executing = false // Our read-write mirror of the super read-only executing property var _numberOfOperationsFinished = 0 // The number of finished operations override var executing:Bool { get { return _executing } set { willChangeValueForKey("isExecuting") _executing = newValue didChangeValueForKey("isExecuting") } } override var finished:Bool { get { return _finished } set { willChangeValueForKey("isFinished") _finished = newValue didChangeValueForKey("isFinished") } } // Initialisation with one action for one node // // For backwards compatibility // init(node:SKNode, action:SKAction) { _theActions = [(node,action)] super.init() } init (theActions:[(SKNode,SKAction)]) { _theActions = theActions super.init() } func checkCompletion() { _numberOfOperationsFinished++ if _numberOfOperationsFinished == _theActions.count { self.executing = false self.finished = true } } override func start() { if cancelled { finished = true return } executing = true _numberOfOperationsFinished = 0 var operation = NSBlockOperation() for (node,action) in _theActions { operation.addExecutionBlock({ node.runAction(action,completion:{ self.checkCompletion() }) }) } NSOperationQueue.mainQueue().addOperation(operation) } }
source share