我正在尝试实现某种“仅适合我”的游戏引擎,问题的情节如下:
假设我有一个可渲染实体的抽象接口,例如IRenderable.
它以下列方式声明:
interface IRenderable {
// (...)
// Suppose that Backend is some abstract backend used
// for rendering, and it's implementation is not important
virtual void Render(Backend& backend) = 0;
};
我现在正在做的就像声明不同的类一样
class Ball : public IRenderable {
virtual void Render(Backend& backend) {
// Rendering implementation, that is specific for
// the Ball object
// (...)
}
};
然后一切都很好.我可以很容易地做一些像std :: vector< IRenderable *>项目,在此向量中推送一些像新Ball()的项目,然后拨打类似于foreach的调用(IRenderable * in items){item-> Render(backend); }
好吧,我想这是’多态’的方式,但是如果我想在我的游戏中拥有不同类型的对象并且能够操纵它们的状态,那么每个对象都可以通过它自己的界面进行操作呢?
我可以做点什么
struct GameState {
Ball ball;
Bonus bonus;
// (...)
};
然后通过他们自己的方法轻松更改对象状态,如ball.Move(…)或bonus.Activate(…),其中Move(…)仅适用于Ball和Activate(…) – 仅适用于奖励实例.
但是在这种情况下,我失去了编写foreach IRenderable *的机会,因为我将这些球和奖金存储为派生的,而不是基类的实例.在这种情况下,渲染过程变得像一团糟
ball.Render(backend);
bonus.Render(backend);
// (...)
这很糟糕,因为我们实际上以这种方式失去了多态性(没有实际需要使Render函数虚拟等等)
另一种方法意味着通过dynamic_cast调用向下转换或使用typeid来调用你想要操作的对象的类型,这对我来说更糟糕,这也打破了这种“多态”的想法.
所以,我的问题是 – 是否有某种(可能)替代方法可以做我想做的事情,或者我的当前模式可以以某种方式进行修改,以便我实际上为我的游戏对象存储IRenderable *(这样我就可以调用虚拟渲染他们每个人的方法)同时保留了轻松改变这些对象状态的能力?
也许我从一开始就做了一些绝对错误的事情,如果有的话,请指出:)
提前致谢!
解决方法:
我不是一个程序员,但希望人造代码会帮助…
Class Renderable具有Render功能
Movable类继承自Renderable,还具有x,y,z等属性以及Move等函数
Class Ball继承自Movable
现在你的游戏状态可以有一个可渲染对象列表,当渲染时,它可以循环遍历它们.
其他操作(如世界时钟的勾号)可能会循环查找Moveable实例的对象并告诉他们更新.
如果您的奖金是可渲染的(我无法从您的问题中确定),那么它可以将Collectable子类化为子类Moveable.