OK - I’m sure this is a duplicate and that Whirlwind or KnightOfDragons has posted a solution, but I can’t find it.
I’m writing a clone of Space Invader in Swift using Sprite-Kit. The problem I have is that when a invader bomb hits my ship, the code sometimes registers 2 or 3 collisions, immediately ending the game. Here’s the section of ‘didBeginContact’ that handles the bomb/ship collision:
case category.bomb.rawValue | category.ship.rawValue:
print("Bomb hit ship!")
let bomb = contact.bodyA.categoryBitMask == category.bomb.rawValue ? contact.bodyA.node : contact.bodyB.node
bomb?.physicsBody?.contactTestBitMask = 0 // Seems to prevent multiple contacts with same bomb
ship.physicsBody!.contactTestBitMask = 0 // We'll reset this after the death animation
bomb?.removeAllActions()
ship.removeAllActions()
bomb?.removeFromParent()
ships -= 1
if ships == 0 { endScene(won: false, withMessage: "A bomb got you!") }
and when I run the game I see:
Bomb hit ship!
2 ships left.
after 1 bomb hit (this is correct)
Bomb hit ship!
1 ships left.
Bomb hit ship!
0 ships left.
after a 2nd bomb hit (which is wrong).
I never have the contact NOT being registered, and sometimes (50%?) it works perfectly. Other times I’ve seen myself with -4 ships! I’m sure it’s something obvious/fundamental that I’m getting wrong though.
My comments about setting the contactTestBitMask to 0 for the bomb and the ship are obviously wrong. I know this shouldn’t be necessary, as I remove the bomb when the contact occurs, so it shouldn’t occur again.
How can I guarantee that the contact is only processed once?
================================
Update: I added 2 print statements to provide more debugging information:
print("bodyA is \(contact.bodyA.node!.name)")
print("bodyB is \(contact.bodyB.node!.name)")
This is after the let bomb = contact.bodyA.category... statement and now I get:
Bomb hit ship!
bodyA is Optional("bomb")
bodyB is Optional("playerShip")
1 ships left.
after 1 bomb hit, and :
Bomb hit ship!
fatal error: unexpectedly found nil while unwrapping an Optional value
after a 2nd bomb hit. So after the second collision, bodyA is nil, so I don't see why Sprite-Kit has actually registered a collision?
Any ideas?