diff --git a/packages/ecs/src/ecs.js b/packages/ecs/src/ecs.js index 6c00ebf..fbe05d1 100644 --- a/packages/ecs/src/ecs.js +++ b/packages/ecs/src/ecs.js @@ -1,6 +1,7 @@ /* eslint-disable guard-for-in, max-classes-per-file, no-continue, no-restricted-syntax */ import Bundle from './bundle'; import Component from './component'; +import System from './system'; export default class Ecs { @@ -36,9 +37,9 @@ export default class Ecs { } } - addSystem(System) { + addSystem(source) { const ecs = this; - class WrappedSystem extends System { + class WrappedSystem extends System.normalize(source) { constructor(Components) { super(Components); @@ -53,10 +54,15 @@ export default class Ecs { return this.ecs.createMany(count, components); } + // eslint-disable-next-line class-methods-use-this + get source() { + return source; + } + } - const system = new WrappedSystem(this.Components); - this.$$systems.push(system); - return system; + const wrappedSystem = new WrappedSystem(this.Components); + wrappedSystem.reindex(Object.keys(this.$$entities)); + this.$$systems.push(wrappedSystem); } create(components = {}) { @@ -321,6 +327,13 @@ export default class Ecs { } } + removeSystem(SystemLike) { + const index = this.$$systems.findIndex((system) => SystemLike === system.source); + if (-1 !== index) { + this.$$systems.splice(index, 1); + } + } + setClean() { for (const i in this.Components) { this.Components[i].setClean(); diff --git a/packages/ecs/src/system.js b/packages/ecs/src/system.js index 4c97ffb..126bbea 100644 --- a/packages/ecs/src/system.js +++ b/packages/ecs/src/system.js @@ -1,4 +1,4 @@ -/* eslint-disable guard-for-in, no-restricted-syntax */ +/* eslint-disable guard-for-in, max-classes-per-file, no-restricted-syntax */ import Query from './query'; @@ -31,6 +31,18 @@ export default class System { } } + static normalize(SystemLike) { + if (SystemLike.prototype instanceof System) { + return SystemLike; + } + if ('function' === typeof SystemLike) { + class TickingSystem extends System {} + TickingSystem.prototype.tick = SystemLike; + return TickingSystem; + } + return undefined; + } + static queries() { return {}; } diff --git a/packages/ecs/test/ecs.js b/packages/ecs/test/ecs.js index 7794d4e..5e37259 100644 --- a/packages/ecs/test/ecs.js +++ b/packages/ecs/test/ecs.js @@ -13,6 +13,34 @@ const Position = { z: 'int32', }; +it('can add and remove systems at runtime', () => { + const ecs = new Ecs(); + let oneCount = 0; + let twoCount = 0; + const oneSystem = () => { + oneCount++; + }; + ecs.addSystem(oneSystem); + ecs.tick(); + expect(oneCount) + .to.equal(1); + const twoSystem = () => { + twoCount++; + }; + ecs.addSystem(twoSystem); + ecs.tick(); + expect(oneCount) + .to.equal(2); + expect(twoCount) + .to.equal(1); + ecs.removeSystem(oneSystem); + ecs.tick(); + expect(oneCount) + .to.equal(2); + expect(twoCount) + .to.equal(2); +}); + it('can create entities with components', () => { const ecs = new Ecs({Empty, Position}); const entity = ecs.create({Empty: {}, Position: {y: 420}});