Astrum Astrum - 5 months ago 33
Swift Question

Removing a node that collides with player sprite

I am trying to remove a node with the name “specialObstacle” in a levelUnit that is contained within a world node when the player collides with it, it succeeds but I have multiple nodes with the name “specialObstacle” in the multiple level units that all get removed as soon as a player collides with one. I’m trying to get the one that the player collides with to only be removed. my code is as follows:

The Removal Code (Which is placed inside the contact code also):

worldNode.enumerateChildNodesWithName("levelUnit"){
node, stop in

let levelUnit:LevelUnit = node as! LevelUnit //cast as an actual LevelUnit class

levelUnit.enumerateChildNodesWithName("specialObstacle"){
node, stop in


node.removeFromParent()

}

}


Obstacle Code: (Which is in its own class called Object: SKnode)

func createSpecialObject() {


objectSprite = SKSpriteNode(imageNamed:imageName)
self.addChild(objectSprite)

objectSprite.physicsBody = SKPhysicsBody(circleOfRadius: objectSprite.size.width / 3)
objectSprite.physicsBody!.categoryBitMask = BodyType.specialObjectDiamond.rawValue
objectSprite.physicsBody!.contactTestBitMask = BodyType.specialObjectDiamond.rawValue

}

objectSprite.physicsBody!.friction = 1
objectSprite.physicsBody!.dynamic = false
objectSprite.physicsBody!.affectedByGravity = false
objectSprite.physicsBody!.restitution = 0.0
objectSprite.physicsBody!.allowsRotation = false

self.zPosition = 400

self.name = "specialObstacle"

self.position = CGPointMake(objectSprite.size.width / 2 , 0)

}


Contact Code:

func didBeginContact(contact: SKPhysicsContact) {

if (contact.bodyA.categoryBitMask == BodyType.player.rawValue && contact.bodyB.categoryBitMask == BodyType.specialObjectCoin.rawValue ) {

**REMOVAL CODE HERE**

numberOfCoins += 1
print("number of Coins collected is \(numberOfCoins)")

}

else if (contact.bodyA.categoryBitMask == BodyType.specialObjectCoin.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue ) {

**REMOVAL CODE HERE**

numberOfCoins += 1
print("number of Coins collected is \(numberOfCoins)")

}
}


I don't really know how to get it to only remove the node that my player collides with instead of all the other obstacles in the level units with the same name as "specialObstacle" being removed with it. Can Someone please provided insight into what am I doing wrong?

Answer

You never want to remove during the didBeginContact phase. You can enter a position where you remove a node that has collided with 2 objects, removes on the first, then on the check second object, your program crashes due to the object not being there. Instead, you need to queue up all nodes that you will delete, and remove them during the didFinishUpdate phase

var nodesToRemove = [SKNode]()

override func didBeginContact() 
{

    if (contact.bodyA.categoryBitMask == BodyType.player.rawValue && contact.bodyB.categoryBitMask == BodyType.specialObjectCoin.rawValue ) 
    {

        **REMOVAL CODE HERE**
        nodesToRemove.append(contact.bodyB.node)
        numberOfCoins += 1
        print("number of Coins collected is \(numberOfCoins)")

    }

     else if (contact.bodyA.categoryBitMask == BodyType.specialObjectCoin.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue  ) 
     {

       **REMOVAL CODE HERE**
        nodesToRemove.append(contact.bodyA.node)
        numberOfCoins += 1
        print("number of Coins collected is \(numberOfCoins)")

    }  
}

override func didFinishUpdate() 
{   
     nodesToRemove.forEach(){$0.removeFromParent()}   
     nodesToRemove = [SKNode]()

}