#pragma once #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 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 { 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 this->active; } void destroy() { this->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 }; this->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); } private: Manager& manager; bool active = true; std::vector> components; ComponentArray componentArray; ComponentBitSet componentBitSet; GroupBitSet groupBitSet; }; class Manager { 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; } private: std::vector> entities; std::array, maxGroups> groupedEntities; };