如何高效使用dynamic_cast?
How to use dynamic_cast efficiently?
有一个抽象class Entity
,其他class像Player
和Enemy
都是从它继承的。当游戏检测到实体之间发生碰撞时,将调用以下方法:
void handleCollision(Entity* ent1, Entity* ent2) {
if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Enemy*>(ent1) || dynamic_cast<Enemy*>(ent2)) {
//player <-> enemy collision
}
else if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Projectile*>(ent1) || dynamic_cast<Projectile*>(ent2)) {
//player <-> projectile collision
}
else if () {
//...
}
else if() {
//...
}
}
每个实体在与另一个实体碰撞时都有独特的行为,这取决于实体的类型(玩家、敌人等),这就是为什么我需要检查实体之间所有可能的组合,如上所示。但我不喜欢它创建一个巨大的 else if 链,其中每个实体都被多次检查。还有其他方法吗?
使用Entity
class中定义的虚函数来唯一标识派生的class是Player还是Enemy 。这也是避免任何运行时错误的好习惯。
enum EntityType { Entity, Player, Enemy}
在实体中class定义这样一个虚函数,
virtual EntityType getType (return Entity;)
并相应地在两个 class 中覆盖该函数。
试图扩展 Ben Voigt 关于 多个虚拟调度 的评论,大致如下:
void handleCollision(Entity* ent1, Entity* ent2)
{
ent1->collide_with(ent2);
}
其中:
class Entity
{
public:
virtual void collide_with(Entity*) = 0; // Dispatcher
virtual void handle_collision_with(Entity*) {}
virtual void handle_collision_with(class Player*) {}
virtual void handle_collision_with(class Enemy*) {}
virtual void handle_collision_with(class Projectile*) {}
};
class Player : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Entity* other) override
{
// Unhandled entity
}
virtual void handle_collision_with(Player* other) override
{
// Handle collision player-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision player-projectile
}
};
class Enemy : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Enemy* other) override
{
// Handle collision enemy-enemy
}
virtual void handle_collision_with(Player* player) override
{
// Handle collision enemy-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision enemy-projectile
}
};
class Projectile : public Entity
{...}
有一个抽象class Entity
,其他class像Player
和Enemy
都是从它继承的。当游戏检测到实体之间发生碰撞时,将调用以下方法:
void handleCollision(Entity* ent1, Entity* ent2) {
if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Enemy*>(ent1) || dynamic_cast<Enemy*>(ent2)) {
//player <-> enemy collision
}
else if (dynamic_cast<Player*>(ent1) || dynamic_cast<Player*>(ent2) &&
dynamic_cast<Projectile*>(ent1) || dynamic_cast<Projectile*>(ent2)) {
//player <-> projectile collision
}
else if () {
//...
}
else if() {
//...
}
}
每个实体在与另一个实体碰撞时都有独特的行为,这取决于实体的类型(玩家、敌人等),这就是为什么我需要检查实体之间所有可能的组合,如上所示。但我不喜欢它创建一个巨大的 else if 链,其中每个实体都被多次检查。还有其他方法吗?
使用Entity
class中定义的虚函数来唯一标识派生的class是Player还是Enemy 。这也是避免任何运行时错误的好习惯。
enum EntityType { Entity, Player, Enemy}
在实体中class定义这样一个虚函数,
virtual EntityType getType (return Entity;)
并相应地在两个 class 中覆盖该函数。
试图扩展 Ben Voigt 关于 多个虚拟调度 的评论,大致如下:
void handleCollision(Entity* ent1, Entity* ent2)
{
ent1->collide_with(ent2);
}
其中:
class Entity
{
public:
virtual void collide_with(Entity*) = 0; // Dispatcher
virtual void handle_collision_with(Entity*) {}
virtual void handle_collision_with(class Player*) {}
virtual void handle_collision_with(class Enemy*) {}
virtual void handle_collision_with(class Projectile*) {}
};
class Player : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Entity* other) override
{
// Unhandled entity
}
virtual void handle_collision_with(Player* other) override
{
// Handle collision player-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision player-projectile
}
};
class Enemy : public Entity
{
public:
virtual void collide_with(Entity* other) override
{
other->handle_collision_with(this);
}
virtual void handle_collision_with(Enemy* other) override
{
// Handle collision enemy-enemy
}
virtual void handle_collision_with(Player* player) override
{
// Handle collision enemy-player
}
virtual void handle_collision_with(Projectile* projectile) override
{
// Handle collision enemy-projectile
}
};
class Projectile : public Entity
{...}