我试图在Swift中使用碰撞位掩码和接触测试位掩码,我希望两个对象不要碰撞在一起,所以我在做:
firstNode.physicsBody?.collisionBitMask = 0b01
secondNode?.collisionBitMask = 0b10
由于SpriteKit对这两个数字进行AND运算,因此00
的结果不应该是10 & 01 = 00
吗?
那么为什么碰撞会发生呢?
谢谢。
答案 0 :(得分:9)
这不是碰撞处理的工作原理。当两个物体交叉时,物理引擎在当前的物体AND
和其他物体collisionBitMask
之间执行逻辑categoryBitMask
运算符:
当两个物理实体相互接触时,可能会发生碰撞。 该身体的碰撞面具与其他身体的类别进行比较 通过执行逻辑AND操作进行掩码。如果结果是非零 值,这个身体受到碰撞的影响。每个身体独立 选择是否想要受到其他身体的影响。对于 例如,您可以使用它来避免碰撞计算 对身体的速度做出微不足道的改变。
因此,结果取决于您在这两个实体上设置categoryBitMask
的方式。 categoryBitMask
的默认值为0xFFFFFFFF
,表示设置了所有位。所以,当你表演&在0xFFFFFFFF
和0b10
或0b01
之间,结果将是非零值,因此是碰撞。
例如,设置你的身体是这样的:
spriteA.physicsBody?.categoryBitMask = 0b01
spriteA.physicsBody?.collisionBitMask = 0b01
和
spriteB.physicsBody?.categoryBitMask = 0b10
spriteB.physicsBody?.collisionBitMask = 0b10
会给你想要的结果。此外,这可能不是您需要的确切设置,它只是一个简单的示例,您必须根据需要更改值。在这种情况下,spriteA只会与categoryBitMask
设置为0b01
的实体发生冲突。同样适用于spriteB,它会与categoryBitMask
设置为0b10
的实体发生冲突。
此外,如果您不希望这些精灵能够与任何事物发生碰撞,只需将其collisionBitMask
属性设置为0。
答案 1 :(得分:5)
这不是你如何测试具有冲突位的节点之间的交互。
假设我有以下内容:
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.
}
变量冲突使用按位OR,即|。在这种情况下(如果玩家接触敌人),它获得玩家(bodyA)的类别为2,并获得敌人的类别(bodyB),即4.所以2(0b10)或4( 0b100)等于6(0b110),它被分配给碰撞。
然后在if语句中,它检查6的碰撞是否等于(PC.player | PC.enemy),这是真的,因此玩家和敌人之间发生了交互,因为它会是如果6 == 6。
您可以使用变量碰撞来测试任何交互。例如,在我的测试游戏中,我有以下功能来测试触摸的对象。
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()
}
}
}