我在检测零G太空游戏中的碰撞时遇到了很多麻烦。希望这张图片能帮助我解释一下:
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,同样的事情发生了。有谁知道这里发生了什么?我真的很喜欢碰撞,所以我可以继续其他事情。非常感谢您的帮助。
答案 0 :(得分:2)
边界框是AABB(轴对齐边界框),这意味着它将始终与笛卡尔坐标轴对齐。 AABB通常用于广角碰撞检测,因为它是一种相对简单(且便宜)的计算。
如果你想要更精确(但不像Micah所指出的那样像素完美)结果,你需要确保你正在测试对象的OBB(定向边界框)。
另外,我同意Micah的回答,你很可能需要一个更通用的系统来处理碰撞。即使你只有墙和玩家,也不能保证哪个对象是A,哪个对象是B.当你添加其他对象类型时,这将很快解开。
答案 1 :(得分: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
分配给玩家的灯具用户数据字段。然后你就可以像这样使用联系人监听器:
m_Physics->GetWorld()->SetContactListener(new MyContactListener(m_Player));
答案 2 :(得分:0)
你怎么知道GetFixtureA是玩家而B是墙?可以逆转吗?可能有FixtureC吗?我认为你需要一个更通用的解决方案。
我使用了类似的图形框架(Qt),它有一些东西,所以你可以抓住任何两个对象并调用类似'hasCollided'的东西,它会返回一个bool。你可以逃避不使用回调,只需在drawScene()中调用它或定期检查它。
答案 3 :(得分:0)
在Box2D中,接触的存在只意味着两个灯具的AABB重叠。这并不一定意味着固定装置本身的形状正在接触。
您可以使用联系人的IsTouching()函数来检查形状是否实际接触,但处理碰撞的首选方法是使用回调功能让引擎在两个灯具开始/停止触摸时告诉您。从长远来看,使用回调更有效,更容易管理,但最初设置可能需要更多努力,有一些事项需要注意 - 请参阅此处的示例:http://www.iforce2d.net/b2dtut/collision-callbacks < / p>