Skip to content
This repository has been archived by the owner on Dec 14, 2021. It is now read-only.

Latest commit

 

History

History
executable file
·
141 lines (100 loc) · 4.64 KB

README.md

File metadata and controls

executable file
·
141 lines (100 loc) · 4.64 KB

ecx

Lang Version Dependencies License

Build Status Build Status

ECX is Entity Component System framework for Haxe

Libraries (work in progress):

World

Initialization

var config = new WorldConfig([...]);
var world = Engine.createWorld(config, ?capacity);

Entity

Entity is just integer id value. 0 is reserved as invalid id.

Service

All services are known at world creation. World provides possibility to resolve services. World::resolve use constant Class<Service> for resolving. At compile-time these expressions will be translated to lookup array access by constant index with unsafe cast (pseudo example: cast _services[8]). For hxcpp poiter trick is used to avoid generating dynamic_cast.

Injection

Each service could have dependencies on different services. With Wire<T:Service> you could inject your dependencies to instance fields.

For example we need to inject TimeSystem system to our MovementSystem

class MovementSystem extends System {
    var _time:Wire<TimeSystem>;
    ...
    override function update() {
        var dt = _time.dt;
        ...
    }
}

Family

For all System types. For example we need to track all active(live) entities with components: Transform, Node and Renderable.

class MovementSystem extends System {
    var _entities:Family<Transform, Node, Renderable>;
    ...
    override function update() {
        // Note: typeof _entities is Array<Entity>
        for(entity in _entities) {
            // only entities with required component will be displayed
            trace(entity.id);
        }
    }
}

Sometimes it could be useful to mark some optional component in Family declaration just for readability. You can wrap each optional Component type in parentheses () and it will be ignored by Family, but will be notated.

var _entities:Family<Transform, Node, Renderable, (Scissors)>;

System Flags

  • IDLE: System doesn't override update method. Should not be updated.
  • CONFIG: System is defined with @:config meta. This system is just configurator. It will be deleted after World initialization phase.

Component

Component is a way to associate [data] per Entity. You could just use component-builders to define your own components.

class Position extends AutoComp<Point> {}

/// later just use it like Point class per entity
_position.get(entity).x = 10;

Or you could create any custom crazy ComponentStorage / ComponentManager.

class Color extends Service implements Component {
    // BitmapData is used just to demonstrate that you are not limited to anything to store <component data> per <entity>
    // Each pixel is color for entity
    var _colors:BitmapData;

    ...

    inline public function get(entity:Entity):Int {
        _colors.getPixel32(entity.id % _stride, Std.int(entity.id / _stride));
    }

    ....
}

Injection: World Component is Service, so you are able to invoke all messages directly to other services. Implementation: Component is just interface, you could iterate all registered components and access their base API per entity. It's handy for automatically cloning or serialization.

CTTI

ServiceType, ServiceSpec, ComponentType, ClassMacroTools

RTTI

TypeManager (WIP)

Debug

-D ecx_debug for debugging

-D ecx_macro_debug for macro debugging

-D ecx_report to get and analyse ecx_wires.html and ecx_matrix.html report files generated during compilation

TODO:

  • Rethink world initialization:
    • Are we are ok that instance of service could be created outside by default?
  • Rethink system-flags
  • Delete configurator services
  • Add more information on specific cases of AutoComp
  • Pack for dense storage
  • Entity Generations