Search code examples
swiftanimationskactionsknode

Running SKActions on Multiple SKNodes in Sequence


I am creating a card game and having trouble having SKActions run in a sequence across multiple SK Objects (Nodes, Textures, Labels, etc.). Any help would be much appreciated! In the example below, I am trying to create a "dealing" motion. Where 1 card gets dealt, some time elapses, then the next card gets dealt. I tried using this, but with 52 cards, it's not exactly the simplest approach.

First, I tried creating an array of SKActions for each card. However, I don't believe I can run the below using one command based on my understanding of the documentation. Each action needs to be run against the specific Sprite Object as opposed to running a whole sequence of actions across multiple Sprite Objects.

let dealAction = SKAction[]()
for card in deck {
    let move = SKAction.... 
    dealAction.append(move)
}
run.SKAction.sequence(dealAction) // This will not work. 

Then I tried this with the hope that the loop would complete each cards block of code before moving on to the next card. However, all the actions run at the same time. Now, I am a bit lost and I don't know exactly how to implement this efficiently. The only thing I could think of was creating a "timingIndex", where .2 seconds gets added to the wait time for each card. So even though they are all running at the same time, the wait time grows for each card. Not sure if this is the best way to approach the problem however and was hoping there was a more elegant solution.

for card in deck {
    let move = SKAction.... 
    let wait = SKAction.wait(forDuration: 1)
    card.run(SKAction.sequence[move, wait])
}

// Possible Solution
let timingIndex = 0.2
for card in deck {
    let move = SKAction.... 
    let wait = SKAction.wait(forDuration: timingIndex)
    card.run(SKAction.sequence[move, wait])
    timingIndex += 0.2
}

import SpriteKit
import UIKit

let screenH = 100
let screenW = 50

class Player {
    var handLocation: CGPoint
    var pile = [Card]()

    init() {
        handLocation = CGPoint(x: 100, y: 583)
    }
}

class Card: SKSpriteNode {

}

struct Game {
    var player1 = Player()
    var player2 = Player()
    var deck = [Card]()

    func dealDeck() {
        for card in deck {
            player1.pile.append(card) // This would theoretically loop through both players
            card.position = CGPoint(x: screenW / 2, y: screenH / 2)
            let move = SKAction.move(to: player1.handLocation, duration: 1)
            card.run(move)
        }
    }

}

Solution

  • This worked! Worried about the use of this overall and if there exists a better solution still, but for the time being, this worked.

    // Possible Solution
    let timingIndex = 0.2
    for card in deck {
        let move = SKAction.... 
        let wait = SKAction.wait(forDuration: timingIndex)
        card.run(SKAction.sequence[move, wait])
        timingIndex += 0.2
    }