Search code examples
iosswiftsprite-kitskphysicscontact

Detecting Physics Contact in Swift 2


I want to detect in my app a contact between two objects. I have an enum to define the different types:

enum ColliderType: UInt32 {

    case Ball = 0b010
    case Object = 0b001
    case Gap = 0b100

}

I also added SKPhysicsContactDelegate to my SKView:

In didMoveToView, I have

self.physicsWorld.contactDelegate = self

So here are my objects that I defined

ball = SKSpriteNode(texture: ballTexture)
    ball.position = CGPoint(x: CGRectGetMidX(self.frame) - self.frame.width/12, y: self.frame.size.height - (self.frame.size.height - 100))
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ballTexture.size().height)
    ball.physicsBody!.dynamic = false
    ball.physicsBody?.allowsRotation = false
    ball.physicsBody!.categoryBitMask = ColliderType.Ball.rawValue
    ball.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
    ball.physicsBody!.collisionBitMask = ColliderType.Object.rawValue


let boxTexture = SKTexture(imageNamed: "Obstacle.png")
    let box1 = SKSpriteNode(texture: boxTexture)
    box1.size = CGSizeMake(self.frame.width/4, self.frame.width/8)
    box1.runAction(moveAndRemoveBoxes)
    box1.physicsBody = SKPhysicsBody(rectangleOfSize: box1.size)
    box1.physicsBody!.dynamic = false
    box1.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
    box1.physicsBody!.contactTestBitMask = ColliderType.Ball.rawValue
    box1.physicsBody!.collisionBitMask = ColliderType.Object.rawValue

let gap = SKSpriteNode()
    gap.size = box1.size
    gap.physicsBody = SKPhysicsBody(rectangleOfSize: box1.size)
    gap.physicsBody!.dynamic = false
    gap.physicsBody!.categoryBitMask = ColliderType.Gap.rawValue
    gap.physicsBody!.contactTestBitMask = ColliderType.Ball.rawValue
    gap.physicsBody!.collisionBitMask = ColliderType.Gap.rawValue

In the didBeginContact function I have:

func didBeginContact(contact: SKPhysicsContact) {

    if contact.bodyA.categoryBitMask == ColliderType.Gap.rawValue || contact.bodyB.categoryBitMask == ColliderType.Gap.rawValue {

        print("score")
        score++

        scoreLabel.text = String(score)

    } else {

        if gameOver == false {

            gameOver = true

            self.speed = 0


        }

    }
}

If you tap the screen the ball objects jumps from half of the screen to other, and the object called box1 is "falling down" on one half of the screen and the "invisible" gap to detect if the player passed without colliding with the box is on the other half of the screen. So I want to detect if the ball touches the gap, so that the players score, otherwise the ball collides with the box


Solution

  • This is because your obstacles contactTestBitMask is looking for Object, not Ball. You want this: box1.physicsBody!.contactTestBitMask = ColliderType.Ball.rawValue

    In light of the new changes:

    ball.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue | ColliderType.Gap.rawValue

    You need to be checking for gap value if you want contact to work