eliasku / ecx

ECX is Entity Component System framework for Haxe
52 stars 10 forks source link

How to run this thing, and usage of `World#invalidate` #2

Closed Misiur closed 8 years ago

Misiur commented 8 years ago

This might be a silly question, but I reread whole test folder and ecx benchmark code, yet I can't find the answer: How to run this thing? So far I met two types of ECS:

  1. Use world.run(), we'll take care of framerate and stuff.
  2. Create your own game loop, then put in world.update() and we'll take care of updating the systems.

I can see there is world._systems, but it's only used in WorldConstructor#initializeSystems.

The second question: when to use World#invalidate? When I add a component to an entity? When I add/remove entity from the world?

Thank you.

eliasku commented 8 years ago

Question is quite reasonable. ecx library is in progress right now. I have no stable API yet. I've created the wiki-page with some answers: https://github.com/eliasku/ecx/wiki/Running-Systems I hope this information is helpful.

Second question. Present design is to create/delete entity with world. When you have alive entity, you able to add/remove component. Families will be updated on next world#invalidate. But sometimes we need to update state immediately per component-behaviour, so there are component#onAdded and component#onRemoved

eliasku commented 8 years ago

I'm working on it in my personal free time (like a personal haxe research project). Anyway I have TODO to create examples and snippets. If you're going to experiment with ecx, feel free to contact me for ideological decisions on ecx design, or even contribute more documentation, or samples/examples/snippets.

Misiur commented 8 years ago

So far ECX is blazing fast for my purposes. One more question: is there a way to add system to world after creating the world? I see there's some complexish stuff with createSystemsOrder and createSystemLookup. In edge I used to have setup like this:

world = new World();
creator = new EntityCreator(world.engine, this);
world.physics.add(new BulletCollision(creator));

EntityCreator requires world to, well, create entities, and some systems need the creator.

Misiur commented 8 years ago

Few things:

  1. We can steal edge's typebuilding macros, for components. For example
package;

import edge.IComponent;

class MyComponent implements IComponent
{
    var x:Float;
    var y:Float; 
}

expands to something like

class MyComponent implements IComponent
{
    public var x:Float;
    public var y:Float; 

    public function new(x:Float, y:Float)
    {
        this.x = x;
        this.y = y;
    }
}
  1. Passing args to update. In Edge, each system has injected deltaTime value, which is quite important for all systems. The systems are not inherited, just using a common interface with typebuilding magic. Currently I can neither pass an argument to update (overriding doesn't allow that), and adding a new property won't work when working on System type without casting.
  2. I can't get past some weird errors:
D:/Dev/ecx-dev/src/ecx/macro/TypeBuilder.hx:77: characters 12-21 : Not enough arguments, expected accelerationRate:Float, rotationAccelerationRate:Float
Source/input/component/MotionControls.hx:5: lines 5-15 : Defined in this class

Class is really basic:

package input.component;

import ecx.Component;

class MotionControls extends Component
{
    public var accelerationRate:Float;
    public var rotationAccelerationRate:Float;

    public function new(accelerationRate:Float, rotationAccelerationRate:Float)
    {
        this.accelerationRate = accelerationRate;
        this.rotationAccelerationRate = rotationAccelerationRate;
    }
}

This doesn't happen for all components, and I can't quite get where it's coming from. I'm using something like

var ship = world.edit(createShip(shipSheet));
ship.addInstance(new MotionControls(100, 60));
ship.addInstance(new Life(1000));

return ship.entity;
eliasku commented 8 years ago
  1. Component require default constructor. If you need arguments to constructor, make them all optional. (at design level it will allow easily do automatic component objects pooling)
  2. ECX is for Entity-Component-X. So System is X. Traditionally pure-ecs libraries limit Systems to do only logic (NO STATE inside systems, only function). For ECX I trade this limitation to provide something like service-based architecture design. So World in system's context is just ServiceLocator pattern. ECX provides wiring systems at compile-time for you. All systems need to be known before you create your world. This allow me to skip requirments to the client to follow ALL specific systems life-time cycles and cases. Just keep it simple. If you will need this system in run-time - just create it in config and build your initial state it during first update call (look at example, GameManager creates game-state-entity in update method).

So, finally I've made example especially for you: https://github.com/eliasku/ecx-richardlord-asteroids (required openfl and to update ecx 0.0.4 via haxelib)