我有两个 SKShapeNode——一个带有基于边缘的 SKPhysicsBody,一个基于体积——我想检测它们的交叉点而不会发生碰撞。我的工作正常,当一个人越过另一个人时调用 SKPhysicsContactDelegate 接触方法,但我的问题是当边缘不再相交didEndContact
时被调用,即使一个身体完全包含在另一个身体中。确定真正接触或重叠的最佳方法是什么,而不仅仅是边缘相交?我试过了,没有用。usesPreciseCollisionDetection
3 回答
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 上,所以您可能需要稍微使用一下语法。希望这会让您朝着正确的方向前进。
正如meisenman 建议的那样,看起来最好的方法是使用该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
}
}
}
这些是我对 swift 3 的#meisenman 示例的想法。假设我们想知道节点是否在节点内,而不是通过掩码进行碰撞检测。使用#meisenman,每个节点的位置都被使用。
下图是我们实际上想要做的。
#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 语句将不成立。这尚未通过设置节点的主体定义(掩码)进行测试。