我正在用C ++构建一个简单的2D游戏,并使用Box2D进行碰撞检测。
我有一个Entity
类,从中派生一个Enemy
和Bullet
类,而一个EnemySquare
类派生自Enemy
类。 / p>
我正在尝试检测EnemySquare类和Bullet
类之间的冲突(将有更多冲突组合在以后的开发中进行处理)。为此,我创建了一个CollisionManager
类,它是从Box2D类b2ContactListener
派生的,该类处理碰撞回调。
每个Entity
实例都有一个私有变量m_collisionObjectType
,它是对象类型的enum class
(如下所示)。
在BeginContact()
回调中,我试图将box2d灯具的用户数据转换为正确的类类型,以便可以施加损坏,标记要删除的项目符号等。
(为简化起见,删除了无关代码)
对象类型枚举:
enum class COLLISION_OBJECT_TYPE {BULLET, ENEMY, PLAYER};
实体类
.h
class Entity
{
public:
Entity();
~Entity();
COLLISION_OBJECT_TYPE getCollisionObjectType() { return m_collisionObjectType; }
protected:
b2Body* m_body = nullptr;
b2Fixture* m_fixtures[3];
COLLISION_OBJECT_TYPE m_collisionObjectType;
};
敌对阶级
.h
class Enemy : public Entity
{
public:
Enemy();
~Enemy();
virtual void init(glm::vec2 position, float health, float speed, Player* player, b2World* physicsWorld) = 0;
virtual void update(float deltaTime) = 0;
protected:
float m_health;
float m_speed;
Player* m_playerTarget;
};
敌方广场
.h
class EnemySquare : public Enemy
{
public:
EnemySquare();
~EnemySquare();
void init(glm::vec2 position, float health, float speed, Player* player, b2World* physicsWorld) override;
void update(float deltaTime) override;
};
.cpp
void EnemySquare::init(glm::vec2 position, float health, float speed, Player * player, b2World* physicsWorld) {
// init physics body
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(m_position.x, m_position.y);
bodyDef.fixedRotation = false;
bodyDef.angle = 0;
bodyDef.userData = this;
m_body = physicsWorld->CreateBody(&bodyDef);
// init physics fixtures
b2PolygonShape squareShape;
squareShape.SetAsBox(m_width * 0.5f, m_height * 0.5f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &squareShape;
m_fixtures[0] = m_body->CreateFixture(&fixtureDef);
}
子弹班
.h
class Bullet : public Entity
{
public:
Bullet(
b2World* world,
glm::vec2 startPosition,
glm::vec2 direction,
Tempest::glTexture texture,
float width,
float height,
float damage,
float speed,
float range
);
~Bullet();
// methods are unrelated
private:
// private variables are unrelated
};
.cpp
Bullet::Bullet(
b2World* world,
glm::vec2 startPosition,
glm::vec2 direction,
Tempest::glTexture texture,
float width,
float height,
float damage,
float speed,
float range
) {
// Make the body
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(m_position.x, m_position.y);
bodyDef.fixedRotation = true;
bodyDef.angle = 0;
bodyDef.userData = this;
m_body = world->CreateBody(&bodyDef);
// Create the box
b2PolygonShape boxShape;
boxShape.SetAsBox(m_height * 0.4f, m_width * 0.5f);
b2FixtureDef boxDef;
boxDef.shape = &boxShape;
m_fixtures[0] = m_body->CreateFixture(&boxDef);
m_collided = false;
m_collisionObjectType = COLLISION_OBJECT_TYPE::BULLET;
}
在我的CollisionManager
类中,我试图检索碰撞夹具的userData(它是一个void *),然后将其转换为Entity*
以调用getCollisionObjectType()
方法。当我知道我要处理的是哪种类型的实体时,我想将其转换为正确的对象类型,并执行诸如施加损坏,标记要删除的项目符号之类的操作。
void CollisionManager::BeginContact(b2Contact * contact) {
void* fixtureABodyData = contact->GetFixtureA()->GetBody()->GetUserData();
void* fixtureBBodyData = contact->GetFixtureB()->GetBody()->GetUserData();
if (fixtureABodyData && fixtureBBodyData) {
Entity* fixtureAData = static_cast<Entity*>(fixtureABodyData);
Entity* fixtureBData = static_cast<Entity*>(fixtureBBodyData);
if (fixtureAData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::BULLET) {
std::cout << "A BULLET" << std::endl;
}
if (fixtureBData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::BULLET) {
std::cout << "B BULLET" << std::endl;
}
if (fixtureAData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::ENEMY) {
std::cout << "A ENEMY" << std::endl;
}
if (fixtureBData->getCollisionObjectType() == COLLISION_OBJECT_TYPE::ENEMY) {
std::cout << "B ENEMY" << std::endl;
}
std::cout << "----------------------" << std::endl;
}
}
由于某种原因,演员表只能用于Bullet类,而不能用于Enemy类。我认为它返回了nullptr
。所以我知道一个碰撞的物体是一颗子弹,但是我无法分辨第二个物体是什么。
我感觉static_cast
调用有问题,或者是因为EnemySquare类两次从Entity类中删除了?否则我在Box2D代码中可能做错了什么。任何建议将不胜感激!
答案 0 :(得分:0)
为m_collisionObjectType
派生类设置Enemy
成员变量。最好是COLLISION_OBJECT_TYPE::ENEMY
。
如代码现在所示,它只是在m_collisionObjectType
派生类的代码中设置Bullet
。因此,Enemy
派生的类实例是在其m_collisionObjectType
成员变量未初始化的情况下构造的。即getCollisionObjectType()
方法中的值可以是m_collisionObjectType
的内存位置在构造函数使用之前的值。
希望这会有所帮助!