SpriteKit:检测完整的节点重叠

时间:2014-06-25 15:13:32

标签: ios sprite-kit skphysicsbody sknode

我有两个SKShapeNodes - 一个带有基于边缘的SKPhysicsBody,一个基于音量 - 我想要检测它们的交叉点而不会发生碰撞。我有这个工作正常,SKPhysicsContactDelegate联系方法被调用,因为一个经过另一个,但我的问题是当不再相交时,didEndContact被调用,即使是身体完全包含在另一个体内。确定真实接触或重叠的最佳方法是什么,而不仅仅是边缘交叉?我试过usesPreciseCollisionDetection,但没有用。

3 个答案:

答案 0 :(得分:7)

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 :(得分:4)

作为meisenman suggested,看起来最好的方法是使用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
    }
  }
}

答案 2 :(得分:0)

这些是关于swift 3的#meisenman示例的想法。不是通过掩码进行碰撞检测,而是说我们想要知道节点是否在节点内。使用#meisenman,节点的位置将用于每个节点。

Image Example of CGPoint's of two different nodes.

以下图片是我们实际想做的事情。

Image example of two CGPoint's within one another.

#meisenman使用的代码不需要SKPhysics。这是Swift 3.0中的代码

df['col_3'] = list(map( function, df['col_1'], df['col_2'],instance_of_class ))

def function(a,b,instance):
     return a + b + instance_of_class.attribute

我发现的唯一限制是,如果这些节点的中心不在所需节点的主体内,则此if语句将不为真。尚未通过设置节点的主体定义(掩码)来测试这一点。

我喜欢的是,能够在不同的功能或覆盖功能中使用这个if语句,这不仅仅限于“确实开始”#39;或者'触动了。'
Image example of two CGPoint's within one another, with possible limitations.