操作 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

這將影響你操作位域的方式。它可能是有用的(例如)表明物理體(例如炸彈)已經以某種方式發生了變化(例如它可能已經獲得了另一類別的超級能力,你可能會檢查某個物體(一個外星人的母親)