Search code examples
iosswiftsprite-kitcollision-detection

Single collisions being detected multiple times


I've read similar questions posted here, but none of them fully address my problem. I've only been working with iOS for a few months.

My collisions are working 90% of the time, but occasionally I'm getting collisions with same object. This should never happen because one of the 2 objects should explode.

Sometimes this leads to fatal crashes, seemingly because it tries to run the subsequent code after its already been executed.

Basically when the ship has a shield I want the asteroid to explode rather than the ship. I have put in the "if bonus == 0" statement to accomplish this.

I've posted the relevant code, if you need more, please let me know.

Have I over complicated the code? Or should I be taking another approach?

enum PhysicsCategory : UInt32 {
    case None = 0
    case objectGroup = 1
    case birdGroup = 2
    case shieldGroup = 4
    case gapGroup = 8
    case boundaryGroup = 16
    case bonusGroup = 32
}

....

    func didBeginContact(contact: SKPhysicsContact) {
  if bonus == 0 {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
        switch contactMask {
        ....
        case PhysicsCategory.birdGroup.rawValue | PhysicsCategory.objectGroup.rawValue:
            if contact.bodyA.categoryBitMask == PhysicsCategory.birdGroup.rawValue {
                gameOverActions()
            } else if contact.bodyB.categoryBitMask == PhysicsCategory.birdGroup.rawValue {
                gameOverActions()
            }
        default:
            fatalError("other collision: \(contactMask)")
        }
   } else if bonus > 0 {
        println("Bonus > 0")
        let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
        switch contactMask {
        ....
        case PhysicsCategory.birdGroup.rawValue | PhysicsCategory.objectGroup.rawValue:
            if contact.bodyA.categoryBitMask == PhysicsCategory.birdGroup.rawValue {
                let secondBody = contact.bodyB.node
                let asteroidExplosionNode = secondBody?.position
                //asteroidExplosion()
                let asteroidExplosionEmitter3 = SKEmitterNode(fileNamed: "explosionSmoke.sks")
                asteroidExplosionEmitter3.position = asteroidExplosionNode!
                asteroidExplosionEmitter3.name = "asteroidExplosionEmitter3"
                asteroidExplosionEmitter3.zPosition = 25
                asteroidExplosionEmitter3.targetNode = self
                movingObjects.addChild(asteroidExplosionEmitter3)
                secondBody?.removeFromParent()
                bonus--
                bonusUsed++
                bonusIndicator.text = "x\(bonus)"
                bonusIndicatorShadow.text = "x\(bonus)"
                if bonus >= 1 {
                    shieldAnimate()
                } else if bonus == 0 {
                    shield.removeFromParent()
                }
            } else if contact.bodyB.categoryBitMask == PhysicsCategory.birdGroup.rawValue {
                let secondBody = contact.bodyA.node
                let asteroidExplosionNode = secondBody?.position
                //asteroidExplosion()
                let asteroidExplosionEmitter3 = SKEmitterNode(fileNamed: "explosionSmoke.sks")
                asteroidExplosionEmitter3.position = asteroidExplosionNode!
                asteroidExplosionEmitter3.name = "asteroidExplosionEmitter3"
                asteroidExplosionEmitter3.zPosition = 25
                asteroidExplosionEmitter3.targetNode = self
                movingObjects.addChild(asteroidExplosionEmitter3)
                secondBody?.removeFromParent()
                bonus--
                bonusUsed++
                bonusIndicator.text = "x\(bonus)"
                bonusIndicatorShadow.text = "x\(bonus)"
                if bonus >= 1 {
                    shieldAnimate()
                } else if bonus == 0 {
                    shield.removeFromParent()
                }
            }
        default:
            fatalError("other collision: \(contactMask)")
        }
    }
}

Solution

  • Since you are removing the node on collision you can check if the parent is nil, before executing the rest of the code.

    let secondBody = contact.bodyB.node
    if secondBody?.parent != nil {
        // Asteroid explosion and bonus code.
    }