Search code examples
swiftsprite-kitcollision-detectioncollisionbitmask

Swift Sprite kit Collision Bitmask


I was wondering if anyone would be able to offer me some help with using 3 nodes, I understand if I just have 2 nodes E.g. body A and body B but I'm struggling with adding a third body, I hoped it was as simple as body C but that wasn't the case. This is the related code below:

    struct CollisionCategoryBitmask {
    static let Player: UInt32 = 0x00
    static let Enemy1: UInt32 = 0x01
    static let Enemy2: UInt32 = 0x02
}



    func didBeginContact(contact: SKPhysicsContact) {

    var updateHud = false
    _ = (contact.bodyA.node != player) ? contact.bodyA.node : contact.bodyB.node
    updateHud = slowDown(player)
}

This function below is intended to slow the player down when contacting Enemy1

 func slowDown (player: SKNode) -> Bool {

    player.physicsBody?.velocity = CGVector(dx: 0, dy: -50.0)
    return true

}

and this below is intended to get the game to end when contacting Enemy2

 func endGame (player: SKNode) -> Bool {

    endOfGame()
    return true
}

At the moment both functions work, but only one at a time, so when the player contacts either Enemy 1 or 2. I can currently either get the player to slow down or get the game to end by just changing the updateHud = slowDown(player) line. So how can I adjust the code to have the two different outcomes happen when the player touches either Enemy 1 or 2.

Thanks


Solution

  • You are not understanding how didBeginContact works. Basically what is happening is when any 2 nodes make a contact, the first thing that the system will do is make sure that the category and contact bit masks line up to make a valid contact. If it does, then didBeginContact gets called. now inside this function, you have the 2 arbitrary nodes that made contact, called bodyA, and bodyB. What you need to do first, is figure out what bodyA and bodyB are. So the first thing you do, is check the categoryBitMask.

       if(contact.bodyA.categoryBitMask == HERO) then contact.bodyA is a hero
    

    Now that we know what categories these nodes refer to, we can then check what the node actually is. To do this, you can either check the name of the node

      if(contact.bodyA.node.name == "Hero") then bodyA is the hero 
    

    Or compare the node itself

      if(contact.bodyA.node == heroNode) then bodyA is the hero
    

    Now do the same for bodyB.

    You have established at this point what your nodes are, you can proceed with the outcome results that you need based on this information.

    If Hero hits both enemy nodes at the same time, then you need to handle this as well. What is going to happen is 2 calls to didBeginContact will happen, you need to find a way to remember this, and do your contact code in either the didEvaluateActions, or didSimulatePhysicsMethod. I do not remember which of these follows didBeginContact, so you will have to test it out on your own.