This is similar to these questions: Is it possible to initialise two classes, that require pointers to each other, at the same time?
Two classes that refer to each other
But I am looking for a more general or "best practices" solution.
This is a problem that often comes up in game design: when many objects need information from other objects and one of them will inevitably be the "most downstream" (in terms of header includes) than any other element. Seeing as there are thousands of games out there, I am assuming there is some "good" solution to this.
In particular, I have a virtual base class "GameObject" to which all my game objects belong: players, bullets, zombies... and a map of "GameObject*" that stores all game objects. My GameState class holds this map and all Game objects retain the same static pointer to the map. Each GameObject also has a vector<GameObject*> called "collisions" that holds a ptr to each GameObject that collided with it since the last update.
Class GameObject {
private:
static int objID;
int id;
//maps
static std::unordered_map<int, GameObj*>* objs;
public:
//list of collisions with other objects
std::vector<GameObj*> collisions;
//Accessors - some generic accessors
unsigned int getID() const;
ObjType getType() const;
sf::Vector2f getPos() const;
virtual const sf::FloatRect& getGlobalBounds() const = 0;
//And the key function, update
virtual STATE update() = 0;
}
My GameState class contains a method which calls Player::update() (for all players, its a non-Static method), Zombies::update() for all zombies and so on. Update() is a pure virtual function of GameObject.
If Player.h includes Zombie.h then I can go into my player class, iterate through my vector of bullets and check if any of them has collided with a zombie. I can delete the bullet, add to the players score, etc. as necessary.
However, in my Zombie class, I can deduce that the zombie has collided with a bullet but I cannot deduce how much damage that bullet does, or anything else about the bullet because the zombie doesn't know what a bullet is (i.e., I cant dynamic cast GameObj* to Bullet* and use accessor methods). So how can we solve this problem.
Solutions:
It occurred to me that a primitive fix may be to include "Bullet.h" in for both Zombies and Players - which may work but does not fix the larger problem - say the player did direct damage to the zombie, for instance.
A "forward declaration" of the class did not work for me here. The compiler still gets angry over a dynamic cast from GameObject* to Bullet*
Passing all bullet/zombie information through (via the wrapper gameState class) is possible but cumbersome, not to mention I'm using a pure virtual function for all my game objects, most of which would not make use of this information being passed.
I could expand my GameObject class to hold more information about a GameObject like its damage. However, for some GameObjects this information would be extraneous.
Finally, I could do everything I need to do to the zombie in the Player class, (via dynamic casting) but this feels disjunct, why should the player be directly modifying the zombie?
Any other clever solutions?