问题:当玩家节点与硬币节点接触时,游戏结束时游戏应该只在玩家与边界碰撞时结束。
输出应该是什么:播放器应该能够与硬币节点接触并穿过它,向scoreLabel添加一个值。 目前的代码:
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))
}
}
更新:
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()
}
}
答案 0 :(得分:2)
您的gameOver = true
语句超出了didBeginContact中的所有if。换句话说:发生联系的那一刻你设置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()
}
可能更接近你想要的东西。
答案 1 :(得分:1)
使用firstBody / secondbody编写代码didBeginContact
的更简洁的方法是:
func didBeginContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case ColliderType.playerCategory | ColliderType.coinCategory:
// player and coin have contacted. We need to get the coin, which is either firstBody or secondBody, to remove it, so assign the corect one to coinNode
let coinNode = contact.bodyA.categoryBitMask == ColliderType.coinCategory ? contact.bodyA.node! : contact.bodyB.node!
coinNode.removefromParent
coinInt += 1
coinLabel.text = "\(coinInt)"
case ColliderType.playerCategory | ColliderType.boundaryCategory:
// player and boundary have contacted
gameOver = true
self.speed = 0
timer.invalidate()
default :
//Some other contact has occurred
print("Some other contact")
}
}
您可以根据需要添加任意数量的case ColliderType.object1 | ColliderType.object2:
。
答案 2 :(得分:1)
(添加新答案,因为它基于新代码和O.P.问题中的讨论/更改会使逻辑流程难以理解)
首先,我会对physicBodies进行以下更改:
player.physicsBody?.contactTestBitMask = 0 // or ColliderType.None which would be my stylistic choice
然后其他人会读到这样的东西。
func didBeginContact(contact:SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
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()
}
}
备注:
从提供的代码中不清楚self.coin是如何被引用的。我猜测 self.coin.removeFromParent()
可能没有多大意义,因为您在初始帖子中写了几个硬币。它可能应该是这样的:
if contact.bodyA.categoryBitMask == ColliderType.coinCategory {
contact.bodyA.node!.removeFromParent()
} else if contact.bodyB.categoryBitMask == ColliderType.coinCategory {
contact.bodyB.node!.removeFromParent()
}
但我真的认为将整个联系处理完全重新组合成一个不同的野兽如果你打算在这个方面进行扩展。