iOS Swift didBeginContact not being called
Asked Answered
H

4

8

I have been struggling for the past two days to get two SKSpriteNodes to register a collision and evoke didBegin#contact.

I've set their bit masks 'categoryBitMask', 'contactTestBitMask' and 'collisionTestBitMask' for both objects.

I've also set the 'dynamic' property for both to 'true'

initPhysics() seems to set up the physicsWorld okay.

All I'm expecting is that didBegin#Contact is called, but it is not

//Set up Physicsbody bit masks
let playerCarBitMask: UInt32 = 0x1 << 1
let slowCarBitMask: UInt32 = 0x1 << 2



//initPhysics
func initPhysics() {
    println("(((((((((((((( Initiating Physicsbody ))))))))))))))")
    self.physicsWorld.contactDelegate = self
    self.physicsWorld.gravity = CGVector.zeroVector

    println("self.physicsWorld.contactDelegate = \(self.physicsWorld.contactDelegate)")

}

//setupPlayer
func setupPlayer() {

    car = SKSpriteNode(imageNamed: "redCarUp")
    car.setScale(2.0)
    car.position = CGPoint(x: 800, y: 400)
    car.zPosition = 100
    car.name = "car"

    gameNode.addChild(car)

    let carBody = SKPhysicsBody(
        rectangleOfSize: car.frame.size, center: car.position)

    carBody.dynamic = true
    carBody.categoryBitMask = playerCarBitMask
    carBody.contactTestBitMask = slowCarBitMask
    carBody.mass = 5
    carBody.collisionBitMask = slowCarBitMask
    car.physicsBody = carBody

    println("carBody = \(carBody)")
    println("carBody.dynamic = \(carBody.dynamic)")
    println("carBody.mass = \(carBody.mass)")
    println("carBody.categoryBitMask = \(carBody.categoryBitMask)")
    println("carBody.contactTestBitMask = \(carBody.contactTestBitMask)")
    println("carBody.collisionBitMask = \(carBody.contactTestBitMask)")



    slowCar = SKSpriteNode(imageNamed: "blueCarUp")
    slowCar.setScale(2.0)
    let slowCarScenePos = CGPoint(
        x: 680,
        y: 2048)


    slowCar.position = gameNode.convertPoint(slowCarScenePos, fromNode: self)
    println("slowCar.position = \(slowCar.position) ****")
    slowCar.zPosition = 80
    slowCar.name = "slowCar"



    let slowCarBody = SKPhysicsBody(
        rectangleOfSize: slowCar.frame.size, center: slowCar.position)


    println("slowCar = \(slowCar) ****")

    slowCarBody.dynamic = true
    slowCarBody.categoryBitMask = slowCarBitMask
    slowCarBody.contactTestBitMask = playerCarBitMask
    slowCarBody.mass = 5
    slowCarBody.collisionBitMask = playerCarBitMask
    slowCar.physicsBody = slowCarBody
    gameNode.addChild(slowCar)



}

func didBeginContact(contact: SKPhysicsContact!) {
    println("*******************PhysicsContact********************")
}
Hamlani answered 18/10, 2014 at 9:16 Comment(2)
Code dumps are not appreciated on this platform.Naraka
note that as well as collisionBitMask, you must set contactTestBitMask. this is the usual gotchya. note that in the storyboard editor, it leaves contactTestBitMask as zero by default - it's the usual problem. just set it to "1"Freeswimming
H
2

It turned out to be a simple problem. In my original code I was setting parameters for the SKPhysicsBody detection frame like so:

let carBody = SKPhysicsBody( rectangleOfSize: car.frame.size, center: car.position)

Similarly I was doing the same for the second node that I was testing physics collisions for.

Simply removing the 'centre:' parameters like so:

let carBody = SKPhysicsBody(rectangleOfSize: car.frame.size)

for the two sprite nodes solved the problem and the nodes now crash into each other and push themselves aside as expected.

Hamlani answered 19/10, 2014 at 9:6 Comment(0)
D
11

'didBeginContact' has been changed to 'didBegin' in swift 3

func didBegin(_ contact: SKPhysicsContact) { //stuff }

I had a code from swift 2 and 'didBeginContact' was sitting there but wasn't being called. After quite a white I figured out that the function was changed. So, I thought my answer could help someone.

Distil answered 11/1, 2017 at 13:44 Comment(0)
C
3

If you want make a contact between car and slowCar you have to init the categoryBitMask of both physicsBodies (I think you did). See the code below to get contact between two physicsBodies. When there is a contact it returns your display function :

//init your categoryBitMask : 
let carCategory:UInt32 = 0x1 << 0
let SlowCarCategory:UInt32 = 0x1 << 1


//init car
car.physicsBody?.categoryBitMask = carCategory
car.physicsBody?.contactTestBitMask = slowCarCategory

//init slowCar 
slowCar.physicsBody?.categoryBitMask = slowCarCategory
slowCar.physicsBody?.contactTestBitMask = CarCategory

// set your contact function
func didBeginContact(contact: SKPhysicsContact!)
{
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody


    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA
        secondBody = contact.bodyB

    }
    else
    {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }


    if ((firstBody.categoryBitMask & carCategory) != 0 && (secondBody.categoryBitMask & slowCarCategory) != 0)
    {
        displayfunction(firstBody.node as SKSpriteNode, car: secondBody.node as SKSpriteNode)
    }
}

func displayFunction (slowCar : SKSpriteNode, car : SKSpriteNode)
Choking answered 18/10, 2014 at 18:37 Comment(4)
Thanks, unfortunately didBeginContact() is not being evoked in the first place. I have just stripped the whole code back so that it just puts the sprites on the screen, sets up the physics engine and then runs an action to make one hit the other but unfortunately it is still not working.Hamlani
Do you set the categoryBitMask of carand slowCar? In your code you set carBody and slowCarBodyChoking
Hey Haox, it turned out that the problem was due to the manner in which I was setting up the physicsBody frame for the sprite node, see my answer. Your help was appreciated though because its given me some valuable insight into the next stage of my coding challenge. Thanks again!Hamlani
Glad to help you for later :DChoking
H
2

It turned out to be a simple problem. In my original code I was setting parameters for the SKPhysicsBody detection frame like so:

let carBody = SKPhysicsBody( rectangleOfSize: car.frame.size, center: car.position)

Similarly I was doing the same for the second node that I was testing physics collisions for.

Simply removing the 'centre:' parameters like so:

let carBody = SKPhysicsBody(rectangleOfSize: car.frame.size)

for the two sprite nodes solved the problem and the nodes now crash into each other and push themselves aside as expected.

Hamlani answered 19/10, 2014 at 9:6 Comment(0)
E
1

Please Note that contact will not be detected between two static bodies

(node.physicsBody?.isDynamic = false)
Etheleneethelin answered 5/12, 2016 at 13:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.