24GHz
24GHz

Reputation: 80

Create Array of SKShapeNodes. Swift > Xcode 6

In swift, the code below is called at a certain rate (2 times per second) from didMoveToView(). Every time this function is called, a new circlenode should appear on the screen. But instead of continually adding them, when it tries to add the second one it throws an error : attempted to add sknode which already has a parent. I figured out that you can't make a duplicate node on the same view. With that figured out, I came to the conclusion that I would need to make an array of SKShapeNodes so whenever the function is called, it would take one from the array and add it to the view. When a node has reached the bottom (y = -20) in my case, then it would need to remove the node, and make it available again to use.

So, my question: How to I make an array of SKShapeNodes, so when my function below is called it will take a new node and display it to the view? Also, when nodes exit the view, it will need to make the node available again to use.

let circlenode = SKShapeNode(circleOfRadius: 25) //GLOBAL

func thecircle() {
    circlenode.strokeColor = UIColor.whiteColor()
    circlenode.fillColor = UIColor.redColor()

    let initialx = CGFloat(20) 
    let initialy = CGFloat(1015)

    let initialposition = CGPoint(x: initialx, y: initialy)
    circlenode.position = initialposition


    self.addChild(circlenode)

    let action1 = SKAction.moveTo(CGPoint(x: initialx, y: -20), duration: NSTimeInterval(5)) 
    let action2 = SKAction.removeFromParent()
    circlenode.runAction(SKAction.sequence([action1, action2]))
}

Upvotes: 0

Views: 1772

Answers (1)

Mobile Ben
Mobile Ben

Reputation: 7341

So you're right in that the problem the code above is that an SKNode can only have one parent.

You have 2 approaches you could take.

  1. Create an array of your SKShapeNodes
  2. Create a new SKShapeNode as needed

The former has the constraint that you need to keep tabs on your total amount of circles, else you'll exceed your bounds. If you remove items, this also means accounting for it. The latter has the overhead of generating the SKShapeNode when you need it. More than likely this will not be an issue.

To create the array you'd do something like (option 1):

var circleArray:[SKShapeNode] = [SKShapeNode]() // Property in your class

// Code in your init or wherever else you want, depending on what class this is.
// 10 is just an arbitrary number
for var i=0;i<10;i++ {
    circleArray.append(SKShapeNode(circleOfRadius: 25))
}

When you want to add it in your thecircle, where you were calling self.addChild(circlenode) something like:

if numCircles < circleArray.count {
    SKShapeNode *circlenode = circleArray[numCircles]

    // Do other initialization here

    self.addChild(circlenode)
    numCircles++
}

Or you can do (option 2):

SKShapeNode *circlenode = SKShapeNode(circleOfRadius: 25)

// Do other initialization here

self.addChild(circle node)

I'd probably do option 2 in order to not have to deal with any of the management of number of outstanding circles in the array. This is particularly important if you ever remove circles and want to recycle them.

Upvotes: 2

Related Questions