Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中为游戏对象设计类层次结构+;_C++_Oop - Fatal编程技术网

C++ 在C+中为游戏对象设计类层次结构+;

C++ 在C+中为游戏对象设计类层次结构+;,c++,oop,C++,Oop,我正在寻找一些关于为游戏对象设计类层次结构的建议。对于本次讨论,我将主要讨论两个特定的类。对象和精灵 对象是游戏中任何类型对象的基类Sprite直接继承自Object,但是Object的一些公共方法不再有意义。下面是一些代码来解释: class Object { public: Object() : renderer(NULL), controller(NULL), collider(NULL) { } virtual ~Object(); Renderer *getR

我正在寻找一些关于为游戏对象设计类层次结构的建议。对于本次讨论,我将主要讨论两个特定的类。
对象
精灵

对象
是游戏中任何类型对象的基类
Sprite
直接继承自
Object
,但是
Object
的一些公共方法不再有意义。下面是一些代码来解释:

class Object {
public:
    Object() : renderer(NULL), controller(NULL), collider(NULL) { }
    virtual ~Object();

    Renderer *getRenderer() const;
    Controller *getController() const;
    Collider *getCollider() const;

    void setRenderer(Renderer *renderer);
    void setController(Controller *controller);
    void setCollider(Collider *collider);
private:
    Renderer *renderer;
    Controller *controller;
    Collider *collider;
};
对象
有三个组件:渲染器、碰撞器和控制器
Sprite
当然有这三个组件,但是使用了
spriteender
。我想我不希望为sprite类公开
setRenderer
方法

因此,我认为我应该按照如下方式编写sprite类:

class Sprite : protected Object {
public:
    Sprite(Texture *texture) : Object(), texture(texture) {
        setRenderer(new SpriteRenderer(this));
    }

    Renderer *getRenderer() const;
    Controller *getController() const;
    Collider *getCollider() const;

    void setController(Controller *controller);
    void setCollider(Collider *collider);
private:
    Texture *texture;
};
其中getter和setter只调用相关的
对象
方法。但在这种情况下,我不能真正将
精灵
用作
对象
,例如,将其传递给接受
对象
的函数

我的另一个实施方案是:

class Sprite : public Object {
public:
    Sprite(Texture *texture) : Object(), texture(texture) {
        setRenderer(new SpriteRenderer(this));
    }
private:
    Texture *texture;
};
它公开了
setRenderer
方法

我的想法是,不应该公开
setRenderer
方法,因为
Sprite
是一个带有
SpriteRenderer
对象,因此如果它被更改,那么它就不是
Sprite
。然而,我看不到一个明显的方法来阻止它改变


总的来说,这是我不应该担心的事情,还是有其他方法来进行此设计?

不要使用getter和setter对对象进行建模,而是让对象实际执行您想要的操作——您不必担心在没有setter时暴露setter。:)

例如,让对象自身渲染,而不是返回渲染器。这样,精灵就可以覆盖这种行为:

class Object {
    virtual void render() = 0;
}

class Sprite : public Object {
    void render() {
      // use a SpriteRenderer
    }
}

不要使用getter和setter对对象进行建模,而是让对象实际执行您想要的操作——您不必担心在没有setter的情况下暴露setter。:)

例如,让对象自身渲染,而不是返回渲染器。这样,精灵就可以覆盖这种行为:

class Object {
    virtual void render() = 0;
}

class Sprite : public Object {
    void render() {
      // use a SpriteRenderer
    }
}

您应该问问自己:是否需要在运行时更改渲染器(和其他组件)?我相信在创建对象实例之后不需要这样做。因此,我根本不会将方法setRenderer(和其他setXXX)放在公共API中。 您需要公开这些参数吗?如果是,我可以提出以下建议:

这样你就有了一个很好的不可变类

为了构造精灵实例,您可能需要SpriteFactory或SpriteBuilder

类精灵:公共对象
{
公众:
精灵(常量渲染器和渲染器,常量精灵指定CSTUFF和素材):
对象(渲染器),
...
{
}
};
类SpriteBuilder
{
公众:
void set渲染器(常量渲染器*渲染器);
void setPriteSpecificStuff();
std::auto_ptr build();
};

同样,使用构建器,您将拥有一个很好的不可变类,您应该问问自己:是否需要在运行时更改渲染器(和其他组件)?我相信在创建对象实例之后不需要这样做。因此,我根本不会将方法setRenderer(和其他setXXX)放在公共API中。 您需要公开这些参数吗?如果是,我可以提出以下建议:

这样你就有了一个很好的不可变类

为了构造精灵实例,您可能需要SpriteFactory或SpriteBuilder

类精灵:公共对象
{
公众:
精灵(常量渲染器和渲染器,常量精灵指定CSTUFF和素材):
对象(渲染器),
...
{
}
};
类SpriteBuilder
{
公众:
void set渲染器(常量渲染器*渲染器);
void setPriteSpecificStuff();
std::auto_ptr build();
};

同样,使用构建器,您将拥有一个很好的不可变类。在我关于多重继承的评论中,您可以将对象看作是一些可渲染的对象,一些可碰撞的对象,一些可“控制”(无论在您的系统中意味着什么)。因此,您可以为每个功能使用一个基类,而不是使用一个包含所有这三个属性(可能更多)的基类对象

class Renderable
{
public:
    Renderable(Rendered *renderer) : remderer_(renderer) {}

    Renderer *getRenderer() const;
    void setRenderer(Renderer *renderer);

private:
    Renderer *renderer_;
}

class Controllable
{
public:
    Controllable(Constroller &constroller) : controller_(constroller) {}

    Controller *getController() const;

    void setController(Controller *controller);

private:
    Controller *controller_;
};

class Collidable {
public:
    Collidable(Collider *collider) : collider_(collider) {}

    Collider *getCollider() const;

    void setCollider(Collider *collider);

private:
    Collider *collider_;
};
然后,
Sprite
类拥有这三种功能,您将继承这三种功能:

class Sprite : public Renderable, public Controllable, public Collidable
{
public:
    Sprite()
        : Renderable(new SpriteRenderer)  // Supply special renderer
        {}

private:
    // Disallow users of the `Sprite` class to call this function;
    using Renderable::setRenderer;
};

这个系统有能力类,在游戏世界中创建“对象”时工作得非常好。以一个幻想风格的游戏为例,你有一个类
,它继承了
武器
可穿戴
可携带
,这意味着剑可以用作武器,可以佩戴和携带。

根据我关于多重继承的评论,你可以将对象看作是可渲染的,有些是能够碰撞的,有些是“受控的”(无论在你的系统中意味着什么)。因此,您可以为每个功能使用一个基类,而不是使用一个包含所有这三个属性(可能更多)的基类对象

class Renderable
{
public:
    Renderable(Rendered *renderer) : remderer_(renderer) {}

    Renderer *getRenderer() const;
    void setRenderer(Renderer *renderer);

private:
    Renderer *renderer_;
}

class Controllable
{
public:
    Controllable(Constroller &constroller) : controller_(constroller) {}

    Controller *getController() const;

    void setController(Controller *controller);

private:
    Controller *controller_;
};

class Collidable {
public:
    Collidable(Collider *collider) : collider_(collider) {}

    Collider *getCollider() const;

    void setCollider(Collider *collider);

private:
    Collider *collider_;
};
然后,
Sprite
类拥有这三种功能,您将继承这三种功能:

class Sprite : public Renderable, public Controllable, public Collidable
{
public:
    Sprite()
        : Renderable(new SpriteRenderer)  // Supply special renderer
        {}

private:
    // Disallow users of the `Sprite` class to call this function;
    using Renderable::setRenderer;
};

这个系统有能力类,在游戏世界中创建“对象”时工作得非常好。以一个幻想风格的游戏为例,你有一个类
,它继承了
武器
可穿戴
携带
,这意味着剑可以用作武器,可以佩戴和携带。

为什么不在具体对象上分离特征,然后使用多重继承?例如:
RenderableObject
s包含渲染所需的所有内容,
physicobject
s包含物理所需的所有内容,
AliveObject
s用于所有活动对象。如果你需要一堵隐形墙,你可以