2011-06-09 12 views
2

ゼロG空間のゲームで衝突を検出するのに苦労しています。うまくいけば、この画像は私が説明するのに役立ちます:Box2Dは、角のある線のボディーの周りに四角いバウンディングボックスを作成します。

http://i.stack.imgur.com/f7AHO.png

白い長方形のような、添付b2PolygonShape器具と静的なボディです:

// Create the line physics body definition 
b2BodyDef wallBodyDef; 
wallBodyDef.position.Set(0.0f, 0.0f); 

// Create the line physics body in the physics world 
wallBodyDef.type = b2_staticBody; // Set as a static body 
m_Body = world->CreateBody(&wallBodyDef); 

    // Create the vertex array which will be used to make the physics shape 
b2Vec2 vertices[4]; 
vertices[0].Set(m_Point1.x, m_Point1.y); // Point 1 
vertices[1].Set(m_Point1.x + (sin(angle - 90*(float)DEG_TO_RAD)*m_Thickness), m_Point1.y - (cos(angle - 90*(float)DEG_TO_RAD)*m_Thickness)); // Point 2 
vertices[2].Set(m_Point2.x + (sin(angle - 90*(float)DEG_TO_RAD)*m_Thickness), m_Point2.y - (cos(angle - 90*(float)DEG_TO_RAD)*m_Thickness)); // Point 3 
vertices[3].Set(m_Point2.x, m_Point2.y); // Point 3 
int32 count = 4; // Vertex count 

b2PolygonShape wallShape; // Create the line physics shape 
wallShape.Set(vertices, count); // Set the physics shape using the vertex array above 

// Define the dynamic body fixture 
b2FixtureDef fixtureDef; 
fixtureDef.shape = &wallShape; // Set the line shape 
fixtureDef.density = 0.0f; // Set the density 
fixtureDef.friction = 0.0f; // Set the friction 
fixtureDef.restitution = 0.5f; // Set the restitution 

// Add the shape to the body 
m_Fixture = m_Body->CreateFixture(&fixtureDef); 
m_Fixture->SetUserData("Wall");[/code] 

あなたはそれを作ることを私を信頼する必要があります画像の形。物理シミュレーションは完全に機能し、プレーヤー(小さな三角形)はピクセルで完璧な精度でボディに衝突します。しかし、私は健康と無意味を取り除くことができるように、いつ衝突が起きたかを判断しようとすると問題になります。次のように私はこれを使用していたコードは次のとおりです。

/*------ Check for collisions ------*/ 
     if (m_Physics->GetWorld()->GetContactCount() > 0) 
     { 
      if (m_Physics->GetWorld()->GetContactList()->GetFixtureA()->GetUserData() == "Player" && 
       m_Physics->GetWorld()->GetContactList()->GetFixtureB()->GetUserData() == "Wall") 
      { 
       m_Player->CollideWall(); 
      } 
     } 

私は衝突を行うには、おそらくより良い方法がある承知だけど、私はただの初心者だとリスナーを行う方法を説明しているどこにも発見していません私が理解するのに十分なコールバックがあります。私が持っている問題は、Player本体が上記の紫色のボックスに入るたびにGetContactCount()が連絡先を表示することです。明らかに、白色矩形を包含する矩形の境界ボックスが作成されている。

私は什器をEdgeShapeにしようとしましたが、同じことが起こります。誰がここで何が起こっているか考えているのですか?私は本当に他のものに移動することができるように衝突を釘付けにしたいと思います。助けてくれてどうもありがとう。

答えて

2

バウンディングボックスは、常にデカルト軸と整列することを意味するAABB(軸に沿って配置されたバウンディングボックス)です。 AABBは、比較的単純な(かつ安価な)計算であるため、通常、広帯域衝突検出に使用されます。

ミカが指摘したように、より正確な(ただし完全なピクセルではない)結果を望む場合は、オブジェクトのOBB(方向付けされた境界ボックス)に対してテストする必要があります。

また、Micahの答えには、衝突を処理するためのより一般的なシステムが必要である可能性が高いことに同意します。たとえ壁とプレイヤーだけしか持っていないとしても、どのオブジェクトがAになり、Bになるかは保証されません。また、他のオブジェクトタイプを追加すると、これはすぐに解消されます。

+0

三角形が衝突することについて完全なピクセルであることを望む場合、バウンディングボックスのソリューションは機能しない可能性があります。たぶんそれは彼が気にするものではありません...私は彼を正しく読んでいるとは確信していません。 – micahhoover

+0

良い点。私もどちらか分かりませんでした。そのライブラリでの検出を処理するには、おそらくより良い方法がありますが、あまりよく知っているわけではありません。 –

0

GetFixtureAがプレーヤーであり、Bが壁であることをどのように知っていますか?逆転できますか? FixtureCはありますか?私はもっ​​と汎用的なソリューションが必要だと思います。

私はこれと同様のグラフィックスフレームワーク(Qt)を使用しています。これは何かを持っていて、2つのオブジェクトをつかんで、 'hasCollided'のようなものを呼び出すとboolを返します。あなたはコールバックを使わずに、ただdrawScene()で呼び出したり、定期的にチェックしたりすることができます。接触リスナーを作成

2

は(あなたの状況に対処しようとするために追加された)ドキュメントから、それほど難しいことではありません。

class MyContactListener:public b2ContactListener 
{ 
private: 
    PlayerClass *m_Player; 

public: 
    MyContactListener(PlayerClass *player) : m_Player(player) 
    { } 

    void BeginContact(b2Contact* contact) 
    { /* handle begin event */ } 

    void EndContact(b2Contact* contact) 
    { 
     if (contact->GetFixtureA()->GetUserData() == m_Player 
     || contact->GetFixtureB()->GetUserData() == m_Player) 
     { 
      m_Player->CollideWall(); 
     } 
    } 

    /* we're not interested in these for the time being */ 

    void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) 
    { /* handle pre-solve event */ } 

    void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) 
    { /* handle post-solve event */ } 
}; 

これは、プレイヤーのフィクスチャのユーザデータフィールドにm_Playerを割り当てる必要があります。接触の存在はちょうど2つの固定具のAABBsが重なっていることを意味しBOX2Dで

m_Physics->GetWorld()->SetContactListener(new MyContactListener(m_Player)); 
+0

正確に正しい。また、OPについては、PhysicsEditor(physicseditor.de)をチェックしてください。本当に簡単にできます。 –

0

:次に、あなたはそうのような接触リスナーを使用することができます。これは、必ずしも器具自体の形状が触れていることを意味するものではありません。

連絡先のIsTouching()関数を使用して形状が実際に接触しているかどうかを確認できますが、衝突を処理するための好ましい方法は、コールバック機能を使用して、2つのフィクスチャが開始/触れる。コールバックを使用すると、最初に設定するのに少し手間がかかるかもしれませんが、長期的に管理する方がはるかに効率的で簡単です。例についてはここを参照してください。http://www.iforce2d.net/b2dtut/collision-callbacks

関連する問題