操作 contactTest 和 collison bitmasks 以启用特定的特定联系和冲突

对于这个例子,我们将使用 4 个主体,为简单起见,仅显示位掩码的最后 8 位。这 4 个实体是 3 个 SKSpriteNodes,每个都有一个物理主体和一个边界:

    let edge = frame.insetBy(dx: 0, dy: 0)
    physicsBody = SKPhysicsBody(edgeLoopFrom: edge)

请注意,’edge’物理主体是场景的物理主体,而不是节点。

我们定义 4 个独特的类别

let purpleSquareCategory:   UInt32 = 1 << 0  // bitmask is ...00000001
let redCircleCategory:      UInt32 = 1 << 1  // bitmask is ...00000010
let blueSquareCategory:     UInt32 = 1 << 2  // bitmask is ...00000100
let edgeCategory:           UInt32 = 1 << 31  // bitmask is 10000...00000000

每个物理主体都分配了它所属的类别:

        //Assign our category bit masks to our physics bodies
        purpleSquare.physicsBody?.categoryBitMask = purpleSquareCategory
        redCircle.physicsBody?.categoryBitMask = redCircleCategory
        blueSquare.physicsBody?.categoryBitMask = blueSquareCategory
        physicsBody?.categoryBitMask = edgeCategory  // This is the edge for the scene itself

如果正文的 collisionBitMask 中的某个位设置为 1,那么它会碰撞(弹回)任何在其 categoryBitMask 中位于相同位置的 1 的主体。同样适用于 contactTestBitMask。

除非你另行指定,否则所有内容都会与其他所有内容发生冲突,并且不会生成任何联系人(当任何内容与其他任何内容联系时,你的代

purpleSquare.physicsBody.collisonBitMask = 11111111111111111111111111111111 // 32 '1's.

每个位置的每一位都是'1’,所以当与任何其他 categoryBitMask 相比时,Sprite Kit 会发现'1’,因此会发生碰撞。如果你不希望此主体与某个类别发生冲突,则必须将 collisonBitMask 中的正确位设置为 0

它的 contactTestbitMask 设置为所有 0s:

redCircle.physicsBody.contactTestBitMask = 00000000000000000000000000000000  // 32 '0's

与 collisionBitMask 相同,但反转除外。

体之间的接触或碰撞可关 (留下现有接触或碰撞不变)使用:

nodeA.physicsBody?.collisionBitMask &= ~nodeB.category

我们逻辑地将 nodeA 的碰撞位掩码与 nodeB 的类别位掩码的反(逻辑 NOT,〜运算符)关闭该位 nodeA 的 bitMask。例如,阻止红色圆圈与紫色方块碰撞:

redCircle.physicsBody?.collisionBitMask = redCircle.physicsBody?.collisionBitMask & ~purpleSquareCategory

可以缩短为:

redCircle.physicsBody?.collisionBitMask &= ~purpleSquareCategory

说明:

redCircle.physicsBody.collisonBitMask = 11111111111111111111111111111111
purpleSquareCategory  = 00000000000000000000000000000001
~purpleSquareCategory = 11111111111111111111111111111110 
11111111111111111111111111111111 & 11111111111111111111111111111110 = 11111111111111111111111111111110 
redCircle.physicsBody.collisonBitMask now equals 11111111111111111111111111111110 

redCircle 不再与类别为…… 0001(purpleSquare) 的物体发生碰撞

你可以直接设置它,而不是关闭 collsionsbitMask 中的各个位:

blueSquare.physicsBody?.collisionBitMask = (redCircleCategory | purpleSquareCategory)

blueSquare.physicsBody?.collisionBitMask = (....00000010 OR ....00000001)

等于 blueSquare.physicsBody?.collisionBitMask = ....00000011

blueSquare 只会与类别或..01 或 .10 的实体发生碰撞

2 个机构之间的触点或碰撞可以开启 ON (不影响任何现有的联系人或碰撞)在使用任何点:

redCircle.physicsBody?.contactTestBitMask |= purpleSquareCategory

我们逻辑上将 redCircle 的 bitMask 与 purpleSquare 的类别位掩码相关联,以打开redcircle 的 bitMask 中的那个位。这使得 redCircel 的 bitMas 中的任何其他位都不受影响。

你可以确保每个形状弹回屏幕边缘,如下所示:

// Make sure everything collides with the screen edge
enumerateChildNodes(withName: "//*") { node, _ in
    node.physicsBody?.collisionBitMask |= self.edgeCategory  //Add edgeCategory to the collision bit mask
}

注意:

碰撞可以是片面的,即物体 A 可以碰撞(反弹)物体 B,而物体 B 继续进行,就好像什么也没发生过一样。如果你想让 2 个物体相互反弹,它们必须被告知要与另一个物体相撞:

blueSquare.physicsBody?.collisionBitMask = redCircleCategory
redcircle.physicsBody?.collisionBitMask = blueSquareCategory

然而,联系不是片面的; 如果你想知道对象 A 何时触摸(接触)对象 B,则就对象 B 设置对象 A 的接触检测就足够了。你不必在对象 B 上为对象 A 设置接触检测。

blueSquare.physicsBody?.contactTestBitMask = redCircleCategory

我们不需要 redcircle.physicsBody?.contactTestBitMask= blueSquareCategory

高级用法:

这里没有涉及,但物理机构可以属于多个类别。例如,我们可以将游戏设置如下:

let squareCategory:   UInt32 = 1 << 0   // bitmask is ...00000001
let circleCategory:   UInt32 = 1 << 1   // bitmask is ...00000010
let blueCategory:     UInt32 = 1 << 2   // bitmask is ...00000100
let redCategory:      UInt32 = 1 << 3   // bitmask is ...00001000
let purpleCategory:   UInt32 = 1 << 4   // bitmask is ...00010000
let edgeCategory:     UInt32 = 1 << 31  // bitmask is 10000...0000000

每个物理主体都分配了它所属的类别:

        //Assign our category bit masks to our physics bodies
        purpleSquare.physicsBody?.categoryBitMask = squareCategory | purpleCategory
        redCircle.physicsBody?.categoryBitMask = circleCategory | redCategory
        blueSquare.physicsBody?.categoryBitMask = squareCategory | blueCategory

他们的 categorybitMasks 现在是:

purpleSquare.physicsBody?.categoryBitMask = ...00010001
redCircle.physicsBody?.categoryBitMask    = ...00001010
blueSquare.physicsBody?.categoryBitMask   = ...00000101

这将影响你操作位域的方式。它可能是有用的(例如)表明物理体(例如炸弹)已经以某种方式发生了变化(例如它可能已经获得了另一类别的超级能力,你可能会检查某个物体(一个外星人的母亲)