Jason
Jason

Reputation: 103

Why won't these collisions sense? (Swift SpriteKit)

In my project I am trying to detect a collision between two SKSpriteNodes, but it will not work. Here is my code for the physics category :

struct PhysicsCategory {
static let enemy : UInt32 = 0x1 << 1
static let player : UInt32 = 0x1 << 3
static let neutral : UInt32 = 0x1 << 2
 }

For the neutral, enemy and player bodies

  neutral = SKSpriteNode(imageNamed: "Cave-Bottom")
    neutral.size = CGSize(width: self.frame.width, height: self.frame.height / 8)
    neutral.position = CGPoint(x: 0, y: self.frame.height / -2.5)
    neutral.zPosition = 2
    neutral.physicsBody?.categoryBitMask = PhysicsCategory.neutral
    neutral.physicsBody?.collisionBitMask = PhysicsCategory.player
    neutral.physicsBody?.contactTestBitMask = PhysicsCategory.player
    neutral.physicsBody = SKPhysicsBody.init(rectangleOf:              neutral.size)

    enemy = SKSpriteNode(imageNamed: "spike")
    enemy.size = CGSize(width: 40, height: 40)
    enemy.position = CGPoint(x: 0, y: 0)
    enemy.zPosition = 2
    enemy.physicsBody = SKPhysicsBody.init(rectangleOf: enemy.size)
    enemy.physicsBody?.categoryBitMask = PhysicsCatagory.enemy
    enemy.physicsBody?.collisionBitMask = PhysicsCatagory.player
    enemy.physicsBody?.contactTestBitMask = PhysicsCatagory.player

    player = SKSpriteNode(imageNamed: "bob")
    player.size = CGSize(width: 40, height: 40)
    bob.zPosition = 3
    player.physicsBody?.categoryBitMask = PhysicsCatagory.player
    player.physicsBody?.collisionBitMask = PhysicsCatagory.enemy | PhysicsCatagory.neutral
    player.physicsBody?.contactTestBitMask = PhysicsCatagory.enemy | PhysicsCatagory.neutral
    player.physicsBody = SKPhysicsBody.init(rectangleOf: player.size)

And the code for my ContactHasBegan function:

  func didBegin(_ contact: SKPhysicsContact) {

   print("collided!")

    if (contact.bodyA.categoryBitMask == PhysicsCatagory.enemy && contact.bodyB.categoryBitMask == PhysicsCatagory.player) {
        print("player and enemy!")
    }
    if (contact.bodyB.categoryBitMask == PhysicsCatagory.enemy && contact.bodyA.categoryBitMask == PhysicsCatagory.player) {
        print("player and enemy!")
    }
    if (contact.bodyA.categoryBitMask == PhysicsCatagory.neutral && contact.bodyB.categoryBitMask == PhysicsCatagory.player) {
        print("neutral and player!")    
    }
    if contact.bodyB.categoryBitMask == PhysicsCatagory.neutral && contact.bodyA.categoryBitMask == PhysicsCatagory.player{
        print("neutral and player")
    }          }

For some reason it only detects a collision between the player and enemy and prints "Collided!" and none of the if statements in the didBeginContact function test out positive.

Upvotes: 1

Views: 58

Answers (1)

Steve Ives
Steve Ives

Reputation: 8134

Because player's physicsBody doesn't have it's category and contactTest bit masks set corrcetly.

You've created the player's physicsBody AFTER you tried to set the player's physicsBody's attributes:

player.physicsBody?.categoryBitMask = PhysicsCatagory.player
player.physicsBody?.collisionBitMask = PhysicsCatagory.enemy | PhysicsCatagory.neutral
player.physicsBody?.contactTestBitMask = PhysicsCatagory.enemy | PhysicsCatagory.neutral
player.physicsBody = SKPhysicsBody.init(rectangleOf: player.size)

In the first 3 lines of code, because player.physicsBody is an optional, the rest of the line is ignored, as there is no physicsBody.

So the physics body is created with all properties set to default i.e. it collides with everything and contacts nothing.

You need to move the line :

player.physicsBody = SKPhysicsBody.init(....

to before the code where you set the physics body's attributes:

player.physicsBody = SKPhysicsBody.init(rectangleOf: player.size)
player.physicsBody?.categoryBitMask = PhysicsCatagory.player
player.physicsBody?.collisionBitMask = PhysicsCatagory.enemy | PhysicsCatagory.neutral
player.physicsBody?.contactTestBitMask = PhysicsCatagory.enemy | PhysicsCatagory.neutral

Upvotes: 4

Related Questions