Reputation: 487
I want to do an infinite loop with my SKSpriteNodes
/ SKNode
, but the loop doesn't work correctly.
To give you an Idea of my game, there are 2 long objectives, spawned next to each other on the bottom side of screen and with a gap inbetween them. Between both of the Objectives is the contactNode, which determines if the Player passed through the walls or not, to score a point. The Objectives spawn infinitely.
After the game starts, it calls the Function addObjectives
. After a small delay, I want to call the same Function again, with new Nodes, while the old spawned one are still there and moving to the top with the new ones.
But with my Code, after the Nodes reach the point given in the Update:
, they stop and the scene calls the Function again and the new Nodes move upon to the point and stop again.An infinite loop.
I don't want to stop the Nodes after addObjectives
is called again, they should spawn from the bottom of the screen and move to the top, and then being removed, while there will always come new Objectives from the bottom.
How can I do that?
...
var contactNode = SKNode()
...
func addObjectives(){
O1 = SKSpriteNode(imageNamed: "Objective.png")
O1.size = CGSize(width: self.frame.size.width / 1.3, height: self.frame.size.height / 17)
O1.position = positions[randomPosition()]
O1.zPosition = 3
...
self.addChild(O1)
O2 = SKSpriteNode(imageNamed: "Objective.png")
O2.size = CGSize(width: self.frame.size.width / 1.3, height: self.frame.size.height / 17)
O2.position = CGPoint(x: O1.position.x + CGFloat(Gap), y: O1.position.y)
O2.zPosition = 3
...
self.addChild(O2)
contactNode.physicsBody = SKPhysicsBody(rectangleOfSize:CGSize(width: CGFloat(Gap) / 2, height: O1.size.height))
contactNode.position = CGPoint(x: O1.position.x + (CGFloat(Gap) / 2), y: O1.position.y - 20)
contactNode.physicsBody?.dynamic = false
contactNode.physicsBody?.categoryBitMask = ScoreCategory
contactNode.physicsBody?.contactTestBitMask = PlayerCategory
contactNode.physicsBody?.collisionBitMask = 0
self.addChild(contactNode)
}
//Called in the Update Method
func ScrollingMauer(){
O1.position = CGPointMake(O1.position.x, O1.position.y + Speed)
O2.position = CGPointMake(O2.position.x, O2.position.y + Speed)
contactNode.position = CGPointMake(contactNode.position.x, contactNode.position.y + Speed)
if(O1.position.y > self.frame.size.height + O1.size.height)
{
O1.removeFromParent()
}
if(O2.position.y > self.frame.size.height + O2.size.height)
{
O2.removeFromParent()
}
if(contactNode.position.y > self.frame.size.height + Mauer2.size.height)
{
contactNode.removeFromParent()
}
// Here the Function is called again, but the previous spawned
Objectives stop and the new Objectives come from the bottom to the top.
if(O1.position.y > self.frame.size.height / 3)
{
self.addObjectives()
}
}
Upvotes: 2
Views: 274
Reputation: 13713
You get the error since contactNode
has already been added to the scene so adding it again will produce this error since contactNode
already has a parent.
You could use a boolean flag indicating if the node was already added and add it only once:
contactNode.physicsBody = SKPhysicsBody(rectangleOfSize:CGSize(width: CGFloat(Gap) / 2, height: O1.size.height))
contactNode.position = CGPoint(x: O1.position.x + (CGFloat(Gap) / 2), y: O1.position.y - 20)
contactNode.physicsBody?.dynamic = false
contactNode.physicsBody?.categoryBitMask = ScoreCategory
contactNode.physicsBody?.contactTestBitMask = PlayerCategory
contactNode.physicsBody?.collisionBitMask = 0
if !self.contactNodeAdded {
self.addChild(contactNode)
self.contactNodeAdded = true
}
and in your ScrollingMauer
method:
if(contactNode.position.y > self.frame.size.height + Mauer2.size.height)
{
contactNode.removeFromParent()
self.contactNodeAdded = false
}
(You could also search the node by name but that will be less efficient, especially when called on each frame update)
EDIT: If you want a new instance for each contact node create one:
contactNode = SKNode()
// set physics body etc..
contactNodesArray.append(contactNode)
To keep track of these instances (for removing them later) store them in an array and check each instance of the array as you do in the remove contact node logic:
let nodesToRemoveArray: Array<Int> = Array();
for (index, node) in enumerate(contactNodesArray) {
if(node.position.y > self.frame.size.height + Mauer2.size.height)
{
node.removeFromParent()
nodesToRemoveArray.append(index);
}
}
for indexToRemove in nodesToRemoveArray {
contactNodesArray.removeATIndex(indexToRemove)
}
Upvotes: 1