]> code.bitgloo.com Git - clyne/entityx.git/commitdiff
Add Entity class helper.
authorAlec Thomas <alec@swapoff.org>
Wed, 24 Oct 2012 23:54:30 +0000 (19:54 -0400)
committerAlec Thomas <alec@swapoff.org>
Thu, 25 Oct 2012 00:06:34 +0000 (20:06 -0400)
This largely supplants the use of entity IDs.

README.md
entityx/Components.h
entityx/Components_test.cc
entityx/Entity.h
entityx/Entity_test.cc
entityx/System_test.cc

index 0ca2918df8a098aca554d06a63fd263a080288d2..611dc98f9c32a20557713450b9e8907135221f57 100644 (file)
--- a/README.md
+++ b/README.md
@@ -50,18 +50,18 @@ struct Direction : Component<Direction> {
 
 #### Assigning components to entities
 
-To associate a component with a previously created entity call ``EntityManager::assign<C>()`` with the component type, the entity, and any component constructor arguments:
+To associate a component with a previously created entity call ``Entity::assign<C>()`` with the component type, and any component constructor arguments:
 
 ```c++
 // Assign a Position with x=1.0f and y=2.0f to "entity"
-entities.assign<Position>(entity, 1.0f, 2.0f);
+entity.assign<Position>(1.0f, 2.0f);
 ```
 
 You can also assign existing instances of components:
 
 ```c++
 boost::shared_ptr<Position> position = boost::make_shared<Position>(1.0f, 2.0f);
-entities.assign(entity, position);
+entity.assign(position);
 ```
 
 #### Querying entities and their components
@@ -76,10 +76,10 @@ for (auto entity : entities.entities_with_components(position, direction)) {
 }
 ```
 
-To retrieve a component associated with an entity use ``EntityManager::component()``:
+To retrieve a component associated with an entity use ``Entity::component<C>()``:
 
 ```c++
-boost::shared_ptr<Position> position = entities.component<Position>();
+boost::shared_ptr<Position> position = entity.component<Position>();
 if (position) {
   // Do stuff with position
 }
@@ -186,8 +186,8 @@ class GameManager : public Manager {
     // Create some entities in random locations heading in random directions
     for (int i = 0; i < 100; ++i) {
       Entity entity = entity_manager.create();
-      entity_manager.assign<Position>(entity, rand() % 100, rand() % 100);
-      entity_manager.assign<Direction>(entity, (rand() % 10) - 5, (rand() % 10) - 5);
+      entity.assign<Position>(rand() % 100, rand() % 100);
+      entity.assign<Direction>((rand() % 10) - 5, (rand() % 10) - 5);
     }
   }
   
index cbc74d9abe2a3260c6be5d9ee94f771802b7c348..c963302a7f55b5a20d6150ccdc0feb7a201f2b94 100644 (file)
@@ -23,7 +23,7 @@ class TagsComponent : public Component<TagsComponent> {
   struct TagsPredicate {
     TagsPredicate(const std::string &tag) : tag(tag) {}
 
-    bool operator () (EntityManager &manager, Entity id) {
+    bool operator () (EntityManager &manager, Entity::Id id) {
       auto tags = manager.component<TagsComponent>(id);
       return tags != nullptr && tags->tags.find(tag) != tags->tags.end();
     }
index bb9ae5deb279727d2d0813a875115e88156beee8..8fe05ec32e9ef77062e310990b5d3e3a104ec970 100644 (file)
@@ -40,7 +40,7 @@ TEST(TagsComponentTest, TestVariadicConstruction) {
 TEST(TagsComponentTest, TestEntitiesWithTag) {
   EventManager ev;
   EntityManager en(ev);
-  Entity a = en.create();
+  Entity::Id a = en.create();
   en.assign<Position>(a);
   for (int i = 0; i < 99; ++i) {
     auto e = en.create();
index b90abe772fdcde50cfcb21ac64aa550027d922a3..e76321445d9b09c77c5d42b9f2fc6348f252cb92 100644 (file)
 
 namespace entityx {
 
+
+class EntityManager;
+
+
 /**
- * Entity handle.
+ * A convenience handle around an Entity::Id.
  */
-typedef uint64_t Entity;
+class Entity {
+ public:
+  typedef uint64_t Id;
 
+  Id id() const { return id_; }
 
-class EntityManager;
+  operator Id () { return id_; }
+
+  template <typename C>
+  boost::shared_ptr<C> assign(boost::shared_ptr<C> component);
+  template <typename C, typename ... Args>
+  boost::shared_ptr<C> assign(Args && ... args);
+
+  template <typename C>
+  boost::shared_ptr<C> component();
+
+  template <typename A>
+  void unpack(boost::shared_ptr<A> &a);
+  template <typename A, typename B, typename ... Args>
+  void unpack(boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args);
+
+ private:
+  friend class EntityManager;
+
+  Entity(EntityManager &entities, Entity::Id id) : entities_(entities), id_(id) {}
+
+  EntityManager &entities_;
+  Entity::Id id_;
+};
 
 
 /**
@@ -54,7 +83,7 @@ struct BaseComponent {
  * Component implementations should inherit from this.
  *
  * Components MUST provide a no-argument constructor.
- * Components SHOULD provide convenience constructors for initializing on assignment to an Entity.
+ * Components SHOULD provide convenience constructors for initializing on assignment to an Entity::Id.
  *
  * This is a struct to imply that components should be data-only.
  *
@@ -85,20 +114,20 @@ struct Component : public BaseComponent {
  * Emitted when an entity is added to the system.
  */
 struct EntityCreatedEvent : public Event<EntityCreatedEvent> {
-  EntityCreatedEvent(EntityManager &manager, Entity entity) :
+  EntityCreatedEvent(EntityManager &manager, Entity::Id entity) :
       manager(manager), entity(entity) {}
 
   EntityManager &manager;
-  Entity entity;
+  Entity::Id entity;
 };
 
 
 struct EntityDestroyedEvent : public Event<EntityDestroyedEvent> {
-  EntityDestroyedEvent(EntityManager &manager, Entity entity) :
+  EntityDestroyedEvent(EntityManager &manager, Entity::Id entity) :
       manager(manager), entity(entity) {}
 
   EntityManager &manager;
-  Entity entity;
+  Entity::Id entity;
 };
 
 
@@ -107,27 +136,27 @@ struct EntityDestroyedEvent : public Event<EntityDestroyedEvent> {
  */
 template <typename T>
 struct ComponentAddedEvent : public Event<ComponentAddedEvent<T>> {
-  ComponentAddedEvent(EntityManager &manager, Entity entity, boost::shared_ptr<T> component) :
+  ComponentAddedEvent(EntityManager &manager, Entity::Id entity, boost::shared_ptr<T> component) :
       manager(manager), entity(entity), component(component) {}
 
   EntityManager &manager;
-  Entity entity;
+  Entity::Id entity;
   boost::shared_ptr<T> component;
 };
 
 
 /**
- * Manages Entity creation and component assignment.
+ * Manages Entity::Id creation and component assignment.
  *
  * eg.
  * EntityManager e;
  *
  * Entity player = e.create();
  *
- * e.assign<Movable>(player);
- * e.assign<Physical>(player);
- * e.assign<Scriptable>(player);
- * shared_ptr<Controllable> controllable = e.assign<Controllable>(player);
+ * player.assign<Movable>();
+ * player.assign<Physical>();
+ * player.assign<Scriptable>();
+ * shared_ptr<Controllable> controllable = player.assign<Controllable>();
  */
 class EntityManager : boost::noncopyable {
  private:
@@ -138,14 +167,14 @@ class EntityManager : boost::noncopyable {
 
   class View {
    public:
-    typedef boost::function<bool (EntityManager &, Entity)> Predicate;
+    typedef boost::function<bool (EntityManager &, Entity::Id)> Predicate;
 
     /// A predicate that excludes entities that don't match the given component mask.
     class ComponentMaskPredicate {
      public:
       ComponentMaskPredicate(const std::vector<uint64_t> &entity_bits, uint64_t mask) : entity_bits_(entity_bits), mask_(mask) {}
 
-      bool operator () (EntityManager &, Entity entity) {
+      bool operator () (EntityManager &, Entity::Id entity) {
         return (entity_bits_.at(entity) & mask_) == mask_;
       }
 
@@ -155,7 +184,7 @@ class EntityManager : boost::noncopyable {
     };
 
     /// An iterator over a view of the entities in an EntityManager.
-    class Iterator : public std::iterator<std::input_iterator_tag, Entity> {
+    class Iterator : public std::iterator<std::input_iterator_tag, Entity::Id> {
      public:
       Iterator &operator ++ () {
         ++i_;
@@ -164,14 +193,14 @@ class EntityManager : boost::noncopyable {
       }
       bool operator == (const Iterator& rhs) const { return i_ == rhs.i_; }
       bool operator != (const Iterator& rhs) const { return i_ != rhs.i_; }
-      Entity & operator * () { return i_; }
-      const Entity & operator * () const { return i_; }
+      Entity operator * () { return Entity(manager_, i_); }
+      const Entity operator * () const { return Entity(manager_, i_); }
 
      private:
       friend class View;
 
       Iterator(EntityManager &manager, const std::vector<Predicate> &predicates,
-               const std::vector<boost::function<void (Entity)>> &unpackers, Entity entity)
+               const std::vector<boost::function<void (Entity::Id)>> &unpackers, Entity::Id entity)
           : manager_(manager), predicates_(predicates), unpackers_(unpackers), i_(entity) {
         next();
       }
@@ -198,8 +227,8 @@ class EntityManager : boost::noncopyable {
 
       EntityManager &manager_; 
       const std::vector<Predicate> predicates_;
-      std::vector<boost::function<void (Entity)>> unpackers_;
-      Entity i_;
+      std::vector<boost::function<void (Entity::Id)>> unpackers_;
+      Entity::Id i_;
     };
 
     // Create a sub-view with an additional predicate.
@@ -216,7 +245,7 @@ class EntityManager : boost::noncopyable {
     View &unpack_to(boost::shared_ptr<A> &a) {
       unpackers_.push_back(Unpacker<A>(manager_, a));
       // This resulted in a segfault under clang 4.1 on OSX. No idea why. 
-      /*unpackers_.push_back([&a, this](Entity id) {
+      /*unpackers_.push_back([&a, this](Entity::Id id) {
         a = manager_.component<A>(id);
       });*/
       return *this;
@@ -234,7 +263,7 @@ class EntityManager : boost::noncopyable {
     struct Unpacker {
       Unpacker(EntityManager &manager, boost::shared_ptr<T> &c) : manager(manager), c(c) {}
 
-      void operator () (Entity id) {
+      void operator () (Entity::Id id) {
         c = manager.component<T>(id);
       }
 
@@ -249,7 +278,7 @@ class EntityManager : boost::noncopyable {
 
     EntityManager &manager_;
     std::vector<Predicate> predicates_;
-    std::vector<boost::function<void (Entity)>> unpackers_;
+    std::vector<boost::function<void (Entity::Id)>> unpackers_;
   };
 
   /**
@@ -258,12 +287,12 @@ class EntityManager : boost::noncopyable {
   size_t size() const { return entity_component_mask_.size(); }
 
   /**
-   * Create a new Entity.
+   * Create a new Entity::Id.
    *
    * Emits EntityCreatedEvent.
    */
   Entity create() {
-    Entity id;
+    Entity::Id id;
     if (free_list_.empty()) {
       id = id_counter_++;
       accomodate_entity(id);
@@ -271,16 +300,16 @@ class EntityManager : boost::noncopyable {
       id = *free_list_.erase(free_list_.begin());
     }
     event_manager_.emit<EntityCreatedEvent>(*this, id);
-    return id;
+    return Entity(*this, id);
   }
 
   /**
-   * Destroy an existing Entity and its associated Components.
+   * Destroy an existing Entity::Id and its associated Components.
    *
    * Emits EntityDestroyedEvent.
    */
-  void destroy(Entity entity) {
-    CHECK(entity < entity_component_mask_.size()) << "Entity ID outside entity vector range";
+  void destroy(Entity::Id entity) {
+    CHECK(entity < entity_component_mask_.size()) << "Entity::Id ID outside entity vector range";
     event_manager_.emit<EntityDestroyedEvent>(*this, entity);
     for (auto &components : entity_components_) {
       components.at(entity).reset();
@@ -290,9 +319,9 @@ class EntityManager : boost::noncopyable {
   }
 
   /**
-   * Check if an Entity is registered.
+   * Check if an Entity::Id is registered.
    */
-  bool exists(Entity entity) {
+  bool exists(Entity::Id entity) {
     if (entity_component_mask_.empty() || entity >= id_counter_) {
       return false;
     }
@@ -300,12 +329,12 @@ class EntityManager : boost::noncopyable {
   }
 
   /**
-   * Assigns a previously constructed Component to an Entity.
+   * Assigns a previously constructed Component to an Entity::Id.
    *
    * @returns component
    */
   template <typename C>
-  boost::shared_ptr<C> assign(Entity entity, boost::shared_ptr<C> component) {
+  boost::shared_ptr<C> assign(Entity::Id entity, boost::shared_ptr<C> component) {
     boost::shared_ptr<BaseComponent> base = boost::static_pointer_cast<BaseComponent>(component);
     accomodate_component(C::family());
     entity_components_.at(C::family()).at(entity) = base;
@@ -316,24 +345,24 @@ class EntityManager : boost::noncopyable {
   }
 
   /**
-   * Assign a Component to an Entity, optionally passing through Component constructor arguments.
+   * Assign a Component to an Entity::Id, optionally passing through Component constructor arguments.
    *
    *   shared_ptr<Position> position = em.assign<Position>(e, x, y);
    *
    * @returns Newly created component.
    */
   template <typename C, typename ... Args>
-  boost::shared_ptr<C> assign(Entity entity, Args && ... args) {
+  boost::shared_ptr<C> assign(Entity::Id entity, Args && ... args) {
     return assign<C>(entity, boost::make_shared<C>(args ...));
   }
 
   /**
-   * Retrieve a Component assigned to an Entity.
+   * Retrieve a Component assigned to an Entity::Id.
    *
-   * @returns Component instance, or empty shared_ptr<> if the Entity does not have that Component.
+   * @returns Component instance, or empty shared_ptr<> if the Entity::Id does not have that Component.
    */
   template <typename C>
-  boost::shared_ptr<C> component(Entity id) {
+  boost::shared_ptr<C> component(Entity::Id id) {
     // We don't bother checking the component mask, as we return a nullptr anyway.
     if (C::family() >= entity_components_.size()) {
       return boost::shared_ptr<C>();
@@ -374,7 +403,7 @@ class EntityManager : boost::noncopyable {
    * unpack<Position, Direction>(e, p, d);
    */
   template <typename A>
-  void unpack(Entity id, boost::shared_ptr<A> &a) {
+  void unpack(Entity::Id id, boost::shared_ptr<A> &a) {
     a = component<A>(id);
   }
 
@@ -390,7 +419,7 @@ class EntityManager : boost::noncopyable {
    * unpack<Position, Direction>(e, p, d);
    */
   template <typename A, typename B, typename ... Args>
-  void unpack(Entity id, boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
+  void unpack(Entity::Id id, boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
     unpack<A>(id, a);
     unpack<B, Args ...>(id, b, args ...);
   }
@@ -416,7 +445,7 @@ class EntityManager : boost::noncopyable {
     return component_mask<C1>(c1) | component_mask<C2, Components ...>(c2, args...);
   }
 
-  inline void accomodate_entity(Entity entity) {
+  inline void accomodate_entity(Entity::Id entity) {
     if (entity_component_mask_.size() <= entity) {
       entity_component_mask_.resize(entity + 1);
       for (auto &components : entity_components_) {
@@ -434,15 +463,40 @@ class EntityManager : boost::noncopyable {
     }
   }
 
-  Entity id_counter_ = 0;
+  Entity::Id id_counter_ = 0;
 
   EventManager &event_manager_;
   // A nested array of: components = entity_components_[family][entity]
   std::vector<EntitiesComponent> entity_components_;
-  // Bitmask of components associated with each entity. Index into the vector is the Entity.
+  // Bitmask of components associated with each entity. Index into the vector is the Entity::Id.
   std::vector<uint64_t> entity_component_mask_;
-  // List of available Entity IDs.
-  boost::unordered_set<Entity> free_list_;
+  // List of available Entity::Id IDs.
+  boost::unordered_set<Entity::Id> free_list_;
 };
 
+template <typename C>
+boost::shared_ptr<C> Entity::assign(boost::shared_ptr<C> component) {
+  return entities_.assign<C>(id_, component);
+}
+
+template <typename C, typename ... Args>
+boost::shared_ptr<C> Entity::assign(Args && ... args) {
+  return entities_.assign<C>(id_, args ...);
+}
+
+template <typename C>
+boost::shared_ptr<C> Entity::component() {
+  return entities_.component<C>(id_);
+}
+
+template <typename A>
+void Entity::unpack(boost::shared_ptr<A> &a) {
+  entities_.unpack(id_, a);
+}
+
+template <typename A, typename B, typename ... Args>
+void Entity::unpack(boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
+  entities_.unpack(id_, a, b, args ...);
+}
+
 }
index 1433b26e709760bc8d4c2bb51a9dad3ce37b1a2b..55da405e14a8352282fb45252a6a52896f10a980 100644 (file)
@@ -79,8 +79,9 @@ TEST_F(EntityManagerTest, TestCreateEntity) {
 
 TEST_F(EntityManagerTest, TestComponentConstruction) {
   auto e = em.create();
-  auto p = em.assign<Position>(e, 1, 2);
-  auto cp = em.component<Position>(e);
+  auto p = e.assign<Position>(1, 2);
+  //auto p = em.assign<Position>(e, 1, 2);
+  auto cp = e.component<Position>();
   ASSERT_EQ(p, cp);
   ASSERT_FLOAT_EQ(1.0, cp->x);
   ASSERT_FLOAT_EQ(2.0, cp->y);
@@ -88,8 +89,8 @@ TEST_F(EntityManagerTest, TestComponentConstruction) {
 
 TEST_F(EntityManagerTest, TestComponentCreationWithObject) {
   auto e = em.create();
-  auto p = em.assign(e, make_shared<Position>(1.0, 2.0));
-  auto cp = em.component<Position>(e);
+  auto p = e.assign(make_shared<Position>(1.0, 2.0));
+  auto cp = e.component<Position>();
   ASSERT_EQ(p, cp);
   ASSERT_FLOAT_EQ(1.0, cp->x);
   ASSERT_FLOAT_EQ(2.0, cp->y);
@@ -98,27 +99,27 @@ TEST_F(EntityManagerTest, TestComponentCreationWithObject) {
 TEST_F(EntityManagerTest, TestDestroyEntity) {
   Entity e = em.create();
   Entity f = em.create();
-  auto ep = em.assign<Position>(e);
-  em.assign<Position>(f);
-  em.assign<Direction>(e);
-  em.assign<Direction>(f);
+  auto ep = e.assign<Position>();
+  f.assign<Position>();
+  e.assign<Direction>(e);
+  f.assign<Direction>();
 
   ASSERT_EQ(2, ep.use_count());
   ASSERT_TRUE(em.exists(e));
   ASSERT_TRUE(em.exists(f));
-  ASSERT_TRUE(em.component<Position>(e));
-  ASSERT_TRUE(em.component<Direction>(e));
-  ASSERT_TRUE(em.component<Position>(f));
-  ASSERT_TRUE(em.component<Direction>(f));
+  ASSERT_TRUE(e.component<Position>());
+  ASSERT_TRUE(e.component<Direction>());
+  ASSERT_TRUE(f.component<Position>());
+  ASSERT_TRUE(f.component<Direction>());
 
   em.destroy(e);
 
   ASSERT_FALSE(em.exists(e));
   ASSERT_TRUE(em.exists(f));
-  ASSERT_FALSE(em.component<Position>(e));
-  ASSERT_FALSE(em.component<Direction>(e));
-  ASSERT_TRUE(em.component<Position>(f));
-  ASSERT_TRUE(em.component<Direction>(f));
+  ASSERT_FALSE(e.component<Position>());
+  ASSERT_FALSE(e.component<Direction>());
+  ASSERT_TRUE(f.component<Position>());
+  ASSERT_TRUE(f.component<Direction>());
   ASSERT_EQ(1, ep.use_count());
 }
 
@@ -126,23 +127,23 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponent) {
   Entity e = em.create();
   Entity f = em.create();
   Entity g = em.create();
-  em.assign<Position>(e);
-  em.assign<Direction>(e);
-  em.assign<Position>(f);
-  em.assign<Position>(g);
+  e.assign<Position>();
+  e.assign<Direction>();
+  f.assign<Position>();
+  g.assign<Position>();
   ASSERT_EQ(3, size(em.entities_with_components<Position>()));
   ASSERT_EQ(1, size(em.entities_with_components<Direction>()));
 }
 
 TEST_F(EntityManagerTest, TestGetEntitiesWithIntersectionOfComponents) {
-  vector<Entity> entities;
+  vector<Entity::Id> entities;
   for (int i = 0; i < 150; ++i) {
     Entity e = em.create();
     entities.push_back(e);
     if (i % 2 == 0)
-      em.assign<Position>(e);
+      e.assign<Position>();
     if (i % 3 == 0)
-      em.assign<Direction>(e);
+      e.assign<Direction>();
 
   }
   ASSERT_EQ(50, size(em.entities_with_components<Direction>()));
@@ -151,10 +152,10 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithIntersectionOfComponents) {
 }
 
 TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
-  vector<Entity> entities;
-  Entity e = em.create();
-  Entity f = em.create();
-  Entity g = em.create();
+  vector<Entity::Id> entities;
+  Entity::Id e = em.create();
+  Entity::Id f = em.create();
+  Entity::Id g = em.create();
   std::vector<std::pair<shared_ptr<Position>, shared_ptr<Direction>>> position_directions;
   position_directions.push_back(std::make_pair(
           em.assign<Position>(e, 1.0f, 2.0f),
@@ -180,7 +181,7 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
 }
 
 TEST_F(EntityManagerTest, TestUnpack) {
-  Entity e = em.create();
+  Entity::Id e = em.create();
   auto p = em.assign<Position>(e);
   auto d = em.assign<Direction>(e);
 
@@ -192,7 +193,7 @@ TEST_F(EntityManagerTest, TestUnpack) {
 }
 
 TEST_F(EntityManagerTest, TestUnpackNullMissing) {
-  Entity e = em.create();
+  Entity::Id e = em.create();
   auto p = em.assign<Position>(e);
 
   struct NullDeleter {template<typename T> void operator()(T*) {} };
@@ -213,7 +214,7 @@ TEST_F(EntityManagerTest, TestEntityCreatedEvent) {
       created.push_back(event.entity);
     }
 
-    vector<Entity> created;
+    vector<Entity::Id> created;
   };
 
   EntityCreatedEventReceiver receiver;
@@ -232,14 +233,14 @@ TEST_F(EntityManagerTest, TestEntityDestroyedEvent) {
       destroyed.push_back(event.entity);
     }
 
-    vector<Entity> destroyed;
+    vector<Entity::Id> destroyed;
   };
 
   EntityDestroyedEventReceiver receiver;
   ev.subscribe<EntityDestroyedEvent>(receiver);
 
   ASSERT_EQ(0, receiver.destroyed.size());
-  vector<Entity> entities;
+  vector<Entity::Id> entities;
   for (int i = 0; i < 10; ++i) {
     entities.push_back(em.create());
   }
@@ -282,7 +283,7 @@ TEST_F(EntityManagerTest, TestComponentAddedEvent) {
   ASSERT_EQ(0, receiver.position_events);
   ASSERT_EQ(0, receiver.direction_events);
   for (int i = 0; i < 10; ++i) {
-    Entity e = em.create();
+    Entity::Id e = em.create();
     em.assign<Position>(e, float(i), float(i));
     em.assign<Direction>(e, float(-i), float(-i));
   }
index 42312d39068bf772551a0105f4f4c9935e0f4201..63da01f1b0ab6f8ef6e853ffa4eabcfea3efbfd7 100644 (file)
@@ -54,7 +54,7 @@ class MovementSystem : public System<MovementSystem> {
 
 class TestManager : public entityx::Manager {
  public:
-  std::vector<Entity> entities;
+  std::vector<Entity::Id> entities;
 
   SystemManager &sm() { return system_manager; }
   EntityManager &em() { return entity_manager; }
@@ -65,7 +65,7 @@ class TestManager : public entityx::Manager {
 
   void initialize() override {
     for (int i = 0; i < 150; ++i) {
-      Entity e = entity_manager.create();
+      Entity::Id e = entity_manager.create();
       entities.push_back(e);
       if (i % 2 == 0)
         entity_manager.assign<Position>(e, 1, 2);