添加可绘制对象层以将逻辑与图形分开

时间:2012-08-20 20:48:20

标签: c++ rtti

我正在尝试编写经典的蛇游戏。我有逻辑工作(吃饭,成长动作等)。现在我想添加一些漂亮的图形。到目前为止,我使用此代码制作了一些丑陋的图形: (伪代码)

void drawWorld(const std::vector<Tileable*> world_map) {
    for each Tileable {
         get position of Tileable
         get color of Tileable
         draw rectangle at position with color
    }
}

Class Tileable表示Snakes地图上的对象 - &gt;苹果,墙甚至蛇本身。它存储物体位置,当蛇与物体碰撞时会发生什么等等 - &gt;逻辑。

BUT

如果苹果是圈子而不是矩形,那么它会很好吗?

所以我想添加类Drawable与方法.draw()和派生类DrawableSnake,DrawableApple,DrawableWall,DrawableWhatever,每个都有自己的draw()方法。 问题是将Tielable子类从集合world_map转换为Drawable的适当子类,具有以下内容:

void drawWorld(const std::vector<Tileable*> world_map) {
    for each Tileable {
         get drawable from tileable
         drawable.draw()
    }
}

我正在考虑使用像RTTI这样的工厂:(伪代码)

Drawable convertToDrawable(Tileable* tileable){
     if tileable is Apple return DrawableApple
     if tileable is Wall return DrawableWall
     etc.
}

有没有更好的方法可以做到这一点,而不使用RTTI?

1 个答案:

答案 0 :(得分:2)

这是设计游戏引擎时的常见问题。解决此问题的一种方法是转移到基于实体组件的系统。

苹果,墙壁和蛇都属于同一类 - “实体”。对于每个实体,您将附加组件列表。在你的情况下,'ComponentDrawable'可以是一个组件,'ComponentTileable'可能是另一个组件。在创建实体时,使用绘制该特定实体所需的数据初始化ComponentDrawable。

您需要一种方法从实体中获取特定类型的组件。一个简单的系统可以让每个实体都有一个组件指针数组。每个组件类型在该数组中都有一个唯一索引。数组中的空槽将具有NULL值。

template<typename T> T* getComponent( Entity *entity ) {
    entity.component_array[T::index]
}

然后你修改过的伪代码示例最终会看起来像这样:

void drawWorld(const std::vector<Entity*> world_map) {
    for each entity in world_map {
         ComponentDrawable *drawable = getComponent<ComponentDrawable>( entity )
         if( drawable )
             drawable->draw()
    }
}

有些人喜欢将功能保留在组件之外,只将它们用作数据载体。如果您想要走这条路线,那么数据驱动系统可以使用ComponentDrawable中的数据来绘制每个实体的正确表示。