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();
            }
        }
我知道可能有更好的方法来进行冲突,但是我只是一个初学者,而且还没有发现任何地方可以解释如何很好地进行监听器和回调,使我理解。我的问题是,只要玩家身体进入上方的紫色框,GetContactCount()就会显示联系人。显然,将创建一个包含白色矩形的矩形边界框。 我尝试过将灯具做成EdgeShape,并且发生了同样的事情。有人知道这里发生了什么吗?我真的很想撞钉,这样我就可以继续其他事情了。非常感谢您的帮助。     

解决方法

        边界框是AABB(轴对齐的边界框),这意味着它将始终与笛卡尔轴对齐。 AABB通常用于广相碰撞检测,因为它是一个相对简单(且便宜)的计算。 如果要获得更准确的结果(如米卡指出,不是像素完美的),则需要确保针对对象的OBB(定向边界框)进行测试。 另外,我也同意米卡(Micah)的回答,即您很可能需要一个更通用的系统来处理碰撞。即使您只有墙壁和播放器,也无法保证哪个对象将是A,哪个对象将是B。而且,当您添加其他对象类型时,这将很快解散。     ,        从文档(添加到尝试处理您的情况)开始,创建联系人侦听器并不十分困难:
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 */ }
};
这要求您在播放器的灯具的用户数据字段中分配“ 3”。然后,您可以像这样使用联系人监听器:
m_Physics->GetWorld()->SetContactListener(new MyContactListener(m_Player));
    ,        您怎么知道GetFixtureA是玩家,B是墙?可以逆转吗?可以有一个FixtureC吗?我认为您将需要一个更通用的解决方案。 我使用了类似的图形框架(Qt),它具有某些功能,因此您可以抓取任何两个对象并调用类似“ hasCollided \”的名称,这将返回布尔值。您可以不使用回调而逃脱,只需在drawScene()中调用它或定期检查它即可。     ,        在Box2D中,接触的存在仅意味着两个夹具的AABB重叠。这并不一定意味着固定装置本身的形状相互接触。 您可以使用联系人的IsTouching()函数来检查形状是否确实在触摸,但是处理冲突的首选方法是使用回调功能让引擎在两个夹具开始/停止触摸时告诉您。从长远来看,使用回调会更高效且更易于管理,尽管最初设置可能会花费更多精力,并且需要注意一些事项-请参见此处的示例:http:// www。 iforce2d.net/b2dtut/collision-callbacks