SDL系列教程:第三章 游戏对象设计

每个游戏当中都会有很多的对象存在,例如玩家、敌人、非玩家角色(NPC)、陷阱、子弹等。将这些游戏对象关联起来是一项很复杂的工作,如果没有一个可靠的基础框架的话,我们的游戏会越来越笨拙,代码结构也会越来越混乱。所以我们可以完全利用面向对象编程(OOP)的力量来帮助我们实现可靠的基础框架。
我们将会在这一章介绍以下内容:

  • 使用继承
  • 实现多态
  • 使用抽象基类
  • 有效继承设计

使用继承

继承是OOP第一种强大的特性,这个特性可以帮助我们开发可复用的基础框架。通过使用继承,我们可以从现有类型当中创建新的子类。我们在这里不会花太多篇幅去讨论继承的细节,而是着重于如何将这个特性应用到我们的框架当中。

正如前面所提到的,每个游戏有各种类型的对象。在大多数情况下,这些对象拥有很多相似的数据与类似的功能。下面我们举个栗子来说明一下:

  • 几乎所有的对象都需要被绘制到屏幕上面,所以我们需要一个draw函数来进行绘制对象。
  • 我们的对象绘制肯定需要使用x,y来定位,所以他们肯定都会有一个x,y变量。
  • 除非是静态图片,否则我们希望我们的对象能够对自己进行更新,所以肯定会有一个update函数进行对象更新。
  • 对象不再被使用的时候,我们也希望他能够清理掉不使用的资源,所以我们可能会需要一个clean函数来进行资源清理。

OK,这是一个很好的开始,让我们继续创建和完善我们的“GameObject”类。

class GameObject
{
public:
    void draw(){std::cout<<"draw game object";}
    void update(){std::cout<<"update game object";}
    void clean(){std::cout<<"clean game object";}
protected:
    int m_x;
    int m_y;
};

现在我们有了第一个游戏对象类了,下面我们创建一个玩家类继承自该类:

class Player : public GameObject
{
public:
    void draw()
    {
        GameObject::draw();
        std::cout<<"draw player";
    }
    void update()
    {
        GameObject::update();
        std::cout<<"update player";
    }
    void clean()
    {
        GameObject::clean();
        std::cout<<"clean player";
    }
}

现在我们可以复用基类函数与对象的成员了,当然我们也可以在调用父类实现的功能的同时,扩展自身的功能。

void update()
{
    GameObject::update();
    std::cout<<"update player";
    m_x = 10;
    m_y = 20;
}