/Fomalhaut

A clean, simple, c++14, Entity Component System like Overwatch ECS architecture

Primary LanguageC++MIT LicenseMIT

Fomalhaut

A clean, simple, c++14, Entity Component System like Overwatch ECS architecture

Overview

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.

NOTE:

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.

Support(Need C++14)

  • gcc >= v5 (tested with v5.4.0)
  • clang
  • MSVC >= VS2015

Installation

  1. Git pull source code
  2. cd Fomalhaut && mkdir build
  3. Run ./run.sh

Tutorial

Create An EntityAdmin

EntityAdmin controlls all entities and systems. You can simply define it by the following code:

EntityAdmin admin; 

Create Component

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;
};

Create An Entity

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>();

Create A Demosystem And Iterate Components

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();
}