无法理解冲突位掩码的工作原理

Can't understand how collision bit mask works

我正在尝试在 Swift 中使用碰撞位掩码和接触测试位掩码,我希望两个对象不会碰撞在一起,所以我正在做 :

firstNode.physicsBody?.collisionBitMask = 0b01
secondNode?.collisionBitMask = 0b10

由于 SpriteKit 对这两个数字进行了 AND 运算,结果不应该是 00 因为 10 & 01 = 00 ?

那么为什么会发生碰撞?

谢谢。

这不是碰撞处理的工作方式。当两个物体相交时,物理引擎在当前的 body collisionBitMask 和其他的 body categoryBitMask:

之间执行逻辑 AND 运算符

When two physics bodies contact each other, a collision may occur. This body’s collision mask is compared to the other body’s category mask by performing a logical AND operation. If the result is a nonzero value, this body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body. For example, you might use this to avoid collision calculations that would make negligible changes to a body’s velocity.

source.

所以结果取决于你如何在这两个物体上设置 categoryBitMaskcategoryBitMask 的默认值为 0xFFFFFFFF,表示已设置所有位。因此,当您在 0xFFFFFFFF0b100b01 之间执行 & 时,结果将是 non-zero 值,因此发生了冲突。

例如,像这样设置你的身体:

spriteA.physicsBody?.categoryBitMask = 0b01
spriteA.physicsBody?.collisionBitMask = 0b01

spriteB.physicsBody?.categoryBitMask = 0b10
spriteB.physicsBody?.collisionBitMask = 0b10

会给你想要的结果。此外,这可能不是您需要的确切设置,它只是一个简单的示例,您必须根据需要更改值。在这种情况下,spriteA 只会与 categoryBitMask 设置为 0b01 的物体发生碰撞。 spriteB 也是如此,它会与 categoryBitMask 设置为 0b10.

的物体发生碰撞

此外,如果您不希望这些精灵与任何东西发生碰撞,只需将它们的 collisionBitMask 属性设置为 0。

这不是测试具有冲突位的节点之间交互的方式。

  • categoryBitMask 是对象的类别。
  • collisionBitMask 是对象碰撞时的响应。
  • 当指定位掩码发生交集时,contactTestBitMask 用于通知。

假设我有以下内容:

struct PC {
    static var player: UInt32 = 0b10 //2
    static var enemy: UInt32 = 0b100 //4
    static var rock: UInt32 = 0b1000 //8
}

player.physicsBody!.categoryBitMask = PC.player
player.physicsBody!.collisionBitMask = PC.enemy | PC.rock
enemy.physicsBody!.categoryBitMask = PC.enemy
enemy.physicsBody!.collisionBitMask = PC.player

因此,当您在 didBeginContact 函数中检查何时发生交互时,您使用位逻辑检查它们是否发生交互。

func didBeginContact(contact: SKPhysicsCountact) {
    //1
    let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    //2
    if collision == PC.player | PC.enemy {
        //An interaction occured between the player and enemy.
    }
  1. 变量碰撞是按位或,即|。在这种情况下(如果玩家接触到一个敌人),它得到玩家(bodyA)的类别是 2,它得到敌人(bodyB)的类别,它是 4。所以 2 (0b10) OR 4 ( 0b100) 等于分配给碰撞的 6 (0b110)。

  2. 所以在if语句中,它检查6的碰撞是否等于(PC.player | PC.enemy),这是真的,因此之间发生了交互玩家和敌人,因为如果 6 == 6.

您可以使用变量 collision 来测试任何交互。例如,在我的测试游戏中,我有以下功能来测试触摸到的对象。

func didBeginContact(contact: SKPhysicsContact) {
    let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    //Collision between the penguin and land
    if collision == PhysicsCategory.Land | PhysicsCategory.Animal {
        lostLevel()
    } else if collision == PhysicsCategory.Animal | PhysicsCategory.Pillow {
        animalCounter -= 1
        if animalCounter == 0 {
            wonLevel()
        }
    }
}