0

有一个抽象类Entity,其他类喜欢PlayerEnemy继承自它。当游戏检测到实体之间的碰撞时,会调用以下方法:

    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 链,每个实体都被检查多次的事实。还有另一种方法吗?

4

2 回答 2

1

试图扩展 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
{...}

来源:a-polyglots-guide-to-multiple-dispatch

于 2021-04-23T19:28:58.347 回答
-1

使用Entity类中定义的虚函数来唯一标识派生类是Player还是Enemy。这也是避免任何运行时错误的好习惯。

 enum EntityType { Entity, Player, Enemy}

在 Entity 类中定义一个像这样的虚函数,

virtual EntityType getType (return Entity;)

并相应地覆盖两个类中的函数。

于 2021-04-23T18:28:42.850 回答