/* * ECS.h * * Created on: Feb 21, 2020 * Author: ayoungblood */ #ifndef SRC_ECS_H_ #define SRC_ECS_H_ #include #include #include #include #include #include class Component; class Entity; class Manager; using ComponentID = std::size_t; using Group = std::size_t; inline ComponentID getNewComponentTypeID() { static ComponentID lastID = 0u; return lastID++; } template inline ComponentID getComponentTypeID() noexcept { static_assert (std::is_base_of::value, ""); static ComponentID typeID = getNewComponentTypeID(); return typeID; } constexpr std::size_t maxComponents = 32; constexpr std::size_t maxGroups =32; using ComponentBitSet = std::bitset; using GroupBitset = std::bitset; using ComponentArray = std::array; class Component { public: Entity* entity; virtual void init() {} virtual void update() {} virtual void draw() {} virtual ~Component() {} }; class Entity { private: Manager& manager; bool active = true; std::vector> components; ComponentArray componentArray; ComponentBitSet componentBitSet; GroupBitset groupBitset; public: Entity(Manager& mManager) : manager(mManager) {} void update() { for(auto& c : components) c->update(); } void draw() { for(auto& c : components) c->draw(); } bool isActive() const { return active; } void destroy() { active = false; } bool hasGroup(Group mGroup) { return groupBitset[mGroup]; } void addGroup(Group mGroup); void delGroup(Group mGroup) { groupBitset[mGroup] = false; } template bool hasComponent() const { return componentBitSet[getComponentTypeID()]; } template T& addComponent(TArgs&&... mArgs) { T* c(new T(std::forward(mArgs)...)); c->entity = this; std::unique_ptr uPtr{ c }; components.emplace_back(std::move(uPtr)); componentArray[getComponentTypeID()] = c; componentBitSet[getComponentTypeID()] = true; c->init(); return *c; } template T& getComponent() const { auto ptr(componentArray[getComponentTypeID()]); return *static_cast(ptr); } }; class Manager { private: std::vector> entities; std::array, maxGroups> groupedEntities; public: void update() { for (auto& e : entities) e->update(); } void draw() { for (auto& e : entities) e->draw(); } void refresh() { for (auto i(0u); i < maxGroups; i++) { auto& v(groupedEntities[i]); v.erase( std::remove_if(std::begin(v), std::end(v), [i](Entity* mEntity) { return !mEntity->isActive() || !mEntity->hasGroup(i); }), std::end(v)); } entities.erase(std::remove_if(std::begin(entities), std::end(entities), [](const std::unique_ptr &mEntity) { return !mEntity->isActive(); }), std::end(entities)); } void AddToGroup(Entity* mEntity, Group mGroup) { groupedEntities[mGroup].emplace_back(mEntity); } std::vector& getGroup(Group mGroup) { return groupedEntities[mGroup]; } Entity& addEntity() { Entity* e = new Entity(*this); std::unique_ptr uPtr{ e }; entities.emplace_back(std::move(uPtr)); return *e; } }; #endif /* SRC_ECS_H_ */