Pelle Beckman wrote:
whew. This must be my tenth post or so just this
week - thank you to everyone who took the time
to answer my questions!
Now, I'm helping a friend with an OpenGL application
and we need some help in figuring out a design pattern.
Here's the deal:
Each frame we draw lots of "3DObjects" and
if they implement "Actor" they should also
think (ie call Think(), or whatever).
So, we tought of using RTTI to check
wheter it's an object that is also an Actor -
but thats complicated and a bit too slow.
There is probably a very simple solution to
this, but I'm all out of ideas (or *cough* knowledge...)
-- Pelle
Yes, there is an elegant solution to this described in "Game Programming
Gems pt. 2". It sort of works like Microsoft's COM and is realized using
type trait interfaces.
You let each of your classes which you want to perform some action on
(like your 3DObject) inherit from an ABC Object, which provides a method
to query which operations it supports:
class Object
{
public:
enum InterfaceType
{
RENDERABLE,
PLAYABLE,
WHATEVER-ABLE
};
virtual bool QueryInterface(InterfaceType, void**) = 0;
};
Now all child classes have to implement this function, like this:
class 3DObject: public Object, public Renderable
{
public:
void render();
// ...
};
bool 3DObject::QueryInterface( InterfaceType type, void ** pObject )
{
bool bSucceeded = false;
if( type == RENDERABLE )
{
*pObject = dynamic_cast<Renderable*>(this);
assert( *pObject != 0 );
bSucceeded = true;
}
return bSucceeded;
}
In your code, you can now use these objects like this:
// be objects a list of all kinds of ObjectS, and you now want to call a
// render() method on all those objects in the list, which implement the
// Renderable() interface:
// (loop through list, be obj the current object)
//...
Renderable *pRenderable = 0;
if( obj->QueryInterface( Object::RENDERABLE, &pRenderable ) )
pRenderable->render();
// ...
In this loop all renderable objects will call render(), cool eh?
Hope that helps.
--
Matthias Kaeppler