#include #include #include #include #include class ComponentBase { public: ComponentBase(std::type_index type) : type { type } { } virtual ~ComponentBase() = default; virtual std::type_index get_type() const { return type; } protected: std::type_index type; }; template class Component : public ComponentBase { public: Component(T const& data) : ComponentBase { typeid(T) }, data { data } { } T& get() { return data; } private: T data; }; class Entity { public: Entity() = default; Entity(Entity const&) = delete; Entity& operator=(Entity const&) = delete; ~Entity() { for (ComponentBase* component : components) { delete component; } } template T& get() { return static_cast*>(get_component())->get(); } template void add(T const& component) { components.push_back(new Component(component)); } template bool has() const { return get_component() != nullptr; } private: template ComponentBase* get_component() const { for (auto component : components) { if (component->get_type() == typeid(T)) { return component; } } return nullptr; } std::vector components { }; }; struct Name { std::string name; }; struct Health { int hp; }; struct Damage { int damage; }; int main() { int entity_count { 10 }; std::vector entities(entity_count); // a pseudo random number generator std::mt19937 gen { std::random_device{}() }; // generates a number in [0, 100) std::uniform_int_distribution dist { 0, 99 }; for (int i { 0 }; i < entity_count; ++i) { if (dist(gen) <= 50) // 50% chance to get a name { entities[i].add(Name { "Entity #" + std::to_string(i) }); } if (dist(gen) <= 80) // 80% chance to get health { entities[i].add(Health{dist(gen)}); } if (dist(gen) <= 75) // 75% chance to get damage { entities[i].add(Damage{dist(gen)}); } } // A system for processing all entities with the Name component std::cout << "Named entities: " << std::endl; for (Entity& entity : entities) { if (entity.has()) { std::cout << " - " << entity.get().name << std::endl; } } // A system for processing all entities with both Health and Damage std::cout << "Battle ready entities: " << std::endl; for (std::size_t i { 0 }; i < entities.size(); ++i) { Entity& entity { entities[i] }; if (entity.has() && entity.has()) { std::cout << " - " << i << ": has " << entity.get().hp << " hp and deals " << entity.get().damage << " damage" << std::endl; } } }