Entity Component System
-
Hallo
Hab mich unter Zuhilfenahme von diversen Artikeln und Videos mal an einem sehr einfachen "ECS" versucht. In folgendem seht ihr eine Klasse namens "ComponentManager" ( wenn euch ein besserer Name einfällt, dankeschön ).
Dieser wird später einem Entity, das lediglich aus einem unsigned integer besteht ( std::size_t ), in einer Map zugewiesen.std::map < EntityId /* using EntityId = std::size_t */, std::unique_ptr< ComponentManager> > entities_;
Wollte einfach einmal eure Meinungen bzw. Verbesserungsvorschläge von euch hören.
#ifndef COMPONENT_MANAGER_H #define COMPONENT_MANAGER_H #include <bitset> #include <map> #include <memory> #include <type_traits> #include "ComponentInterface.h" #define MAX_COMPONENTS 32 using ComponentId = std::size_t; class ComponentManager { public: ComponentManager(); ~ComponentManager(); template < typename ComponentType > bool hasComponent() const { return componentBitset_.at(getComponentTypeId<ComponentType>()); } template < typename ComponentType > ComponentType& addComponent() { if (!hasComponent<ComponentType>()) { auto typeId = getComponentTypeId<ComponentType>(); components_.emplace(typeId, std::make_shared<ComponentType>()); componentBitset_.at(typeId) = true; return *(std::static_pointer_cast<ComponentType>(components_.at(typeId))); } // ERR_INVALID_COMPONENT_TYPE } template < typename ComponentType > ComponentType& getComponent() { if (hasComponent<ComponentType>()) { return *(std::static_pointer_cast<ComponentType>(components_.at(getComponentTypeId<ComponentType>()))); } // ERR_INVALID_COMPONENT_TYPE } private: inline ComponentId createUniqueComponentId() const { static ComponentId lastId{ 0u }; return lastId++; } template < typename ComponentType > inline ComponentId getComponentTypeId() const { if (std::is_base_of<ComponentInterface, ComponentType>::value) { static ComponentId typeId = createUniqueComponentId(); return typeId; } // ERR_INVALID_COMPONENT_TYPE } std::bitset<MAX_COMPONENTS> componentBitset_; std::map<ComponentId, std::shared_ptr<ComponentInterface>> components_; }; // class ComponentManager #endif // COMPONENT_MANAGER_H
Und so kann man das ganze dann benutzen :
#include <iostream> #include "ComponentManager.h" struct ComponentHealth : public ComponentInterface { float Health; }; struct ComponentPosition : public ComponentInterface { float X; float Y; }; int main() { ComponentManager m; ComponentManager m2; auto& handle = m.addComponent<ComponentHealth>(); handle.Health = 200; std::cout << m.getComponent<ComponentHealth>().Health << std::endl; auto& handle_2 = m2.addComponent<ComponentPosition>(); handle_2.X = 400; handle_2.Y = 500; std::cout << m2.getComponent<ComponentPosition>().X << std::endl; std::cout << m2.getComponent<ComponentPosition>().Y << std::endl; auto& handle_3 = m2.addComponent<ComponentHealth>(); handle_3.Health = 600; std::cout << m2.getComponent<ComponentHealth>().Health << std::endl; std::getchar(); return EXIT_SUCCESS; }
Im vornherein schon einmal danke !