I was programming this simple space game in Swift until I encountered the problem of detecting collisions. After looking around forums, tutorials, etc, I tried to implement
SKPhysicsContactDelegate
and make yourself the physics contact delegate://Physics categories
let enemyCategory: UInt32 = 1 << 1
let bulletCategory: UInt32 = 1 << 2
class GameScene: SKScene, SKPhysicsContactDelegate {
physicsWorld.contactDelegate = self
Assign the categories (usually in didMove(to view:)
:
enemy.physicsBody.catgeoryBitMask = enemyCategory
bullet.physicsBody.catgeoryBitMask = bulletCategory
(Make sure you've created physics bodies for each node)
enemy.physicsBody?.collisionBitMask = 0 // enemy collides with nothing
bullet.physicsBody?.collisionBitMask = 0 // bullet collides with nothing
or even:
for node in [enemy, bullet] {
node.physicsBody?.collisionBitMask = 0 // collides with nothing
}
Set up contacts
bullet.physicsBody?.collisionBitMask = enemyCategory // bullet contacts enemy
Make sure that at least one of the objects involved in each potential contact has the isDynamic
property on its physics body set to true
, or no contact will be generated. It is not necessary for both of the objects to be dynamic.
You should now get didBegin
called when the bullet and the enemy make contact. You could code didBegin
like this:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case bulletCategory | enemyCategory:
print("bullet and enemy have contacted.")
let bulletNode = contact.bodyA.categoryBitMask == bulletCategory ? contact.bodyA.node : contact.bodyB.node
enemyHealth -= 10
bulletNode.removeFromParent
default:
print("Some other contact occurred")
}
}