Godzil 3 лет назад
Родитель
Сommit
d1c4d353bd
4 измененных файлов с 121 добавлено и 4 удалено
  1. 92 1
      source/ECS.cpp
  2. 4 0
      source/Game.cpp
  3. 24 2
      source/include/ECS.h
  4. 1 1
      source/include/Systems/ProjectileEmit.h

+ 92 - 1
source/ECS.cpp

@@ -26,6 +26,26 @@ void Entity::kill()
     this->registry->killEntity(*this);
 }
 
+void Entity::tag(const std::string &tag)
+{
+    this->registry->tagEntity(*this, tag);
+}
+
+bool Entity::hasTag(const std::string &tag) const
+{
+    return this->registry->entityHasTag(*this, tag);
+}
+
+void Entity::group(const std::string &groupName)
+{
+    this->registry->groupEntity(*this, groupName);
+}
+
+bool Entity::belongToGroup(const std::string &groupName) const
+{
+    return this->registry->entityBelongsToGroup(*this, groupName);
+}
+
 /* System */
 void System::addEntity(Entity entity)
 {
@@ -50,7 +70,6 @@ const Signature& System::getComponentSignature() const
     return this->componentSignature;
 }
 
-
 Entity Registry::createEntity()
 {
     uint32_t entityId;
@@ -129,6 +148,78 @@ void Registry::update()
         this->entityComponentSignatures[entity.getId()].reset();
 
         this->freeIds.push_back(entity.getId());
+
+        this->removeEntityTag(entity);
+        this->removeEntityGroup(entity);
     }
     this->entitiesToBeKilled.clear();
 }
+
+
+void Registry::tagEntity(Entity entity, const std::string &tag)
+{
+    this->entityPerTag.emplace(tag, entity);
+    this->tagPerEntity.emplace(entity.getId(), tag);
+}
+
+bool Registry::entityHasTag(Entity entity, const std::string &tag) const
+{
+    if (this->tagPerEntity.find(entity.getId()) == this->tagPerEntity.end())
+    {
+        return false;
+    }
+    return this->entityPerTag.find(tag)->second == entity;
+}
+
+Entity Registry::getEntityByTag(const std::string &tag) const
+{
+    return this->entityPerTag.at(tag);
+}
+
+void Registry::removeEntityTag(Entity entity)
+{
+    auto taggedEntity = this->tagPerEntity.find(entity.getId());
+    if (taggedEntity != this->tagPerEntity.end())
+    {
+        auto tag = taggedEntity->second;
+        this->entityPerTag.erase(tag);
+        this->tagPerEntity.erase(taggedEntity);
+    }
+}
+
+void Registry::groupEntity(Entity entity, const std::string &groupName)
+{
+    this->entitiesPerGroup.emplace(groupName, std::set<Entity>());
+    this->entitiesPerGroup[groupName].emplace(entity);
+    this->groupPerEntity.emplace(entity.getId(), groupName);
+}
+
+bool Registry::entityBelongsToGroup(Entity entity, const std::string &groupName) const
+{
+    auto groupEntities = this->entitiesPerGroup.at(groupName);
+    return groupEntities.find(entity) != groupEntities.end();
+}
+
+std::vector<Entity> Registry::getEntitiesByGroup(const std::string &groupName) const
+{
+    auto &setOfEntities = this->entitiesPerGroup.at(groupName);
+    return std::vector<Entity>(setOfEntities.begin(), setOfEntities.end());
+}
+
+void Registry::removeEntityGroup(Entity entity)
+{
+    auto groupedEntity = this->groupPerEntity.find(entity.getId());
+    if (groupedEntity != this->groupPerEntity.end())
+    {
+        auto group = this->entitiesPerGroup.find(groupedEntity->second);
+        if (group != this->entitiesPerGroup.end())
+        {
+            auto entityInGroup = group->second.find(entity);
+            if (entityInGroup != group->second.end())
+            {
+                group->second.erase(entityInGroup);
+            }
+        }
+        groupPerEntity.erase(groupedEntity);
+    }
+}

+ 4 - 0
source/Game.cpp

@@ -171,6 +171,7 @@ void Game::LoadLevel(int level)
             Entity tile = registry->createEntity();
             tile.addComponent<TransformComponent>(glm::vec2(x * (tileScale * tileSize), y * (tileScale * tileSize)), glm::vec2(tileScale, tileScale), 0.0);
             tile.addComponent<SpriteComponent>("main-tileset", 0, tileSize, tileSize, false, srcRectX, srcRectY);
+            tile.group("tiles");
         }
     }
     mapFile.close();
@@ -188,6 +189,7 @@ void Game::LoadLevel(int level)
     chopper.addComponent<ProjectileEmitterComponent>(glm::vec2(180, 180), 0, 10000, 0, true);
     chopper.addComponent<HealthComponent>(100);
     chopper.addComponent<CameraFollowComponent>();
+    chopper.tag("player");
 
 
     Entity radar = this->registry->createEntity();
@@ -203,6 +205,7 @@ void Game::LoadLevel(int level)
     tank.addComponent<BoxColliderComponent>(32, 32, glm::vec2(0, 0));
     tank.addComponent<ProjectileEmitterComponent>(glm::vec2(100, 0), 5000, 3000, 0, false);
     tank.addComponent<HealthComponent>(100);
+    tank.group("enemies");
 
     Entity truck = this->registry->createEntity();
     truck.addComponent<TransformComponent>(glm::vec2(10, 10), glm::vec2(1, 1), 0);
@@ -211,6 +214,7 @@ void Game::LoadLevel(int level)
     truck.addComponent<BoxColliderComponent>(32, 32, glm::vec2(0, 0));
     truck.addComponent<ProjectileEmitterComponent>(glm::vec2(0, 100), 2000, 5000, 0, false);
     truck.addComponent<HealthComponent>(100);
+    truck.group("enemies");
 }
 
 void Game::Setup()

+ 24 - 2
source/include/ECS.h

@@ -60,14 +60,20 @@ public:
     bool operator>(const Entity &other) const  { return this->id > other.id; };
     bool operator<(const Entity &other) const  { return this->id < other.id; };
 
-
     /* Some syntaxic sugar */
     template <typename T, typename ...TArgs> void addComponent(TArgs&& ...args);
     template <typename T> void removeComponent();
     template <typename T> bool hasComponent();
     template <typename T> T& getComponent();
+
     class Registry *registry = nullptr;
+
     void kill();
+    void tag(const std::string &tag);
+    bool hasTag(const std::string &tag) const;
+
+    void group(const std::string &groupName);
+    bool belongToGroup(const std::string &groupName) const;
 };
 
 class System
@@ -107,7 +113,13 @@ private:
     std::set<Entity> entitiesToBeAdded;
     std::set<Entity> entitiesToBeKilled;
 
-    std::deque<int> freeIds;
+    std::deque<uint32_t> freeIds;
+
+    std::unordered_map<std::string, Entity> entityPerTag;
+    std::unordered_map<uint32_t, std::string> tagPerEntity;
+
+    std::unordered_map<std::string, std::set<Entity>> entitiesPerGroup;
+    std::unordered_map<uint32_t, std::string> groupPerEntity;
 
 public:
     Registry() = default;
@@ -117,6 +129,16 @@ public:
     Entity createEntity();
     void killEntity(Entity entity);
 
+    void tagEntity(Entity entity, const std::string &tag);
+    bool entityHasTag(Entity entity, const std::string &tag) const;
+    Entity getEntityByTag(const std::string &tag) const;
+    void removeEntityTag(Entity entity);
+
+    void groupEntity(Entity entity, const std::string &groupName);
+    bool entityBelongsToGroup(Entity entity, const std::string &groupName) const;
+    std::vector<Entity> getEntitiesByGroup(const std::string &groupName) const;
+    void removeEntityGroup(Entity entity);
+
     void addEntityToSystems(Entity entity);
     void removeEntityFromSystems(Entity entity);
 

+ 1 - 1
source/include/Systems/ProjectileEmit.h

@@ -42,7 +42,7 @@ public:
         {
             for (auto entity: this->getSystemEntities())
             {
-                if (entity.hasComponent<CameraFollowComponent>())
+                if (entity.hasTag("player"))
                 {
                     auto &emitter = entity.getComponent<ProjectileEmitterComponent>();
                     const auto transform = entity.getComponent<TransformComponent>();