当玩家节点与另一个节点碰撞时游戏结束,当玩家与边界碰撞时游戏才应该结束
Posted
技术标签:
【中文标题】当玩家节点与另一个节点碰撞时游戏结束,当玩家与边界碰撞时游戏才应该结束【英文标题】:Game ends when player node collides with another node, when the game should only end when the player collides with the boundary 【发布时间】:2016-06-10 06:07:47 【问题描述】:问题:一旦玩家节点接触到硬币节点,游戏就会在玩家与边界碰撞时结束。
输出应该是什么:玩家应该能够接触到硬币节点并穿过它,为 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()
【问题讨论】:
关于您的编辑:您的播放器不检查边界,而是相反的方式可能有意义。但是您可能根本不希望 播放器 检查任何联系人以简化事情。 【参考方案1】:您的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()
可能更接近你想要的。
【讨论】:
您好,抱歉回复延迟。该代码看起来正是我需要的,但是当我测试它时,第一个 if 语句不起作用,但 else if 函数正常工作。我一直在修改我的代码,测试不同的方法,一切看起来都应该完美无缺,但第一个 if 语句目前不起作用。 其实你应该使用 iffirstBody.categoryBitMask == ColliderType.coinCategory || secondBody.categoryBitMask == ColliderType.coinCategory
因为硬币只检查它是否与玩家接触。
我将第一个 if 语句替换为您提供的那个,我似乎注意到第一个 if 语句没有按应有的方式运行的任何更改。一秒钟,我将用我当前的代码更新我的问题。我仍在学习 swift,所以我非常感谢您迄今为止的帮助。【参考方案2】:
(添加一个新答案,因为它基于新代码,并且 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()
但我真的考虑如果您打算在此基础上进行扩展,则完全将整个联系人处理重新设计为不同的野兽。
【讨论】:
您提供的代码已经解决了这个问题,现在硬币碰撞功能完美无缺!感谢您的帮助!当我获得 15 名声望时,我将做一个笔记回到这篇文章,以便我可以投票给这个答案。【参考方案3】:编写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 个类别的对象 不确定这是不是真的,因为我们正在测试是否设置了类别中的某些位但掩码,而不是整个类别(至少,这是意图)。 player = 0001 , coin = 0010 superpower = 0100 如果节点因为拥有超能力而变成0101,那么player的情况|硬币失败是因为您将 0111 与 0011 进行比较,但您希望它通过,并且必须扩展到每个案例以实现此目标是荒谬的 是的 - 你是对的,但我想这是一个相当不寻常的情况。为此,我认为如果您在 contactMask 和要检查联系人的 2 个类别之间执行按位与运算,则非 0 结果意味着命中。 很确定我的代码中某处有一条关于我应该如何真正测试每一点的评论......我将此视为个人挑战。以上是关于当玩家节点与另一个节点碰撞时游戏结束,当玩家与边界碰撞时游戏才应该结束的主要内容,如果未能解决你的问题,请参考以下文章