I’m trying to get a better feel for how an entity-component-system system works. I’m most comfortable in JavaScript, so that’s what I wrote it in. I recognize that JS isn’t the best language for this kind of thing (duck-typing, no interfaces, etc.), but I’m mostly looking for ways my code violates ECS principles, and also any non-idiomatic JavaScript.
class Component { get type() { return this.constructor.name; } constructor(data) { this.data = data; } } class Entity { get type() { return this.constructor.name; } constructor(id) { this.id = id; this.components = []; } get(type) { return this.components.find(c => c.type === type); } assign(component) { const included = this.get(component.type); if (included === undefined) this.components.push(component); else this.components[this.components.indexOf(included)] = component; } } class System { get type() { return this.constructor.name; } constructor(types, callback) { this.types = types; this.callback = callback; } run(entities) { entities.forEach(e => this.types.every(t => e.get(t) !== undefined) && this.callback(e) ); } }
Also, here’s a basic example of how the system gets extended.
class ErrorComponent extends Component { constructor(error) { super(error); } } class ErrorSystem extends System { constructor() { super( ["ErrorComponent"], e => console.error(e.get("ErrorComponent").data) ); } } const testComponent = new ErrorComponent("test"); const testComponent2 = new ErrorComponent("test2"); const testEntity = new Entity("test"); testEntity.assign(testComponent); testEntity.assign(testComponent2); const entities = [testEntity]; const testSystem = new ErrorSystem(); testSystem.run(entities); ```