Farseerで非常に特殊な種類のジョイントを作成するにはどうすればよいですか?


7

編集する

問題は解決しました(Drackirの回答を参照)。これが私がこのジョイントで達成しようとしていたことのデモです。この他の質問のシナリオに関する詳細情報。


問題

Farseerで、次のように動作する非常に特殊なタイプのジョイントを作成しようとしています。

  • オブジェクトは、X軸とY軸の両方で常にオブジェクト間の距離を同じに保つ必要があります。
  • 移動-オブジェクトの1つとの衝突により、グループ全体が一緒に移動する必要がありますが、グループは回転してはなりません。トルクの結果として、個々のオブジェクトのみが中心の周りを回転できます。
  • 回転-オブジェクトは常に同じ回転でなければなりません。オブジェクトの1つとの衝突により、他のすべてのオブジェクトがまったく同じ量だけ回転するはずです。

ここに写真があります:

ここに画像の説明を入力してください

箱から出してFarseerでこれを実現する方法がない場合は、それを拡張して、このような動作をする新しいタイプの結合を作成するにはどうすればよいですか?基本的に私はすべてのボディが他のボディの「クローン」のように動作することを望みますが、それらの間のオフセットは固定されています。


この特定のシステムについてはわかりませんが、「ゴースト」のキネマティクスをオフにして、手動で移動/回転させることはできませんか?
テトラッド2011

ゴーストでの衝突も無効になりませんか?たぶん、幽霊はそれのための最高の類推ではなかったでしょう-おそらくクローン。
David Gouveia 2011

つまり、クローンとの衝突は、メインボディにも(まったく同じように)影響するはずです。その場合、あなたの提案はうまくいきますか?
David Gouveia

おそらく私を打ち負かしません。
テトラッド、2011

回答:


6

さて、約2時間のいじくりの後で、なんとかこれを行うことができました。あなたはおそらくこれをメソッド/クラスに抽出したいと思うでしょうが、基本的な考え方はこれです:

  1. オブジェクトの「ホルダー」ボディと呼ぶものを作成します。これらのボディは「オブジェクト」のサイズと位置を共有しますが、衝突には関与しません。基本的に、それらはクローンです。

    //Create "Main" (center) body
    _bodyMain = BodyFactory.CreateRectangle(World, 5f, 5f, 1f);
    _bodyMain.BodyType = BodyType.Dynamic;
    _bodyMain.Position = new Vector2(2, 2);
    //Create "MainHolder"
    _bodyMainHolder = BodyFactory.CreateRectangle(World, 5f, 5f, 1f);
    _bodyMainHolder.BodyType = BodyType.Dynamic;
    _bodyMainHolder.CollisionCategories = Category.None; //Prevents collisions
    _bodyMainHolder.Position = new Vector2(2, 2);
    _bodyMainHolder.IsSensor = true;
    //See http://farseerphysics.codeplex.com/discussions/222524 for why they're sensors
    _bodyMainHolder.FixedRotation = true;
    //Note: Only add FixedRotation for the main one, leave it off of the other
    //      holders. I'll explain later.
    
  2. を使用して各ホルダーを「mainHolder」に取り付けますWeldJoint。これは、彼らが互いに離れることを防ぎます。FixedRotationmainHolderの回転を防ぎます。farseerにバグがあるかどうかはわかりませんが、aを追加し WeldJointて両方のボディにがあるFixedRotation == trueと、ジョイントが正しく機能しません。これが、メインホルダーだけが持っている理由.FixedRotation = trueです。

    //Weld the holders together so they don't move. Assumes another holder is defined
    //  for the object on the right side (bodyRightHolder).
    JointFactory.CreateWeldJoint(World, _bodyMainHolder, _bodyRightHolder,
    _bodyRightHolder.Position - _bodyMainHolder.Position, Vector2.Zero);
    
  3. 「オブジェクト」本体を、RevoluteJoints を使用してそれぞれのホルダーに接続します。これにより、オブジェクトがホルダーにロックされますが、ホルダーは自由に回転できます。

    //Lock the actual bodies to the holders
    JointFactory.CreateRevoluteJoint(World, _bodyMainHolder, _bodyMain, Vector2.Zero);
    JointFactory.CreateRevoluteJoint(World, _bodyRightHolder, _bodyRight, Vector2.Zero);
    
  4. アングルジョイントを取り付けて、実際のオブジェクトの回転を互いに一致させます。注:オブジェクトのすべてのペアにアングルジョイントをアタッチする必要はありません。角度ジョイントをメインボディと他のボディに追加するだけで、回転がすべてのオブジェクトにわたって移動します。

    //Make them rotate the same as each other
    JointFactory.CreateAngleJoint(World, _bodyMain, _bodyRight);
    

それでおしまい!必要な他のオブジェクト/オブジェクトホルダーごとに追加のコードを追加するだけで、残りのコードが処理されます。これが私のテストを説明するための画像です:試験体の画像例。

ここで、緑色のボディがホルダーです。それらは回転したり衝突したりせず、一緒に溶接されます。黄色と赤のボディが「オブジェクト」です(黄色がメインです)。同じ量だけ回転し、それぞれのホルダーを中心に回転していることがわかります。また、赤と黄色のボディだけが衝突に参加します。これは上記の3つの条件をすべて満たしていると思います。

実例

Farseerの "Samples XNA"ソリューションをロードしてSimpleDemo1.cs( "Samples XNA"プロジェクト> "Samples"フォルダー)を見つけたら、テストするために書き直しました(コードはこちら)。

お役に立てれば。ご不明な点がありましたらお知らせください。


不足しているパズルのピースがまだ1つ不足しているようです。システム全体を瞬時に世界の別の場所移動する方法。画面の境界線の周りにオブジェクトを「ラップ」するには、これが必要です。メインホルダーの位置を合わせるだけでは機能しません。
David Gouveia、2012年

前の質問は気にしないでください。すべてのホルダーと本体を同時に移動することでうまくいくようです。
David Gouveia

助けてくれてうれしいです、そうです、あなたはすべての遺体を再配置する必要があります。これをクラスに組み込み、本体との相対位置(Vector2本体の位置と本体の差)を保存できます。次に、メインの位置を変更し、メインの位置との相対位置を更新します。
Richard Marskell-Drackir 2012年1

それは私がやったことのほとんどです。:)
デビッド・グベイア

0

残念ながら、私は今電話に出ているので、この回答を確認することはできません。

私はあなたが望むものを達成するためにいくつかの既存の関節を使用できると思います。三角形のコーナーに衝突ジオメトリのないボディを作成します。その後、3つの距離ジョイントを使用して、必要な移動を実現できます。次に、2つの衝突可能なボディを固定角度ジョイントで接続すると、それらは一緒に回転します。


私も今は少し時間が足りないので、今夜はやってみます。しかし、私の例では2つのボディしかありませんが、実際にはこれよりも複雑なものが必要で、代わりに9つのボディが接続されています。あなたのアイデアはまだ適用されますか?
David Gouveia

@David:それは...面白いですね。このセットアップで何を達成しようとしているのか、もっと詳しく教えていただけますか?あなたが望むものを達成するためのいくつかの代替方法がないのではないかと思います。
Ilmari Karonen、2011

@IlmariKaronen質問の最後に、達成しようとしていることを正確に説明する別の質問へのリンクがあります。基本的に私は、ボディが境界線を「ラップ」し、画面の複数の側面に同時に表示される2D環境で物理を正しく処理しようとしています。
David Gouveia

@Martinまだ今日これをテストする時間がないので、また明日報告します。
David Gouveia

さて、私は今これを試しましたが、うまくいきませんでした。問題は、システム全体が回転しないようにしたいことです。3つの距離のジョイント(2つの溶接ジョイントで置き換えることもできます)は、システムの剛性を維持しますが、回転を妨げません。
David Gouveia
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.