Search code examples
iosswiftobjectsprite-kit2d-games

Converting from an object-creating loop to a runBlock with a wait between object creation


Sorry, very new to swift, and coding in general so this may be a beginner question. I currently have the code below creating arrows around a circle. How can I convert this so that all of the arrows spawn 1 second after the last, until they've all been created? I was told by a user in another thread this would have to be accomplished using a runBlock and an SKAction.sequence but I'm only barely familiar with these. Could I get some help? Thanks! (:

override func didMoveToView(view: SKView) {

 self.spawnArrows()

}

func spawnArrows() {

 for var i = 0; i < 36; i++ {

     let arrow = self.createArrow(specificPointOnCircle(Float(self.frame.size.width), center: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), angle: Float(i * 10)))
     self.addChild(arrow)

 }
}

func specificPointOnCircle(radius:Float, center:CGPoint, angle:Float) -> CGPoint {

let theta = angle * Float(M_PI) / 180
let x = radius * cosf(theta)
let y = radius * sinf(theta)
return CGPoint(x: CGFloat(x) + center.x, y: CGFloat(y) + center.y)

}

func createArrow(position: CGPoint) -> SKSpriteNode {

let arrow = SKSpriteNode(imageNamed: "Arrow.png")
arrow.zPosition = 2
arrow.size = CGSize(width: self.frame.size.width / 2 * 0.12, height: self.frame.size.width * 0.025)
arrow.position = position
return arrow

}

Solution

  • You could update your spawnArrows method like below

    func spawnArrows() {
    
        var list = [SKAction]()
    
        for var i = 0; i < 36; i++ {
            let create = SKAction.runBlock { [unowned self] in 
                let arrow = self.createArrow(self.specificPointOnCircle(Float(self.frame.size.width), center: CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), angle: Float(i * 10)))
                self.addChild(arrow)
            }
            list.append(create)
    
            let wait = SKAction.waitForDuration(1)
            list.append(wait)
        }
    
        let sequence = SKAction.sequence(list)
        self.runAction(sequence)
    }
    

    As you can see now I am using the for loop to create a list of actions.

    1. The first added action does contain the code to create the first arrow
    2. Then there is an action to wait 1 second
    3. Then the action to add the second arrow
    4. And so on...

    After the for loop does end, the list of actions is transformed into a sequence and finally executed.

    Let me know if it does work.