2015-06-29 3 views
14

Насколько я знаю, по умолчанию физические тела должны отскакивать друг от друга, когда они попадают друг в друга, пока вы не установите их collisionBitMask равным числом.Как работает collisionBitMask? Swift/SpriteKit

Однако у меня возникла огромная проблема, которая, похоже, должна быть очень простой из-за столкновенияБитмаски, которые я считаю.

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 

Итак, у меня есть свои 2 шара и мое пограничное тело. Я могу получить обнаружение столкновения, которое я хочу, но когда я добавляю битовую маску категории пограничного тела, он позволяет шарам как проходить, так и выключать экран, чего я не хочу.

Я также хочу, чтобы шары отскакивали друг от друга, но только когда я прокомментирую одну из категорий categoryBitMasks, они отскакивают. В противном случае они проходят друг через друга.

Это не имеет абсолютно никакого смысла для меня, потому что каждый из этих предметов имеет другую collisionbitmask. У меня также было это иногда, когда установка всех чисел, равных 5, позволяла бы всем проходить друг через друга, но тогда установка всего на 6 позволила бы всем ударить друг друга.

Как именно работают битмаски для столкновений, и есть ли способ управления множеством перекрещивающихся правил столкновений?

ответ

37

Вы не можете получить желаемое поведение, потому что вы не задали правильные маски разряда категории, контакта и столкновения. Вот пример того, как вы можете установить эту работу:

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 

Я рекомендовал бы вам прочитать документацию о categoryBitMask, который представляет собой маску, которая определяет, какие категории принадлежит физике тело:

Каждый физическому телу в сцене можно присвоить до 32 различных категорий , каждый из которых соответствует бит в битовой маске. Вы определяете значения маски, используемые в вашей игре . В сочетании с параметрами collisionBitMask и contactTestBitMask вы определяете, какие физические тела взаимодействуют друг с другом, и когда ваша игра уведомляется об этих взаимодействиях.

contactTestBitMask - Маска, определяющая, какие категории тел вызывают уведомления о пересечении с текущим физическим телом.

Когда два тела один и то же место, категория маска каждого тела является проверяется на контактной маску другого тела, выполняя логическую операцию И . Если любое сравнение приводит к ненулевому значению, создается объект SKPhysicsContact и передается делегату физика. Для лучшей производительности, только установленные биты в контактах маски для взаимодействий вы заинтересованы в

collisionBitmask -. Маска, которая определяет, какие категории физических тел могут столкнуться с этой физикой телом.

Когда два физических тела контактируют друг с другом, может возникнуть столкновение. Маска столкновения этого тела сравнивается с маской другого тела , выполняя логическую операцию И. Если результатом является ненулевое значение , на это тело влияет столкновение. Каждый орган независимо выбирает, хочет ли он быть затронутым другим телом. Например, для вы можете использовать это, чтобы избежать вычислений столкновений, которые бы приводили к незначительным изменениям скорости тела.

Так в основном, чтобы настроить все это, вы должны задать себе что-то вроде:

Хорошо, у меня есть зеленый шар, и красный шар, и объекты стены на сцене. Между телами я хочу, чтобы произошли столкновения, или когда я хочу зарегистрировать контакты? Я хочу, чтобы зеленый и красный шар сталкивались друг с другом и сталкивались с стенами. Не проблема. Я первый настроит категории должным образом, а затем обращу столкновения битовых масок, как это:

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

wall.collisionBitMask = GreenBall | RedBall 

Теперь я хочу, чтобы обнаружить, когда некоторые контакты происходят (в didBeginContact: метод) ... Но я не хочу получать уведомления обо всех возможных контактах, а скорее получать уведомления о контактах между шарами (контакты между шарами и стеной будут проигнорированы). Таким образом, позволяет установить contactTestBitMasks для достижения этой цели:

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

И это все. Важно то, что если вы не используете обнаружение контактов, вы не должны устанавливать contactTestBitMask. Это связано с соображениями производительности. Если вам не требуется обнаружение столкновений, и вас интересует только обнаружение контактов, вы можете установить collisionBitMask = 0.

Важен:

Убедитесь, что вы установили ФИЗИК мир контакт делегат для того, чтобы использовать didBeginContact и didEndContact методы:

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

Надеется, что это помогает немного.

+0

Удивительный ответ, большое вам спасибо за то, что нашли время, чтобы написать все это. Он работает отлично. «Задайте себе эту» часть определенно выяснила, на что я был смущен. Спасибо, так много! – Noowoo

+0

Как насчет того, если у вас больше 32? – cnzac

+0

@Abcdefg Как вы можете обнаружить конец столкновения в функции didEnd? – Marin

Смежные вопросы