P.Dane P.Dane - 5 months ago 24
Swift Question

Game ends when player node collides with another node, when the game should only end when the player collides with the boundary

The problem: As soon as the player node comes in contact with a coin node, the game ends when the game should only end when the player collides with the boundary.

What the output should be: The player should be able to come in contact with the coin node and travel through it, adding a value to the scoreLabel.
The current code:

struct ColliderType {

static let playerCategory: UInt32 = 0x1 << 0
static let boundary: UInt32 = 0x1 << 1
static let coinCategory: UInt32 = 0x1 << 2
static let firstBody: UInt32 = 0x1 << 3
static let secondBody: UInt32 = 0x1 << 4

}

var gameOver = false
var coinInt = 0

coin.physicsBody?.categoryBitMask = ColliderType.coinCategory
coin.physicsBody?.contactTestBitMask = ColliderType.playerCategory
coin.physicsBody?.collisionBitMask = 0


player.physicsBody?.categoryBitMask = ColliderType.playerCategory
player.physicsBody?.contactTestBitMask = ColliderType.boundary | ColliderType.coinCategory
player.physicsBody?.collisionBitMask = ColliderType.boundary

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 == ColliderType.playerCategory && secondBody.categoryBitMask == ColliderType.coinCategory {
self.coin.removeFromParent()
coinInt += 1
coinLabel.text = "\(coinInt)"
}

gameOver = true
self.speed = 0
timer.invalidate()

}

override func touchesBegan(touches: Set<UITouch> , withEvent event: UIEvent?) {
if gameOver == false {

self.player.physicsBody?.velocity = CGVectorMake(1, 3)
self.player.physicsBody?.applyImpulse(CGVectorMake(0, 12))

}

}


UPDATE:

boundary.contactTestBitMask = ColliderType.playerCategory
boundary.categoryBitMask = ColliderType.boundary
boundary.collisionBitMask = ColliderType.playerCategory

coin.physicsBody?.categoryBitMask = ColliderType.coinCategory
coin.physicsBody?.contactTestBitMask = ColliderType.playerCategory
coin.physicsBody?.collisionBitMask = 0


player.physicsBody?.categoryBitMask = ColliderType.playerCategory
player.physicsBody?.contactTestBitMask = ColliderType.coinCategory
player.physicsBody?.collisionBitMask = ColliderType.boundary




func didBeginContact(contact:SKPhysicsContact) {
let firstBody: SKPhysicsBody
let 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 == ColliderType.coinCategory || secondBody.categoryBitMask == ColliderType.coinCategory {

self.coin.removeFromParent()
self.coinInt += 1
self.coinLabel.text = "\(self.coinInt)"

}else if firstBody.categoryBitMask == ColliderType.boundary || secondBody.categoryBitMask == ColliderType.boundary {

gameOver = true
self.speed = 0
timer.invalidate()

}
}

Answer

Your gameOver = true statement is outside all the ifs in didBeginContact. In other words: The moment a contact happens you set gameOver = true.

if firstBody.categoryBitMask == ColliderType.coinCategory || secondBody.categoryBitMask == ColliderType.coinCategory {
   self.coin.removeFromParent()
   coinInt += 1
   coinLabel.text = "\(coinInt)"
} else if firstBody.categoryBitMask == ColiderType.boundary || secondBody.categoryBitMask == ColiderType.boundary {
    gameOver = true
    self.speed = 0
    timer.invalidate()
}

Is probably closer to what you want.