0
votes

So I am creating a game and I just want to detect a collision between the player node and a bullet fired by an enemy. So I have set the proper parameters and the categoryBitMask and the contactTestBitMask for each of the player and bullets.

By implementing the didBegin and didEnd functions I want to execute some code when the collision begins and ends. The problem is that when I build and run the project, the physics subsystem moves the bullet around the player instead of though the player. This is because the isDynamic property is set too true for either the player, bullet, or both. Obviously, the first thing to try is to set the isDynamic property to false; however, when I do this the is no callback when a collision occurs, and the didBegin / didEnd function are not executed.

Does anyone have any ideas on how to fix this?

The code for the set up of the player and bullet physics bodies; as well as the didBegin function is below for your reference

    playerNode!.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: playerNode!.size.width/2, height: playerNode!.size.height/2))  //sets the physics body for the player
    playerNode!.physicsBody!.isDynamic = false                                                                                        //we dont want the physics to be simulated by the subsystem
    playerNode!.physicsBody!.affectedByGravity = false
    playerNode!.physicsBody!.pinned = false
    playerNode!.physicsBody!.allowsRotation = false
    playerNode!.physicsBody!.categoryBitMask = PhysicsCategory.Player
    playerNode!.physicsBody!.contactTestBitMask = PhysicsCategory.Bullet

    self.bullet?.physicsBody = SKPhysicsBody(circleOfRadius: bullet!.size.width * 0.5)
    self.bullet?.physicsBody?.isDynamic = true
    self.bullet?.physicsBody?.pinned = false
    self.bullet?.physicsBody?.allowsRotation = false
    self.bullet?.physicsBody?.affectedByGravity = false
    self.bullet?.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
    self.bullet?.physicsBody?.contactTestBitMask = PhysicsCategory.Player

func didBegin(_ contact: SKPhysicsContact) {
    let collision = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    if collision == PhysicsCategory.Player | PhysicsCategory.Bullet {
        print("There was a collision with the player and a bullet")
    }
}

//Defines the physics category for the game
struct PhysicsCategory {
    static let None: UInt32   = 0
    static let Player: UInt32 = 0b1
    static let Bullet: UInt32 = 0b10
}
1

1 Answers

1
votes

The bullet is ‘moving around’ the player instead of through it because you have collisions turned on. All physics bodies collide with all others by default, whereas by default there are no contacts registered between physics bodies.

The first thing to do is to turn off collisions between the player and the bullet and vice-versa whilst leaving all other collisions unaffected:

playerNode.physicsBody?.collisionBitMask &= ~physicsCategory.bullet bullet.physicsBody?.collisionBitMask &= ~physicsCategory.player

Edit: my step-by-step guide for collisions and contacts: https://stackoverflow.com/a/51041474/1430420

A guide to collision and contactTest bit masks: https://stackoverflow.com/a/40596890/1430420

Manipulating bit masks to turn individual collisions and contacts off and on. https://stackoverflow.com/a/46495864/1430420