2014-06-25 6 views
2

У меня есть два SKShapeNodes - один с основанной на краях SKPhysicsBody, один на основе тома, и я хочу обнаружить их пересечение без столкновения. У меня это нормально работает, когда методы связи SKPhysicsContactDelegate получаются вызываемыми, поскольку один передает их другому, но моя проблема заключается в том, что didEndContact вызывается, когда края больше не пересекаются, даже если одно тело полностью находится внутри другого. Каков наилучший способ определить истинный контакт или перекрытие, а не только пересечение края? Я пробовал usesPreciseCollisionDetection, но безрезультатно.SpriteKit: обнаружение полного перекрытия узлов

+0

Как насчет добавления ребенка с альфой в 0 и использовать его как часть логической проверки? вы не увидите его, но он будет постоянно сталкиваться ...и в вашем didBeginContact вы должны попробовать оператор switch, вы можете сказать, какие объекты сталкиваются, а не делать подсчет всех касаний. –

ответ

3

Как meisenmansuggested, это лучший способ сделать это, используя метод containsPoint для определения перекрытия истинных узлов. Документы утверждают, что это «возвращает логическое значение, указывающее, находится ли точка внутри ограничивающего блока узла», но в моих экспериментах это выглядит так, что это работает и для вогнутых форм на основе края.

Так что, если я хочу, чтобы обнаружить, когда уже не два объекта перекрываются, то имеет смысл сделать containsPoint проверку в didEndContact - но оказывается didEndContact не вызывается, когда каждое ребро больше не пересекались, даже если другой край одного и того же форма все еще пересекает один и тот же объект. Например, мяч, выходящий из прямоугольника через его угол, даст дваdidEndContact событий. Поэтому необходимо сохранять абсолютное количество контактных событий (разницу между началом и концом) и проверять только сдерживание, когда этот счет равен нулю.

Мое решение, в Swift:

var _contactCount = 0 

func didBeginContact(contact: SKPhysicsContact!) { 
    if ((contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (CATEGORY_ONE | CATEGORY_TWO)) { 
    if (_contactCount == 0) { 
     // Contact is actually beginning 
    } 
    _contactCount += 1 
    } 
} 

func didEndContact(contact: SKPhysicsContact!) { 
    if ((contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (CATEGORY_ONE | CATEGORY_TWO)) { 
    _contactCount -= 1 
    let overlap = contact.bodyA.node.containsPoint(contact.bodyB.node.position) || contact.bodyB.node.containsPoint(contact.bodyA.node.position) 
    if (!overlap && _contactCount == 0) { 
     // Contact is actually ending 
    } 
    } 
} 
+0

Хорошая работа! Рад, что вы нашли полный ответ! – meisenman

6
CGPoint locObj1 = [sprite1 locationInNode:self]; 
CGPoint locObj2 = [sprite2 locationInNode:self]; 

if([sprite1 containsPoint: locObj2]) return; 
if([sprite2 containsPoint: locObj1]) return; 

Добавить это в начало didBeginContact и didEndContact. Это проверяет, содержит ли один из узлов другой узел. Если это так, он ничего не делает, что облегчит вашу проблему didBeginContact и didEndContact, который будет вызван. Я не на своем mac, поэтому вам может понадобиться немного сыграть с синтаксисом. Надеюсь, это приведет вас в правильном направлении.

+1

Спасибо за идею! Взгляды из документов, таких как 'containsPoint', возвращают логическое значение, указывающее, находится ли точка внутри ограничивающей рамки узла." Я обеспокоен тем, что это может быть недостаточно точным для моего варианта использования (т. Е. Только для проверки ограничивающей рамки для потенциально вогнутых структур на основе краев). Однако я не могу найти более строгую альтернативу 'containsPoint'. – man1

+0

У одного из ваших узлов должен быть физический корпус на основе края? – meisenman

+0

Yep - к сожалению, похоже, что тела, основанные на объеме, должны быть определены как выпуклые многоугольники, а фигуры, с которыми я работаю, иногда могут быть вогнутыми. – man1

0

Это мои мысли на #meisenman например, для быстрой 3. Вместо обнаружения столкновений через маску, скажем, мы хотели бы знать, если узел находится внутри узла , С #meisenman местоположение узла используется для каждого.

Image Example of CGPoint's of two different nodes.

Это следующее изображение того, что мы на самом деле то, что я хочу сделать.

Image example of two CGPoint's within one another.

Код #meisenman использует не требует SKPhysics. Вот код в Swift 3.0

let Object_1: CGPoint! = Sprite_Object_1.position 
//this obtains the location of the sprite node, through CGPoint. 
if Object_Sprite_2.contains(Object_1){ 
    print("Then it is true, object 2 is within the location of object 1") 
} 

Единственные ограничения, которые я нашел в том, что если центр этих узлов не в теле нужного узла, то это, если заявление не будет правдой. Это не было проверено установкой защиты тела узла (маска).

Что мне нравится, имеет возможность использовать это утверждение if в разных функциях или переопределять fuctions, это не ограничивается только «началось» или «тронуло перемещение».
Image example of two CGPoint's within one another, with possible limitations.

+0

Также примечание. В объекте 3 показан пример ограничений этого альтернативного метода. –

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