I'm implementing an Entity-Component-System. Basically, an entity is a wrapper around an ID, a component is just a POD struct, and a System is a class that does work on components corresponding to the Entities subscribed to that system.
I'd like to take advantage of smart pointers, so the cleanup will be much smoother. However, I've ended up with a rather ugly looking function for getting the component attached to an Entity.
For this implementation of an ECS, all components inherit from a base struct just simply called Component. Entities have a hashmap of the components they own, with that components ID as the key.
Entity.h
//Forward declaration
struct Component;
struct Entity
{
/*A unique ID*/
const unsigned long long int kID;
/*A map containing all components held by this entity*/
std::map<int, std::shared_ptr<Component>> component_map_;
};
Component.h
typedef int COMPONENT_ID;
/*Base component class*/
struct Component
{
static const COMPONENT_ID kTYPE = -1;
};
/*Components*/
struct CPosition : public Component
{
static const COMPONENT_ID kTYPE = 0;
float x, y;
};
EntityManager.h templated function for getting a component from an entity
/*Gets a component from an entity*/
template<typename T>
std::shared_ptr<T> GetComponent(std::shared_ptr<Entity> entity) {
return std::shared_ptr<T>((T*)entity->component_map_.at(T::kTYPE).get());
}
An example of how it would be used:
int main(int argc, char** argv)
{
/*Create the entitymanager*/
EntityManager em;
/*Create an entity*/
auto a = em.CreateEntity();
/*Create a new Position Component*/
/*struct CPosition : public Component */
auto component = new CPosition();
component->x = 55;
component->y = 200;
/*Add the CPosition component to the entity a*/
em.AddComponent(a, component);
/*Get the component back from the entity a*/
auto mcomponent = em.GetComponent<CPosition>(a);
return 0;
}
Is there a cleaner way to get the component back from the entity, without grabbing the raw pointer and casting it and sticking it back into a shared_ptr? What about having the static ID of components and using that to map the components in the entity? Any better solutions?