Ios SpriteKit:检测完整的节点重叠

Ios SpriteKit:检测完整的节点重叠,ios,sprite-kit,skphysicsbody,sknode,Ios,Sprite Kit,Skphysicsbody,Sknode,我有两个SkshapeNode,一个是基于边缘的SKPhysicsBody,一个是基于体积的SkshapeNode,我想在不发生碰撞的情况下检测它们的交点。我已经很好地实现了这一点,当一个实体经过另一个实体时调用SKPhysicContactDelegate contact方法,但我的问题是当边不再相交时调用didEndContact,即使一个实体完全包含在另一个实体中。确定真正接触或重叠的最佳方法是什么,而不仅仅是边缘相交?我尝试了使用PreciseCollisionDetection,但没有

我有两个SkshapeNode,一个是基于边缘的SKPhysicsBody,一个是基于体积的SkshapeNode,我想在不发生碰撞的情况下检测它们的交点。我已经很好地实现了这一点,当一个实体经过另一个实体时调用SKPhysicContactDelegate contact方法,但我的问题是当边不再相交时调用
didEndContact
,即使一个实体完全包含在另一个实体中。确定真正接触或重叠的最佳方法是什么,而不仅仅是边缘相交?我尝试了
使用PreciseCollisionDetection
,但没有效果

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

if([sprite1 containsPoint: locObj2]) return;
if([sprite2 containsPoint: locObj1]) return;
将此添加到didBeginContact和didEndContact的开头。这将检查其中一个节点是否包含另一个节点。如果它这样做了,它不会减轻你的didBeginContact和didbendcontact被不必要地调用的问题。我不在我的mac电脑上,所以你可能需要稍微使用一下语法。希望这能给你带来正确的方向

As,看起来最好的方法是使用
containsPoint
方法来确定真正的节点重叠。文档声明这“返回一个布尔值,指示点是否位于节点的边界框内”,但在我的实验中,这似乎也适用于基于凹边的形状

因此,如果我想检测两个对象何时不再重叠,在
didEndContact
中执行
containsPoint
检查是有意义的,但结果是当每条边不再相交时,即使相同形状的另一条边仍与同一对象相交,也会调用
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
    }
  }
}
以下是我对《斯威夫特3》的梅森曼例子的看法。假设我们想知道节点是否在节点内部,而不是通过遮罩进行碰撞检测。使用#meisenman,节点的位置将用于每个节点

下面这张图就是我们想要做的

梅森曼使用的代码不需要物理。这是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语句将不为true。这尚未通过设置节点的主体定义(掩码)进行测试

我喜欢的是,能够在不同的函数或函数中使用这个if语句,这不仅限于“did begin”或“touch moved”。

谢谢你的主意!从文档中查看,如
containsPoint
“返回一个布尔值,该值指示一个点是否位于节点的边界框内。”我担心这对于我的用例来说可能不够准确(即,仅测试边界框中潜在的凹边实体)。但是,我找不到比
containsPoint
更严格的替代方案。你的一个节点必须有一个基于边的物理体吗?是的–不幸的是,基于体积的实体需要定义为凸多边形,而我正在处理的形状有时可能是凹的。你所处的困境非常有趣。我将继续寻找解决方案,因为我认为SpriteKit不应该/不会受到这样的限制。我认为spriteKit社区应该对这篇文章更感兴趣,并且可能有人会通过。。。一个定制的containsPoint可以满足您的凸面形状要求。我一直在尝试这个,我认为文档是错误的!containsPoint似乎可以处理凸多边形(至少在我的上下文中,并且使用iOS 8),但我还需要考虑一个更复杂的问题。我将对此进行投票,然后为遇到此问题的其他人发布更完整的答案。干得好!很高兴你找到了完整的答案!将alpha值添加到0的子级并将其用作逻辑检查的一部分如何?你看不到它,但它会一直在碰撞……在你的didBeginContact中,你应该尝试一个switch语句,你可以告诉那里哪些对象正在碰撞,而不是对所有的接触进行计数。另外,请注意,对象3显示了这个替代方法的局限性示例。