当玩家节点与另一个节点碰撞时游戏结束,当游戏只应在玩家与边界碰撞时结束

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

问题:一旦玩家节点接触到硬币节点,游戏就结束了,当游戏应该只在玩家与边界碰撞时结束。

输出应该是什么:玩家应该能够接触到硬币节点并穿过它,为 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()

}
}

您的 gameOver = true 语句在 didBeginContact 中的所有 ifs 之外。换句话说:接触发生的那一刻你设置 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()
}

可能更接近你想要的。

一种更简洁的编码方式 didBeginContact,它减少了 firstBody/secondbody 的混乱,是:

    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:

(添加新答案,因为它基于新代码和 O.P 中的 discussion/changes。-问题会使逻辑流程有点难以遵循)

首先,我将对 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() 可能没有太多意义,因为你在最初的 post 中写了 几个 硬币。它可能应该是这样的:

if contact.bodyA.categoryBitMask == ColliderType.coinCategory {
    contact.bodyA.node!.removeFromParent()
} else if contact.bodyB.categoryBitMask == ColliderType.coinCategory {
    contact.bodyB.node!.removeFromParent()
}

但我 真的考虑 如果您打算进一步扩展,则将整个联系人处理完全改造成一个不同的野兽。