Skip to content

Archetypes

Dimitri Pomier edited this page Oct 20, 2021 · 1 revision

A particularity that can be confusing when coming from traditional ECS libraries, is how components work in ecso. Let's assume the following example:

typedef Position = {
    var x : Float;
    var y : Float;
}

One could think there is one single component in the above example: Position, yet there are actually two. In fact, ecso will consider x and y as two independent components. The typedef Position is only an alias for the anonymous structure { x : Int, y : Int }, which here refers to a partial entity-archetype including the components x and y.

For instance we could have a system matching only the component x of the above archetype, without caring about the existence of y:

function moveStraightSystem (entity : { x:Int }) {
    entity.x++;
}

Understanding this aspect makes apparent that component naming takes a critical dimension in ecso. It won't be possible to use another x component with a different type. This limitation is intended: it locks down component types, and reduce confusion when reading your code.

This approach also allows for great flexibility. You could, for instance, adopt a more traditional data representation such as the following equivalent:

typedef Pos = {
    var position : Point;
}

function moveStraightSystem (entity : Pos) {
    entity.position.x++;
}

In this context, typedefs show themself particularly handy to manipulate components. Following the above example, let's add a velocity component:

typedef Velocity = {
    var velocity : Point;
}

// systems can then use the above typedef instead of writing the complete archetype `{ position : Point, velocity : Point }`:
function moveStraightSystem (entity : Pos & Velocity) {
    entity.position.x += entity.velocity.x;
}

// we can shorten them further for future use:
typedef MovingEntity = Pos & Velocity

// create an entity with the components `position : Point` and `velocity : Point`:
entities.createEntity({
    position: new Point(),
    velocity: new Point()
});

For more reading on typedefs, you can visit the Haxe manual.

Collision between libraries

If you use third-party libraries using ecso alongside your project, you might end up with component collisions. This is the case when you get errors such as:

  • [ECSO] Cannot redefine x's type
  • [ECSO] Cannot downcast component x
  • [ECSO] Cannot upcast component x.

Do not panic. To address this, ecso provides the possibility to define different contexts to isolate components from each other. In fact, EntityGroup itself is a context where each created entity belongs to, and where each component has a unique type. You can create your own contexts instead of the default EntityGroup, and isolate your component definitions from external code:

var myGroup = new MyGroup();
myGroup.createEntity({ someComponent : SomeType });

var otherGroup = new EntityGroup();
otherGroup.createEntity({ someComponent : AnotherType });

Clone this wiki locally