This is a simple entity component system library based on the Overwatch Gameplay Architecture and Netcode article. It is written in c++14 without other dependencies. You can easily add include-folder into your game project.
This is my thought about how the 'Overwatch' ECS should look. If you want to add it to a commercial project, you'd better read the source code and master it. Then add the features that you need.
- gcc >= v5 (tested with v5.4.0)
- clang
- MSVC >= VS2015
- Git pull source code
- cd Fomalhaut && mkdir build
- Run ./run.sh
EntityAdmin controlls all entities and systems. You can simply define it by the following code:
EntityAdmin admin;
Declare some components that derived from BaseComponent such as:
class MovementComponent : public BaseComponent
{
public:
void Reset(float velocity) { this->velocity = velocity; }
void Print() { std::cout << "MovementComponent: " << velocity << std::endl; }
float velocity;
};
class HealthComponent : public BaseComponent
{
public:
void Reset(float hp, float mana)
{
this->hp = hp;
this->mana = mana;
}
void Print() { std::cout << "HealthComponent: " << hp << '\t' << mana << std::endl; }
float hp, mana;
};
class PositionComponent : public BaseComponent
{
public:
void Reset(float px, float py, float pz)
{
x = px;
y = py;
z = pz;
}
void Print() { std::cout << "PositionComponent: " << x << '\t' << y << '\t' << z << std::endl; }
float x, y, z;
};
Entity is an aggregate that consists of one or more components. It was created by An EntityAdmin.
Entity& entity = admin.CreateEntity<Entity>();
You can simply add or replace component by:
entity.Add<PositionComponent>(3.f, 7.f, 10.f);
entity.Replace<PositionComponent>(10.f, 100.f, 100.f);
To check whether entity has any components:
bool result = entity.Has<HealthComponent>();
bool result = entity.Has<PositionComponent, HealthComponent>();
Remove one or more components:
entity.Remove<PositionComponent>();
entity.Remove<PositionComponent, HealthComponent>();
Use tuple to get some componets one-time:
PositionComponent* p = entity.Get<PositionComponent>();
std::tuple<PositionComponent*, HealthComponent*> va1 = entity.Get<PositionComponent, HealthComponent>();
class DemoSystem : public BaseSystem
{
public:
using BaseSystem::BaseSystem;
void Update(float time_step) override
{
for (PositionComponent* p : ComponentItr<PositionComponent>(admin_)) {
p->Print();
HealthComponent* h = p->Sibling<HealthComponent>();
if (h) { h->Print(); }
MovementComponent* m = p->Sibling<MovementComponent>();
if (m) { m->Print(); }
}
}
};
DemoSystem& sys = admin.CreateSystem<DemoSystem>();
sys.Update(0.1f);
Use tuple-iterator to iterate Entity that has specific components with specific condition:
for (std::tuple<PositionComponent*, HealthComponent*>&& t : ComponentItr<PositionComponent, HealthComponent>(
&admin, [](const PositionComponent*p, const HealthComponent* h) -> bool { return h->hp > 60; }))
{
std::get<0>(t)->Print();
std::get<1>(t)->Print();
}