在 C++ 中,不同的游戏实体应该有不同的类吗?还是应该在一个包含所有行为的类中?

esc*_*ter 5 c++ inheritance game-engine

我正在开发一个具有许多不同实体的游戏环境。每一个都有一些常见的功能(绘制、更新等),但有时游戏必须根据敌人的类型对它们进行不同的处理。到目前为止,我已经在他们的实例的类中编码了敌人的“类型”。所以,我们有这样的情况:

class MotionObject { ... };

class Entity : public MotionObject { ... };

class Coin : public Entity { ... };

class TextSign : public Entity { ... };

class ShapeEnemy : public Entity { ... };

class Attractor : public ShapeEnemy { ... };

class Bumper : public ShapeEnemy { ... };
Run Code Online (Sandbox Code Playgroud)

因此 Coin、TextSign、Attractor 和 Bumper 类是游戏中实例化的实体类型。为不同类型的实体使用不同的类感觉是正确的,但我无法摆脱这样的感觉,如果我只有一个实体类,可能会避免一些麻烦,其中包含一个 switch 语句,根据其“实体类型”控制其行为,存储在变量中的东西。玩家根据它们的类型以不同的方式与这些实体交互,我每次都使用 dynamic_cast 和空测试来确定应用了哪种行为。需要明确的是,这些是针对我无法在每个实体上调用简单 Update() 的行为;玩家将以特定方式做出响应,或者他们将进行实体间交互,所有这些都基于实体类型。我的代码如下所示:

void Game::Update(float deltaT) {

    for (int i =0; i < DrawChildren.size(); i++) {
        //each entity has its Update called
        DrawChildren[i].Update(deltaT);

        //What follows is code that the Game class needs to run based on the entity type.
        Coin * coin = dynamic_cast<Coin*>(DrawChildren[i]);
        if (coin != nullptr) {
            ...
            continue; //so no other type's code executes, in case I have inherited types.
        }

        TextSign * textSign = dynamic_cast<TextSign*>(DrawChildren[i]);
        if (textSign != nullptr) {
            ...
            continue; //so no other type's code executes, in case I have inherited types.
        }

        Attractor * attractor = dynamic_cast<Attractor*>(DrawChildren[i]);
        if (attractor != nullptr) {
            ...
            continue; //so no other type's code executes, in case I have inherited types.
        }

        Bumper * bumper = dynamic_cast<Bumper*>(DrawChildren[i]);
        if (bumper != nullptr) {
            ...
            continue; //so no other type's code executes, in case I have inherited types.
        }

    }

    ...

}
Run Code Online (Sandbox Code Playgroud)

有没有更简单的方法来做到这一点?

esc*_*ter 1

(这个问题最近似乎引起了一些关注,所以我将提供我自己开始使用的解决方案)。

我切换到实体组件系统,它非常棒。最初很难弄清楚制作组件的粒度级别,但做了几个月后我“明白”了它,并且无法想象回到类继承。

对于我的 ECS,我使用的是entityx。这有点令人沮丧,因为它依赖于 C++11,而我最终想在 Windows 上构建,但在我发现的所有 ECS 引擎中,它的语法对我来说似乎是最自然的。

我当前的组件类型是:

ParentComponent
Transformable
TranslateBounds
Drawable
Sprite
SpriteAnimation //gif-style
Velocity
Tags //a list of identifying strings
Animations
Run Code Online (Sandbox Code Playgroud)