cafe hikari cafe hikari - 5 months ago 11
Swift Question

spritekit didBeginContact three object not worked

I am tring to [didBeginContact] by three nodes. I wrote under code.
But not work correctly. when white rectangle fole without hitting black or white rectangle,
println("black"), and println("blue") work...
whien white rectangle hit black rectangle, println("blue") work...

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

let blackCategory: UInt32 = 0x1 << 0
let whiteCategory: UInt32 = 0x1 << 1
let blueCategory: UInt32 = 0x1 << 2

override func didMoveToView(view: SKView) {

self.physicsWorld.contactDelegate = self

self.size = view.bounds.size
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsWorld.gravity = CGVectorMake(0.0, -3.0)

let blackSquare = SKSpriteNode(color: UIColor.blackColor(), size: CGSizeMake(50, 50))
blackSquare.position = CGPoint(
x: CGRectGetMidX(self.frame),
y: CGRectGetMidY(self.frame)
)
blackSquare.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(50, 50))
blackSquare.physicsBody?.affectedByGravity = false
blackSquare.physicsBody?.dynamic = false

blackSquare.physicsBody?.categoryBitMask = blackCategory
blackSquare.physicsBody?.contactTestBitMask = whiteCategory

let blueSquare = SKSpriteNode(color: UIColor.blueColor(), size: CGSizeMake(50, 50))
blueSquare.position = CGPoint(
x: CGRectGetMidX(self.frame) - 100,
y: CGRectGetMidY(self.frame) - 100
)
blueSquare.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(50, 50))
blueSquare.physicsBody?.affectedByGravity = false
blueSquare.physicsBody?.dynamic = false

blackSquare.physicsBody?.categoryBitMask = blueCategory
blackSquare.physicsBody?.contactTestBitMask = whiteCategory

self.addChild(blackSquare)
self.addChild(blueSquare)
}

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {


for touch in touches {

let location = touch.locationInNode(self)
let whiteRectangle = SKSpriteNode(color: UIColor.whiteColor(), size: CGSizeMake(50, 50))
whiteRectangle.position = location
whiteRectangle.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(50, 50))


whiteRectangle.physicsBody?.categoryBitMask = whiteCategory
whiteRectangle.physicsBody?.contactTestBitMask = blackCategory
whiteRectangle.physicsBody?.contactTestBitMask = blueCategory

self.addChild(whiteRectangle)
}

}

override func update(currentTime: CFTimeInterval) {
}


func didBeginContact(contact: SKPhysicsContact!) {

var firstBody, secondBody, thirdBody: SKPhysicsBody


if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
thirdBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
thirdBody = contact.bodyA
}

if firstBody.categoryBitMask & whiteCategory != 0 &&
secondBody.categoryBitMask & blackCategory != 0 {
//secondBody.node?.removeFromParent()
println("black")
}

if firstBody.categoryBitMask & whiteCategory != 0 &&
thirdBody.categoryBitMask & blueCategory != 0 {
//secondBody.node?.removeFromParent()
println("blue")
}
}
}

Answer

1) Based on your contact handler, you should set the categories to be

    let whiteCategory:  UInt32 = 0x1 << 0
    let blackCategory:  UInt32 = 0x1 << 1
    let blueCategory:   UInt32 = 0x1 << 2

2) You are incorrectly setting the blackSquare's physicsBody's bit masks twice

    blackSquare.physicsBody?.categoryBitMask = blueCategory
    blackSquare.physicsBody?.contactTestBitMask = whiteCategory

The above should be

    blueSquare.physicsBody?.categoryBitMask = blueCategory
    blueSquare.physicsBody?.contactTestBitMask = whiteCategory

3) The third contact body is not needed here.

func didBeginContact(contact: SKPhysicsContact!) {

    var firstBody, 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 & whiteCategory) != 0 &&
        (secondBody.categoryBitMask & blackCategory != 0)) {
            //secondBody.node?.removeFromParent()
            println("black")
    }


    if ((firstBody.categoryBitMask & whiteCategory != 0) &&
        (secondBody.categoryBitMask & blueCategory != 0)) {
            //secondBody.node?.removeFromParent()
            println("blue")
    }
}

4) The following is not needed (in touchesBegan). Setting the contact bit masks for the blue and black nodes is sufficient.

    whiteRectangle.physicsBody?.contactTestBitMask = blackCategory
    whiteRectangle.physicsBody?.contactTestBitMask = blueCategory