2 つの SKShapeNodes があり、1 つはエッジ ベースの SKPhysicsBody、もう 1 つはボリューム ベースで、衝突することなくそれらの交差を検出したいと考えています。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 の先頭に追加します。これは、ノードの 1 つに他のノードが含まれているかどうかを確認します。その場合、didBeginContact と didEndContact が不必要に呼び出されるという問題を軽減するものは何もしません。私は自分の Mac を使用していないので、構文を少しいじる必要があるかもしれません。これがあなたを正しい方向に導くことを願っています。
meisenman が示唆したように、これを行う最良の方法は、containsPoint
メソッドを使用して真のノードの重なりを判断することです。ドキュメントには、これは「ポイントがノードの境界ボックス内にあるかどうかを示すブール値を返す」と記載されていますが、私の実験では、これは凹状のエッジベースの形状でも機能するようです。
containsPoint
したがって、2 つのオブジェクトが重なり合っていないことを検出したい場合は、内部でチェックを行うのが理にかなっていますが、同じ形状の別のエッジがまだ同じオブジェクトと交差している場合でも、各エッジが交差しなくなったときに呼び出されるdidEndContact
ことがわかります。didEndContact
たとえば、四角形の角からボールが出ると、2 つの 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 ステートメントは正しくないということです。これは、ノードのボディ定義 (マスク) を設定してテストされていません。
私が気に入っているのは、この if ステートメントをさまざまな関数全体で使用したり、関数をオーバーライドしたりできることです。これは、「開始した」または「移動したタッチ」だけに限定されません。