• Advertisement
Sign in to follow this  

How to implement a object manager class?

This topic is 561 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to implement a ObjectManager in my game, but I'm having some problems doing that.

I currently have a class called Entity which is the base class for all objects in the game, such as Players, Boxes, Walls, and so on.

Two classes that derive from Entity is SpriteGameObject.

 

In my ObjectManager class there's a vector which looks like this : 

std::vector<Entity*> entities

I have no problem adding objects to the vector, but I'm having some problems getting objects.

 

Let's say I want to call my GameObject's function called "AddForce", but the Entity class and Sprite class doesn't have this function, how would I do that?

 

My GetEntity function looks like this : 

Entity* EntityManager::GetEntity(std::string m_id, std::string m_gamestate)
{
	std::cout << "ID : " << _entities[0]->GetID() << std::endl;
	for (int i = 0; i < _entities.size(); i++)
	{
		if (_entities[i]->GetID() == m_id && _entities[i]->GetGamestate() == m_gamestate)
		{
			return _entities[i];
		}
	}

	std::cerr << "Could not get entity : " << m_id << " in gamestate : " << m_gamestate << ", it doesn't exist." << std::endl;
	return nullptr;

}

But when I call this function like this : 

GetEntity("test", "MainMenuState")->AddForce(10, 10);

It wouldn't work, since Entity doesn't have that function.

 

How would I solve this problem?

 

(hopefully this made sense....)

Share this post


Link to post
Share on other sites
Advertisement

Assuming you want to keep your current inheritance pattern (and not consider a component pattern which I think is better for your case), you could implement a GetType() virtual in your Entity base class.  

 

For example:

class Entity {
public:
 ...

 enum class Type {
  Entity,
  Sprite,
  GameObject
 };

 virtual Type GetType() const { return Type::Entity; }
 
 ...
};

class GameObject {
public:
 virtual Type GetType() const { return Type::GameObject; }
};

// and the same for Sprite

And then your code would read something like this:

Entity* entity = GetEntity("test", "MainMenuState");
if (entity->GetType() == Entity::Type::GameObject) {
  static_cast<GameObject*>(entity)->AddForce(10,10);
}

The price the cost of calling a virtual method, though I'm not sure your game's performance would be affected much unless you're developing a serious engine.   There are other ways of mitigating this cost, like adding a member variable to Entity that identifies the class type.   Then your Entity constructor would have an argument "Type", and your GameObject/Sprite/etc. child class constructor would initialize Entity with the appropriate Type value.   The cost is an extra few bytes per entity to store the Type.

 

Also, you might find yourself littering your code with a lot of "GetType" to take care of all the special cases you're going to eventually run into.   

 

Pick your poison.   Again I don't think you're going to have to worry about virtual call performance costs unless you're writing a serious engine.

 

Finally, there are other ways to speed up what I think you're trying to do - but this should address your specific question.

Edited by samsinx

Share this post


Link to post
Share on other sites

Assuming you want to keep your current inheritance pattern (and not consider a component pattern which I think is better for your case), you could implement a GetType() virtual in your Entity base class.  

 

For example:

class Entity {
public:
 ...

 enum class Type {
  Entity,
  Sprite,
  GameObject
 };

 virtual Type GetType() const { return Type::Entity; }
 
 ...
};

class GameObject {
public:
 virtual Type GetType() const { return Type::GameObject; }
};

// and the same for Sprite

And then your code would read something like this:

Entity* entity = GetEntity("test", "MainMenuState");
if (entity->GetType() == Entity::Type::GameObject) {
  static_cast<GameObject*>(entity)->AddForce(10,10);
}

The price the cost of calling a virtual method, though I'm not sure your game's performance would be affected much unless you're developing a serious engine.   There are other ways of mitigating this cost, like adding a member variable to Entity that identifies the class type.   Then your Entity constructor would have an argument "Type", and your GameObject/Sprite/etc. child class constructor would initialize Entity with the appropriate Type value.   The cost is an extra few bytes per entity to store the Type.

 

Also, you might find yourself littering your code with a lot of "GetType" to take care of all the special cases you're going to eventually run into.   

 

Pick your poison.   Again I don't think you're going to have to worry about virtual call performance costs unless you're writing a serious engine.

 

Finally, there are other ways to speed up what I think you're trying to do - but this should address your specific question.

 

I can't make one of the Type enuim items Entity though since the class name is also Entity, results in a redefinition error.

I don't think I'll need a Entity type though since it should always have either GameObject or Sprite, so I can change the name of it to ERROR or something like that, and set it to -1.

 

And I'm getting a bunch of unresolved external errors about redefining Entity::GetType(), can't figure out why though.


Error LNK2005 "public: virtual enum Entity::Type __thiscall Entity::GetType(void)" (?GetType@Entity@@UAE?AW4Type@1@XZ) already defined in Entity.obj SwEngine C:\Users\MyName\Documents\Visual Studio 2015\Projects\SwEngine\SwEngine\GameObject.obj 1
Error LNK2001 unresolved external symbol "public: virtual enum Entity::Type __thiscall SwEngine::GameObject::GetType(void)" (?GetType@GameObject@SwEngine@@UAE?AW4Type@Entity@@XZ) SwEngine C:\Users\MyName\Documents\Visual Studio 2015\Projects\SwEngine\SwEngine\GameObject.obj 1
Error LNK2005 "public: virtual enum Entity::Type __thiscall Entity::GetType(void)" (?GetType@Entity@@UAE?AW4Type@1@XZ) already defined in Entity.obj SwEngine C:\Users\MyName\Documents\Visual Studio 2015\Projects\SwEngine\SwEngine\Sprite.obj 1
Error LNK2005 "public: virtual enum Entity::Type __thiscall Entity::GetType(void)" (?GetType@Entity@@UAE?AW4Type@1@XZ) already defined in Entity.obj SwEngine C:\Users\MyName\Documents\Visual Studio 2015\Projects\SwEngine\SwEngine\Sprite.obj 1
Error LNK2001 unresolved external symbol "public: virtual enum Entity::Type __thiscall SwEngine::Sprite::GetType(void)" (?GetType@Sprite@SwEngine@@UAE?AW4Type@Entity@@XZ) SwEngine C:\Users\MyName\Documents\Visual Studio 2015\Projects\SwEngine\SwEngine\Sprite.obj 1Error LNK2005 "public: virtual enum Entity::Type __thiscall Entity::GetType(void)" (?GetType@Entity@@UAE?AW4Type@1@XZ) already defined in Entity.obj SwEngine C:\Users\MyName\Documents\Visual Studio 2015\Projects\SwEngine\SwEngine\GameObject.obj 1

Here's my Entity header file : 

#pragma once

#include <SFML\Graphics.hpp>

class Entity
{

public:
	
	enum class Type
	{
		ERROR,
		Sprite,
		GameObject
	};

	virtual void Draw(sf::RenderWindow &m_window);
	virtual void Update();
	virtual void HandleEvents(float m_deltaTime);
	virtual std::string GetID();
	virtual std::string GetGamestate();
	virtual void SetID(std::string m_id);
	virtual void SetGamestate(std::string m_gamestate);
	virtual Type GetType();

private:

	std::string _id;
	std::string _gamestate;

};


And my Entity cpp file : 

#include "Entity.h"

void Entity::Draw(sf::RenderWindow &m_window)
{

}

void Entity::Update()
{

}

void Entity::HandleEvents(float m_deltaTime)
{

}

std::string Entity::GetID()
{
	return _id;
}

void Entity::SetID(std::string m_id)
{
	_id = m_id;
}

std::string Entity::GetGamestate()
{
	return _gamestate;
}

void Entity::SetGamestate(std::string m_gamestate)
{
	_gamestate = m_gamestate;
}

Entity::Type Entity::GetType()
{
	return Type::ERROR;
}

Any idea why this is happening? :o

Edited by BiiXteR

Share this post


Link to post
Share on other sites

Some of those errors are a little strange.   Check what happens if you remove the implementation from Entity.cpp and instead write an inline implementation inside GetType() within Entity.h.    Also have you implemented the GameObject and Sprite versions?

Share this post


Link to post
Share on other sites
Two classes that derive from Entity is Sprite, GameObject.

 

Noooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo oooooooooooooooooooooooooooo.

 

http://stackoverflow.com/questions/2218937/has-a-is-a-terminology-in-object-oriented-language

 

(KHawk broke my funny joke.)

Edited by Khatharr
Continuous was breaking layout. Quick fix.

Share this post


Link to post
Share on other sites

Some of those errors are a little strange.   Check what happens if you remove the implementation from Entity.cpp and instead write an inline implementation inside GetType() within Entity.h.    Also have you implemented the GameObject and Sprite versions?

 

Sorry, my bad. For some reason I added Entity::GetType() instead of GameObject::GetType() in my GameObject class.

But I think it's working now! It's messy but working.

I'll go ahead and research on a component system as well, however I don't think I'm going to add it until later on.

 

Thanks a lot for the help though!

 

 

 

Two classes that derive from Entity is Sprite, GameObject.

 

Noooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo.

 

http://stackoverflow.com/questions/2218937/has-a-is-a-terminology-in-object-oriented-language

 

 

But a GameObject is a entity?? D':

Share this post


Link to post
Share on other sites

 

Some of those errors are a little strange.   Check what happens if you remove the implementation from Entity.cpp and instead write an inline implementation inside GetType() within Entity.h.    Also have you implemented the GameObject and Sprite versions?

 

Sorry, my bad. For some reason I added Entity::GetType() instead of GameObject::GetType() in my GameObject class.

But I think it's working now! It's messy but working.

I'll go ahead and research on a component system as well, however I don't think I'm going to add it until later on.

 

Thanks a lot for the help though!

 

 

 

Two classes that derive from Entity is Sprite, GameObject.

 

Noooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo.

 

http://stackoverflow.com/questions/2218937/has-a-is-a-terminology-in-object-oriented-language

 

 

But a GameObject is a entity?? D':

 

 

It could be argued that "game object" is actually the definition of "entity", but in any case sprites are not entities.

 

You've leaning way too heavily on inheritance here. In addition to the is-a/has-a thing, there's no way that you're observing LSP:

https://en.wikipedia.org/wiki/Liskov_substitution_principle

 

Inheritance should only be used to facilitate polymorphism. Prefer composition strongly.

https://en.wikipedia.org/wiki/Composition_over_inheritance

Share this post


Link to post
Share on other sites

 

 

Some of those errors are a little strange.   Check what happens if you remove the implementation from Entity.cpp and instead write an inline implementation inside GetType() within Entity.h.    Also have you implemented the GameObject and Sprite versions?

 

Sorry, my bad. For some reason I added Entity::GetType() instead of GameObject::GetType() in my GameObject class.

But I think it's working now! It's messy but working.

I'll go ahead and research on a component system as well, however I don't think I'm going to add it until later on.

 

Thanks a lot for the help though!

 

 

 

Two classes that derive from Entity is Sprite, GameObject.

 

Noooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo.

 

http://stackoverflow.com/questions/2218937/has-a-is-a-terminology-in-object-oriented-language

 

 

But a GameObject is a entity?? D':

 

 

It could be argued that "game object" is actually the definition of "entity", but in any case sprites are not entities.

 

You've leaning way too heavily on inheritance here. In addition to the is-a/has-a thing, there's no way that you're observing LSP:

https://en.wikipedia.org/wiki/Liskov_substitution_principle

 

Inheritance should only be used to facilitate polymorphism. Prefer composition strongly.

https://en.wikipedia.org/wiki/Composition_over_inheritance

 

 

I'm so confused... ._.

 

The Liskov Subtitution Principle says that if S is a subtype of T, then objects of type T can be replaced with objects of type S, right?

So... If Entity is a subtype of GameObject, then objects of type GameObjects can be replaced with objects of type S.

Doesn't that work?

 

However I guess I can agree on the Sprite though.

 

What would you recommend doing instead of all this inheritance?

Share this post


Link to post
Share on other sites

LSP basically means that if S inherits from T then you should be able to say:

 

T* derp = new S;

 

and then 'derp' should behave 100% correctly as a T, because if you're using inheritance correctly then derp is-a T, even though the underlying type is S. If you enforce LSP in cases where inheritance is not necessary then the parent type usually ends up looking pretty worthless.

 

Before using inheritance:

  1. Do I need polymorphism here? Is polymorphism the best way to manage this?
  2. Does the derived type satisfy the is-a rule for the base type? In the sense that it does, is that really the best way to handle these objects?
  3. If I cast a derived object to the parent type can it behave correctly in all cases?
  4. Is there a reason that I can't use composition? (Hint: usually no)

If you can't meet all those qualifications then there's probably a better solution. It's usually composition.

 

Example:

/* BAD */
class LocationalThing {
public:
  float x, y, z;
};

class Entity : public LocationalThing {
  //stuff
};
/* LESS BAD */
struct Location {
  float x, y, z;
};

class Entity {
public:
  Location position;
};

Note that both cases provide the same basic functionality, but you avoid all of the problems associated with inheritance (diamond of death, etc) and you have a convenient package for handing around position data. Locality is an attribute of entities, not a category that entities fit into. Continue following this logic and soon your need for an Entity class will start to be suspect. Eventually you'll realize that inheritance makes it easier to operate on a series of objects that share some set of attributes through polymorphism.

 

For example, if you have several different graphical types, like Sprite, Circle, Mesh, etc., they can probably all have a draw function, and you probably want to draw them all around the same point in time, so you may want them to inherit from an abstract class RenderObject that declares the draw function. This way you can place them in a single list, sort it, and then iterate it and draw them all in one go. The danger here is that you want to draw a new type of thing in the future, but it doesn't quite fit with the RenderObject signature, so you have to change RenderObject, which means that you have to change all of its derived types, which means that you should start considering another way of managing it.

Share this post


Link to post
Share on other sites

 

What would you recommend doing instead of all this inheritance?

 

 

 

Assuming you're not too far along implementing the engine, Khatharr is right that you'd really want to rethink your approach.  Inheritance isn't necessarily a bad thing - but composition is usually the better answer.  His numbered list is a good basis to decide between the two approaches.

 

One of the pitfalls for your current method is that you're likely going to be writing a lot of "GetType() checks" (and other various virtual calls) in your code as you iterate across your entities vector.  A way around this is to organize your object lists in a way that minimizes or eliminates the need for virtual calls.     Employing a Component/Entity/System approach can help achieve this.   How?  You'll have to read up on CES some at http://entity-systems.wikidot.com or just a search for the appropriate keywords.  

 

Warning about CES - I personally think sometimes people try to implement a "pure" CES and end up spending way too much time with the details without actually programming a game.   But you can implement a CES where an "Entity" class uses the "has a" idiom for components pretty easily.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement