ECS.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * 2D Game Engine
  3. * ECS.h:
  4. * Based on pikuma.com 2D game engine in C++ and Lua course
  5. * Copyright (c) 2021 986-Studio. All rights reserved.
  6. *
  7. * Created by Manoël Trapier on 11/02/2021.
  8. */
  9. #ifndef GAMEENGINE_ECS_H
  10. #define GAMEENGINE_ECS_H
  11. #include <stdint.h>
  12. #include <bitset>
  13. #include <vector>
  14. #include <unordered_map>
  15. #include <typeindex>
  16. #include <set>
  17. #include <Pool.h>
  18. const uint32_t MAX_COMPONENTS = 32;
  19. typedef std::bitset<MAX_COMPONENTS> Signature;
  20. struct IComponent
  21. {
  22. protected:
  23. static uint32_t nextId;
  24. };
  25. template <typename T> class Component: public IComponent
  26. {
  27. public:
  28. static uint32_t getId()
  29. {
  30. static auto id = IComponent::nextId++;
  31. return id;
  32. }
  33. };
  34. class Entity
  35. {
  36. private:
  37. uint32_t id;
  38. public:
  39. explicit Entity(uint32_t id): id(id) {};
  40. Entity(const Entity & entity) = default;
  41. uint32_t getId() const;
  42. Entity& operator=(const Entity & other) = default;
  43. bool operator==(const Entity &other) const { return this->id == other.id; };
  44. bool operator!=(const Entity &other) const { return this->id != other.id; };
  45. bool operator>(const Entity &other) const { return this->id > other.id; };
  46. bool operator<(const Entity &other) const { return this->id < other.id; };
  47. };
  48. class System
  49. {
  50. private:
  51. Signature componentSignature;
  52. std::vector<Entity> entities;
  53. public:
  54. System() = default;
  55. ~System() = default;
  56. void addEntity(Entity entity);
  57. void removeEntity(Entity entity);
  58. std::vector<Entity> getEntities() const;
  59. const Signature& getComponentSignature() const;
  60. template<typename T> void requireComponent();
  61. };
  62. template<typename T> void System::requireComponent()
  63. {
  64. const auto componentId = Component<T>::getId();
  65. this->componentSignature.set(componentId);
  66. }
  67. class Registry
  68. {
  69. private:
  70. uint32_t numEntities = 0;
  71. std::vector<IPool*> componentPools;
  72. std::vector<Signature> entityComponentSignatures;
  73. std::unordered_map<std::type_index, System*> systems;
  74. std::set<Entity> entitiesToBeAdded;
  75. std::set<Entity> entitiesToBeKilled;
  76. public:
  77. Registry() = default;
  78. ~Registry() = default;
  79. /* Entities */
  80. Entity CreateEntity();
  81. void addEntityToSystem(Entity entity);
  82. /* Components */
  83. template <typename T, typename ...TArgs> void addComponent(Entity entity, TArgs&& ...args);
  84. /* Systems */
  85. /* Others */
  86. void Update();
  87. };
  88. template<typename T, typename ...TArgs> void Registry::addComponent(Entity entity, TArgs&& ...args)
  89. {
  90. const auto componentId = Component<T>::getId();
  91. const auto entityId = entity.getId();
  92. Pool<T> *componentPool;
  93. /* Check the pool is big enough */
  94. if (componentId >= this->componentPools.size())
  95. {
  96. this->componentPools.reserve(componentId + 1, nullptr);
  97. }
  98. /* Is this component exist in the pool? */
  99. if (!this->componentPools[componentId])
  100. {
  101. this->componentPools[componentId] = new Pool<T>();
  102. }
  103. componentPool = this->componentPools[componentId];
  104. if (entityId >= componentPool->getSize())
  105. {
  106. componentPool->resize(this->numEntities);
  107. }
  108. T newComponent(std::forward<TArgs>(args)...);
  109. componentPool->set(entityId, newComponent);
  110. entityComponentSignatures[entityId].set(componentId);
  111. }
  112. #endif /* GAMEENGINE_ECS_H */