重构用于绘制游戏组件的代码

时间:2012-03-07 08:15:43

标签: c++ architecture refactoring

如何折射以下内容,将我的绘图函数从h文件移动到GraphicsManager类中?

//drawingFunctions.h
void drawTexturedQuad( Texture texture, Vector2 pos, Vector2 dim) {
    // bind texture...
    glBegin(...);    // draw  
    //...
    glEnd(...);
}

//class file
#include "drawingFunctions.h"
class Player { 
    void drawPlayer(){ drawTexturedQuad( texture, pos, dim) } 
};
class Enemy { 
    void drawEnemy(){ drawTexturedQuad( texture, pos, dim) } 
};
class Item { 
    void drawItem(){ drawTexturedQuad( texture, pos, dim) } 
};
// and so on for the other components

//gameloop file
// instantiate components objects
while (true) {
    // input, logic
    Player.drawPlayer();
    Enemy.drawEnemy();
    Item.drawItem();
    // and so on
}

(代码显然是简化的,我只是在这里询问绘图)

我应该......

  • 将指向GraphicsManager的指针传递给gameloop中的drawPlayer,drawEnemy等每次调用
  • 让Player,Enemy等有一个指向GraphicsManger的指针作为数据成员
  • 让Player,Enemy等扩展一个drawableGameComponent类,该类具有指向GraphicsManager作为数据成员的指针
  • 别的什么?

3 个答案:

答案 0 :(得分:1)

这听起来像是继承的完美用例:

class Drawable
{
public:
    void draw()
    {
         // gl stuff
    }

protected:
     Texture _texture;
     Vector2 _pos;
     Vector2 _dim;
};


class Player : Drawable
{
public:
     // should modify _texture _pos and _dim somewhere.       
};

// same thing for the other objects.

答案 1 :(得分:1)

我会将渲染器传递给模型,并让它自己绘制。

class Player
{
public:
    void draw(Renderer& renderer);
};

class Enemy
{
public:
    void draw(Renderer& renderer);
};

请注意,您无需为函数drawPlayerdrawEnemy命名,因为您已经知道类类型为PlayerEnemy。这种统一调用约定非常适合提取到一个公共接口:

class Model
{
public:
    virtual void draw(Renderer& renderer) = 0;

    virtual ~Model() {}
};

然后,您可以让每个模型继承自Model,并且每个模型都继承draw

正如我在@J.N.的回答中提到的那样,你也可以让Renderer成为一个抽象类。例如,我参与了一个使用OpenGL,GDI +的项目,还需要创建原理图的打印输出。

class Renderer
{
public:
    virtual render(const Triangle& triangle, const Texture& texture) = 0;

    virtual ~Renderer() {}
};

答案 2 :(得分:0)

我会选择第一种可能性:将指针传递给调用中的GraphicsManager 。虽然看起来有点矫枉过正,但使用GraphicsManager的知识仍保持在更高的水平,以后可以更容易地修改。

说完这个之后,我仍然会从Drawable接口继承并将需要绘制的项目放在容器中,因此您可以通过虚拟drawItem()函数迭代它来显示项目。 像这样(C ++ 03,未经测试):

std::vector<Drawable*> Items;
Items.push_back(&player);
Items.push_back(&enemy);
...
for (std::vector<Drawable*>::iterator it = Items.begin(); it != Items.end(): ++it)
{
  (*it)->drawItem(&graphMgr);
}