Search code examples
iosswiftsprite-kitskphysicsbody

SpriteKit + Swift - Not Firing on contact


So I am playing around with Swift and SpriteKit. I decided to create a simple game where a character will walk to a chest of coins and get all the treasure.

I am trying to detect when the two objects contact eachother, however nothing seems to be happening.

What I did:

1) I set the delegate:

SKPhysicsContactDelegate

2) Created the scene:

override func didMoveToView(view: SKView) {

    backgroundColor = SKColor.whiteColor()
    physicsWorld.contactDelegate = self

    let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    sceneBody.friction = 0

    background.zPosition = -20
    background.anchorPoint = CGPointZero
    background.position = CGPointZero

    backgroundRepeated.zPosition = -20
    backgroundRepeated.anchorPoint = CGPointZero
    backgroundRepeated.position = CGPointMake(background.size.width-1,0)


    addChest()
    addCharacter()

    addChild(background)
    addChild(backgroundRepeated)


}

3) Created the items:

func addChest() {
    chestOfCoins.anchorPoint = CGPointZero
    chestOfCoins.size = CGSize(width: 200,height: 200)
    chestOfCoins.position = CGPoint(x: self.frame.width-1, y: 300)
    chestOfCoins.zPosition = 20
    chestOfCoins.physicsBody = SKPhysicsBody(rectangleOfSize: chestOfCoins.size)
    chestOfCoins.physicsBody?.affectedByGravity = false
    chestOfCoins.physicsBody?.dynamic = false
    chestOfCoins.physicsBody?.categoryBitMask = physicsCategory.chests
    chestOfCoins.physicsBody?.collisionBitMask = 0
    chestOfCoins.physicsBody?.contactTestBitMask = physicsCategory.character

    addChild(chestOfCoins)
}

func addCharacter() {
    character.anchorPoint = CGPointZero
    character.position = CGPoint(x: 300, y: 300)
    character.zPosition = 20
    character.size = CGSize(width: 200, height: 200)
    character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
    character.physicsBody?.affectedByGravity = false
    character.physicsBody?.dynamic = false
    character.physicsBody?.categoryBitMask = physicsCategory.character
    character.physicsBody?.contactTestBitMask = physicsCategory.chests
    character.physicsBody?.collisionBitMask = 0


    addChild(character)
}

4) created didBeginContact:

func didBeginContact(contact: SKPhysicsContact) {
    var contactBody1: SKPhysicsBody
    var contactBody2: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        contactBody1 = contact.bodyA
        contactBody2 = contact.bodyB

    } else {
        contactBody1 = contact.bodyB
        contactBody2 = contact.bodyA
    }

    if((contactBody1.categoryBitMask == 1) && (contactBody2.categoryBitMask == 2)) {
        print("touched")
    } else {
        print("not these two")
    }
}

FYI, this IF if((contactBody1.categoryBitMask == 1) && (contactBody2.categoryBitMask == 2)) does not output Either the main if block or the else.

5) I created the category physics :

struct physicsCategory {
  static let none: UInt32 = 0 //0
  static let character: UInt32 = 0b1 //1
  static let chests: UInt32 = 0b10 //2
  static let snake: UInt32 = 0b100 //4
}

Full GameScene.Swift:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

struct physicsCategory {
    static let none: UInt32 = 0 //0
    static let character: UInt32 = 0b1 //1
    static let chests: UInt32 = 0b10 //2
    static let snake: UInt32 = 0b100 //4
    static let all: UInt32 = UInt32.max
}


let background = SKSpriteNode(imageNamed: "Backgrounds")
let backgroundRepeated = SKSpriteNode(imageNamed: "Backgrounds")
let chestOfCoins = SKSpriteNode(imageNamed: "chest")
let character = SKSpriteNode(imageNamed: "character")

let gameActions = NSUserDefaults.standardUserDefaults()

func addChest() {
    chestOfCoins.anchorPoint = CGPointZero
    chestOfCoins.size = CGSize(width: 200,height: 200)
    chestOfCoins.position = CGPoint(x: self.frame.width-1, y: 300)
    chestOfCoins.zPosition = 20
    chestOfCoins.physicsBody = SKPhysicsBody(rectangleOfSize: chestOfCoins.size)
    chestOfCoins.physicsBody?.affectedByGravity = false
    chestOfCoins.physicsBody?.dynamic = false
    chestOfCoins.physicsBody?.categoryBitMask = physicsCategory.chests
    chestOfCoins.physicsBody?.collisionBitMask = 0
    chestOfCoins.physicsBody?.contactTestBitMask = physicsCategory.character

    addChild(chestOfCoins)
}

func addCharacter() {
    character.anchorPoint = CGPointZero
    character.position = CGPoint(x: 300, y: 300)
    character.zPosition = 20
    character.size = CGSize(width: 200, height: 200)
    character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
    character.physicsBody?.affectedByGravity = false
    character.physicsBody?.dynamic = false
    character.physicsBody?.categoryBitMask = physicsCategory.character
    character.physicsBody?.contactTestBitMask = physicsCategory.chests
    character.physicsBody?.collisionBitMask = 0


    addChild(character)
}

override func didMoveToView(view: SKView) {

    backgroundColor = SKColor.whiteColor()
    physicsWorld.contactDelegate = self

    let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    sceneBody.friction = 0

    background.zPosition = -20
    background.anchorPoint = CGPointZero
    background.position = CGPointZero

    backgroundRepeated.zPosition = -20
    backgroundRepeated.anchorPoint = CGPointZero
    backgroundRepeated.position = CGPointMake(background.size.width-1,0)


    addChest()
    addCharacter()

    addChild(background)
    addChild(backgroundRepeated)


}

func didBeginContact(contact: SKPhysicsContact) {
    var contactBody1: SKPhysicsBody
    var contactBody2: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        contactBody1 = contact.bodyA
        contactBody2 = contact.bodyB

    } else {
        contactBody1 = contact.bodyB
        contactBody2 = contact.bodyA
    }

    if((contactBody1.categoryBitMask == 1) && (contactBody2.categoryBitMask == 2)) {
        print("touched")
    } else {
        print("not these two")
    }
}

override func update(currentTime: NSTimeInterval) {

    let startWalking = gameActions.boolForKey("Walking")

    if (startWalking == true) {


        chestOfCoins.position = CGPoint(x: chestOfCoins.position.x - 5, y: chestOfCoins.position.y)

        background.position = CGPoint(x: background.position.x - 5, y: background.position.y)
        backgroundRepeated.position = CGPoint(x: backgroundRepeated.position.x - 5, y: backgroundRepeated.position.y)

        if (background.position.x < -background.size.width) {
            background.position = CGPointMake(backgroundRepeated.position.x + backgroundRepeated.size.width, background.position.y)
        }

        if (backgroundRepeated.position.x < -backgroundRepeated.size.width) {
            backgroundRepeated.position = CGPointMake(background.position.x + background.size.width, backgroundRepeated.position.y)
        }
    }
}

}

Question

Can anyone tell me why, when the screen starts scrolling and those two items come into contact nothing happens and tell me how to fix it?

One also seems to go behind even though I set the zPosition of both to the same

Here is a pic, Don't judge about images :(

enter image description here

enter image description here


Solution

  • set either your chest or your other thingies property to dynamic = true

    two non-dynamic physics bodies wont register contacts