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()
}
}
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.