aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--entityx/Benchmarks_test.cc32
-rw-r--r--entityx/Entity.cc2
-rw-r--r--entityx/Entity.h30
4 files changed, 49 insertions, 17 deletions
diff --git a/README.md b/README.md
index a658fb7..37786d3 100644
--- a/README.md
+++ b/README.md
@@ -104,7 +104,7 @@ if (position) {
#### Implementation notes
- Components must provide a no-argument constructor.
-- The current implementation can handle up to 64 components in total. This can be extended with little effort.
+- The default implementation can handle up to 64 components in total. This can be extended by changing the `EntityManager::MAX_COMPONENTS` constant.
### Systems (implementing behavior)
diff --git a/entityx/Benchmarks_test.cc b/entityx/Benchmarks_test.cc
index 625af29..bee7d15 100644
--- a/entityx/Benchmarks_test.cc
+++ b/entityx/Benchmarks_test.cc
@@ -1,3 +1,4 @@
+#include <iostream>
#include <vector>
#include <gtest/gtest.h>
#include <boost/timer/timer.hpp>
@@ -19,6 +20,8 @@ TEST_F(BenchmarksTest, TestCreateEntities) {
boost::timer::auto_cpu_timer t;
uint64_t count = 10000000L;
+ cout << "creating " << count << " entities" << endl;
+
for (uint64_t i = 0; i < count; i++) {
em.create();
}
@@ -33,6 +36,7 @@ TEST_F(BenchmarksTest, TestDestroyEntities) {
}
boost::timer::auto_cpu_timer t;
+ cout << "destroying " << count << " entities" << endl;
for (auto e : entities) {
e.destroy();
@@ -48,8 +52,11 @@ TEST_F(BenchmarksTest, TestCreateEntitiesWithListener) {
Listener listen;
ev.subscribe<EntityCreatedEvent>(listen);
- boost::timer::auto_cpu_timer t;
uint64_t count = 10000000L;
+
+ boost::timer::auto_cpu_timer t;
+ cout << "creating " << count << " entities while notifying a single EntityCreatedEvent listener" << endl;
+
vector<Entity> entities;
for (uint64_t i = 0; i < count; i++) {
entities.push_back(em.create());
@@ -67,9 +74,32 @@ TEST_F(BenchmarksTest, TestDestroyEntitiesWithListener) {
}
boost::timer::auto_cpu_timer t;
+ cout << "destroying " << count << " entities" << endl;
for (auto e : entities) {
e.destroy();
}
}
+struct Position : public Component<Position> {
+};
+
+TEST_F(BenchmarksTest, TestEntityIteration) {
+ uint64_t count = 10000000L;
+ vector<Entity> entities;
+ for (uint64_t i = 0; i < count; i++) {
+ auto e = em.create();
+ e.assign<Position>();
+ entities.push_back(e);
+ }
+
+ boost::timer::auto_cpu_timer t;
+ cout << "iterating over " << count << " entities with a component 10 times" << endl;
+
+ for (int i = 0; i < 10; ++i) {
+ for (auto e : em.entities_with_components<Position>()) {
+ boost::shared_ptr<Position> position = e.component<Position>();
+ }
+ }
+}
+
diff --git a/entityx/Entity.cc b/entityx/Entity.cc
index 039cc4a..51a80ba 100644
--- a/entityx/Entity.cc
+++ b/entityx/Entity.cc
@@ -13,8 +13,6 @@
namespace entityx {
-const Entity::Id Entity::INVALID = Entity::Id(-1);
-
BaseComponent::Family BaseComponent::family_counter_ = 0;
void Entity::invalidate() {
diff --git a/entityx/Entity.h b/entityx/Entity.h
index 644456f..76e646a 100644
--- a/entityx/Entity.h
+++ b/entityx/Entity.h
@@ -49,7 +49,7 @@ class Entity {
/**
* Id of an invalid Entity.
*/
- static const Id INVALID;
+ static const Id INVALID = Id(-1);
Entity() {}
@@ -212,6 +212,8 @@ struct ComponentAddedEvent : public Event<ComponentAddedEvent<T>> {
*/
class EntityManager : boost::noncopyable {
public:
+ static const int MAX_COMPONENTS = 64;
+
EntityManager(EventManager &event_manager) : event_manager_(event_manager) {}
class View {
@@ -221,15 +223,15 @@ class EntityManager : boost::noncopyable {
/// 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) {}
+ ComponentMaskPredicate(const std::vector<std::bitset<MAX_COMPONENTS>> &entity_bits, std::bitset<MAX_COMPONENTS> mask) : entity_bits_(entity_bits), mask_(mask) {}
bool operator () (EntityManager &, Entity::Id entity) {
return (entity_bits_.at(entity) & mask_) == mask_;
}
private:
- const std::vector<uint64_t> &entity_bits_;
- uint64_t mask_;
+ const std::vector<std::bitset<MAX_COMPONENTS>> &entity_bits_;
+ std::bitset<MAX_COMPONENTS> mask_;
};
/// An iterator over a view of the entities in an EntityManager.
@@ -422,7 +424,7 @@ class EntityManager : boost::noncopyable {
*/
template <typename C, typename ... Components>
View entities_with_components() {
- uint64_t mask = component_mask<C, Components ...>();
+ auto mask = component_mask<C, Components ...>();
return View(this, View::ComponentMaskPredicate(entity_component_mask_, mask));
}
@@ -431,7 +433,7 @@ class EntityManager : boost::noncopyable {
*/
template <typename C, typename ... Components>
View entities_with_components(boost::shared_ptr<C> &c, Components && ... args) {
- uint64_t mask = component_mask(c, args ...);
+ auto mask = component_mask(c, args ...);
return
View(this, View::ComponentMaskPredicate(entity_component_mask_, mask))
.unpack_to(c, args ...);
@@ -472,22 +474,24 @@ class EntityManager : boost::noncopyable {
private:
template <typename C>
- uint64_t component_mask() {
- return uint64_t(1) << C::family();
+ std::bitset<MAX_COMPONENTS> component_mask() {
+ std::bitset<MAX_COMPONENTS> mask;
+ mask.set(C::family());
+ return mask;
}
template <typename C1, typename C2, typename ... Components>
- uint64_t component_mask() {
+ std::bitset<MAX_COMPONENTS> component_mask() {
return component_mask<C1>() | component_mask<C2, Components ...>();
}
template <typename C>
- uint64_t component_mask(const boost::shared_ptr<C> &c) {
- return uint64_t(1) << C::family();
+ std::bitset<MAX_COMPONENTS> component_mask(const boost::shared_ptr<C> &c) {
+ return component_mask<C>();
}
template <typename C1, typename C2, typename ... Components>
- uint64_t component_mask(const boost::shared_ptr<C1> &c1, const boost::shared_ptr<C2> &c2, Components && ... args) {
+ std::bitset<MAX_COMPONENTS> component_mask(const boost::shared_ptr<C1> &c1, const boost::shared_ptr<C2> &c2, Components && ... args) {
return component_mask<C1>(c1) | component_mask<C2, Components ...>(c2, args...);
}
@@ -515,7 +519,7 @@ class EntityManager : boost::noncopyable {
// A nested array of: components = entity_components_[family][entity]
std::vector<std::vector<boost::shared_ptr<BaseComponent>>> entity_components_;
// Bitmask of components associated with each entity. Index into the vector is the Entity::Id.
- std::vector<uint64_t> entity_component_mask_;
+ std::vector<std::bitset<MAX_COMPONENTS>> entity_component_mask_;
// List of available Entity::Id IDs.
std::list<Entity::Id> free_list_;
};