绘制游戏组件的重构代码

Refactoring code for drawing game components

本文关键字:重构 代码 组件 游戏 绘制      更新时间:2023-10-16

如何折射以下内容,将绘图函数从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的指针传递到游戏循环中drawPlayer、drawEnemy等的每次调用
  • 让玩家、敌人等有一个指向GraphicsManager的指针作为数据成员
  • 让Player、Enemy等扩展一个drawableGameComponent类,该类具有指向GraphicsManager的指针作为数据成员
  • 还有别的吗

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

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.

我会将一个渲染器传递给模型,并要求它自己绘制。

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() {}
};

我会选择第一种可能性:在调用中将指针传递给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);
}