2015-06-29 28 views
14

Theo như tôi nhận thức được mặc định cho các cơ quan Vật lý là để tung ra lẫn nhau khi chúng đánh nhau cho đến khi bạn thiết lập collisionBitMask của chúng với một số bằng nhau.collisionBitMask hoạt động như thế nào? Swift/SpriteKit

Tuy nhiên, tôi đang gặp phải một vấn đề lớn hoàn thành những gì có vẻ như nó sẽ rất đơn giản vì collisionBitmasks tôi tin.

let RedBallCategory : UInt32 = 0x1 << 1 
    let GreenBallCategory: UInt32 = 0x1 << 2 
    let RedBarCategory : UInt32 = 0x1 << 3 
    let GreenBarCategory : UInt32 = 0x1 << 4 
    let WallCategory : UInt32 = 0x1 << 5 


     greenBall.physicsBody?.categoryBitMask = GreenBallCategory 
     greenBall.physicsBody?.contactTestBitMask = RedBarCategory 
     greenBall.physicsBody?.collisionBitMask = GreenHealthCategory 

redBall.physicsBody?.categoryBitMask = RedBallCategory 
     redBall.physicsBody?.contactTestBitMask = GreenBarCategory 
     redBall.physicsBody?.collisionBitMask = RedHealthCategory 

    let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 
    self.physicsBody = borderBody 
    self.physicsBody?.friction = 0 
    borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory 
    borderBody.categoryBitMask = WallCategory 

Vì vậy, ở đây tôi có 2 quả bóng và phần thân biên giới. Tôi có thể nhận được phát hiện va chạm mà tôi muốn, nhưng khi tôi thêm mặt nạ bit thể loại biên giới của cơ thể, nó cho phép các quả bóng để cả hai đi qua và tắt màn hình, mà tôi không muốn.

Tôi cũng muốn các quả bóng nảy lên nhau, nhưng chỉ khi tôi nhận xét ra một trong các thể loạiBitMasks của bóng thì chúng có bị trả lại không. Nếu không họ sẽ đi qua nhau.

Điều đó hoàn toàn không có ý nghĩa đối với tôi vì mỗi mục trong số này đều có một va chạm khác nhau. Tôi cũng đã có nó đôi khi nơi thiết lập tất cả các con số bằng 5 sẽ cho phép tất cả mọi thứ đi qua nhau, nhưng sau đó thiết lập tất cả để 6 sẽ cho phép tất cả mọi thứ để đánh nhau.

Làm thế nào chính xác bitmask va chạm hoạt động và có cách thích hợp để quản lý nhiều quy tắc xung đột chéo không?

Trả lời

37

Bạn không thể nhận được hành vi mong muốn vì bạn chưa đặt mặt nạ bit danh mục, liên hệ và va chạm đúng cách. Dưới đây là một ví dụ về cách bạn có thể thiết lập để làm việc này:

greenBall.physicsBody?.categoryBitMask = GreenBallCategory //Category is GreenBall 
greenBall.physicsBody?.contactTestBitMask = RedBarCategory | WallCategory //Contact will be detected when GreenBall make a contact with RedBar or a Wall (assuming that redBar's masks are already properly set) 
greenBall.physicsBody?.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory //Collision will occur when GreenBall hits GreenBall, RedBall or hits a Wall 

redBall.physicsBody?.categoryBitMask = RedBallCategory //Category is RedBall 
redBall.physicsBody?.contactTestBitMask = GreenBarCategory | GreenBallCategory | WallCategory //Contact will be detected when RedBall make a contact with GreenBar , GreenBall or a Wall 
redBall.physicsBody?.collisionBitMask = RedBallCategory | GreenBallCategory | WallCategory //Collision will occur when RedBall meets RedBall, GreenBall or hits a Wall 

let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame) 
self.physicsBody = borderBody 
self.physicsBody?.friction = 0 
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory //Contact will be detected when red or green ball hit the wall 
borderBody.categoryBitMask = WallCategory 
borderBody.collisionBitMask = RedBallCategory | GreenBallCategory // Collisions between RedBall GreenBall and a Wall will be detected 

tôi sẽ khuyên bạn nên đọc tài liệu về categoryBitMask mà là một mặt nạ xác định thể loại mà cơ thể vật lý thuộc về:

Mỗi cơ thể vật lý trong một cảnh có thể được gán cho tối đa 32 loại khác nhau , mỗi loại tương ứng với một chút trong mặt nạ bit. Bạn xác định giá trị mặt nạ được sử dụng trong trò chơi của mình. Cùng với các thuộc tính va chạm BitMask và contactTestBitMask, bạn xác định các đối tượng vật lý nào tương tác với nhau và khi trò chơi của bạn được thông báo các tương tác này.

contactTestBitMask - Mặt nạ xác định loại thể loại nào gây ra thông báo giao lộ với cơ thể vật lý hiện tại.

Khi hai cơ quan chia sẻ cùng một không gian, chủng loại mặt nạ của mỗi cơ thể là thử nghiệm chống lại mặt nạ tiếp xúc các cơ quan khác của bằng cách thực hiện một logic VÀ hoạt động. Nếu một trong hai so sánh dẫn đến một giá trị khác, đối tượng SKPhysicsContact được tạo và được chuyển đến đại diện của của thế giới vật lý. Để đạt hiệu quả tốt nhất, chỉ thiết lập bit trong địa chỉ liên lạc mặt nạ cho tương tác mà bạn đang quan tâm

collisionBitmask -. Một mặt nạ định nghĩa mà loại của các cơ quan vật lý có thể va chạm với cơ thể vật lý này.

Khi hai vật lý liên hệ với nhau, có thể xảy ra va chạm. Mặt nạ va chạm của cơ thể này được so sánh với mặt nạ của cơ thể khác bằng cách thực hiện thao tác logic AND. Nếu kết quả là giá trị không đồng nhất, phần thân này sẽ bị ảnh hưởng bởi va chạm. Mỗi cơ thể độc lập chọn xem nó có bị ảnh hưởng bởi cơ thể khác không. Đối với ví dụ , bạn có thể sử dụng điều này để tránh các phép tính va chạm sẽ thay đổi không đáng kể với vận tốc của cơ thể.

Vì vậy, về cơ bản, thiết lập tất cả các, bạn nên tự hỏi bản thân một cái gì đó của bạn như:

Được rồi, tôi có một quả bóng màu xanh lá cây, và một quả bóng đỏ, và các đối tượng tường trên sân khấu. Giữa những cơ quan nào tôi muốn va chạm xảy ra, hoặc khi tôi muốn đăng ký địa chỉ liên lạc? Tôi muốn một quả bóng màu xanh lá cây và một quả bóng màu đỏ va chạm với nhau và va vào tường. Không thành vấn đề. đầu tiên tôi sẽ thiết lập danh mục đúng cách, và sau đó tôi sẽ thiết lập mặt nạ chút va chạm như thế này:

greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall 
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory 

wall.collisionBitMask = GreenBall | RedBall 

Bây giờ, tôi muốn để phát hiện khi một số địa chỉ liên lạc xảy ra (trong didBeginContact: Phương pháp) ... Nhưng tôi không muốn được thông báo về tất cả các địa chỉ liên lạc có thể, nhưng thay vào đó được thông báo về địa chỉ liên hệ giữa các quả bóng (các liên hệ giữa các quả bóng và tường sẽ bị bỏ qua). Vì vậy, hãy đặt contactTestBitMasks để đạt được điều này:

greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory; 
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory; 

Và đó là nó. Điều quan trọng là khi bạn không sử dụng tính năng phát hiện liên hệ, bạn không nên đặt contactTestBitMask. Điều này là do lý do hiệu suất. Nếu bạn không cần phát hiện xung đột và bạn chỉ quan tâm đến việc phát hiện danh bạ, bạn có thể đặt collisionBitMask = 0.

Chú ý:

Hãy chắc chắn rằng bạn đã thiết lập đại biểu tiếp xúc vật lý thế giới để sử dụng didBeginContactdidEndContact phương pháp:

self.physicsWorld.contactDelegate = self; //where self is a current scene 

Hope this helps một chút.

+0

Câu trả lời tuyệt vời, cảm ơn bạn rất nhiều vì đã dành thời gian viết tất cả điều đó. Nó hoạt động hoàn hảo. Phần "tự hỏi mình" này chắc chắn sẽ xóa những gì tôi đã nhầm lẫn. Cảm ơn bạn rất nhiều! – Noowoo

+0

Còn nếu bạn có nhiều hơn thì 32? – cnzac

+0

@Abcdefg Làm thế nào bạn có thể phát hiện sự kết thúc của va chạm trong hàm didEnd? – Marin

Các vấn đề liên quan