I've got the following code, think simple shooter in c++:
// world.hpp
//----------
class Enemy;
class Bullet;
class Player;
struct World
{
// has-a collision map
// has-a list of Enemies
// has-a list of Bullets
// has-a pointer to a player
};
// object.hpp
//-----------
#include "world.hpp"
struct Object
{
virtual ~Object();
virtual void Update() =0;
virtual void Render() const =0;
Float xPos, yPos, xVel, yVel, radius; // etc.
};
struct Enemy: public Object
{
virtual ~Enemy();
virtual void Update();
virtual void Render() const;
};
// Bullet and Player are similar (they render and update differently per se,
/// but the behavior exposed to World is similar)
// world.cpp
//----------
#include "object.hpp"
// object.cpp
//-----------
#include "object.hpp"
Two problems with this:
1, Game objects knowing about other game objects.
There has to be a facility that knows about all objects. It might or might not have to expose ALL objects, it has to expose some of it, depending parameters of the enquirer (position, for one). This facility is supposed to be World.
Objects have to know about the World they're in, to query for collision information and other objects.
This introduces a dependency where both Objects' and World's implementation have to access to object's header, thus World won't include its own header directly rather than by including object.hpp (which in turn includes world.hpp). This makes me feel uncomfortable -- I don't feel that world.cpp should recompile after I make a change to object.hpp. World doesn't feel like it should work with Object. It feels like bad design - how can it be fixed?
2, Polymorphism -- can and should it be used for anything beyond code reuse and logical grouping of game entities (and how)?
Enemies, Bullets and Player will update and render differently, surely, hence the virtual Update() and Render() functionality -- an identical interface. They're still kept in separate lists and the reason for this is that their interaction depends on which lists two interacting objects are - two Enemies bounce off each other, a Bullet and an Enemy destroys each other etc.
This is functionality that's beyond the implementation of Enemy and Bullet; that's not my concern here. I feel that beyond their identical interfaces there's a factor that separates Enemies, Bullets and Players and this could and should be expressed in some other way, allowing me to create a single list for all of them -- as their interface is identical!
The problem is how to tell an object category from another if contained within the same list. Typeid or other form of type identification is out of the question - but then what other way to do it? Or maybe there's nothing wrong with the approach?