import K from 'kefir'; export default class Emitter { constructor(ecs) { this.ecs = ecs; this.scheduled = []; } async allocate({entity, shape}) { const allocated = this.ecs.get(await this.ecs.create(entity)); if (shape) { switch (shape.type) { case 'filledRect': { allocated.Position.x += Math.random() * shape.payload.width - (shape.payload.width / 2); allocated.Position.y += Math.random() * shape.payload.height - (shape.payload.height / 2); break; } } } return allocated; } emit(particle) { particle = { ...particle, entity: { Position: {}, Sprite: {}, VisibleAabb: {}, ...particle.entity, }, } let {count = 1} = particle; const {frequency = 0} = particle; const stream = K.stream((emitter) => { if (0 === frequency) { const promises = []; for (let i = 0; i < count; ++i) { promises.push( this.allocate(particle) .then((entity) => { emitter.emit(entity); }), ); } Promise.all(promises) .then(() => { emitter.end(); }); return; } const promise = this.allocate(particle) .then((entity) => { emitter.emit(entity); }); count -= 1; if (0 === count) { promise.then(() => { emitter.end(); }); return; } const promises = [promise]; let accumulated = 0; const scheduled = (elapsed) => { accumulated += elapsed; while (accumulated > frequency && count > 0) { promises.push( this.allocate(particle) .then((entity) => { emitter.emit(entity); }), ); accumulated -= frequency; count -= 1; } if (0 === count) { this.scheduled.splice(this.scheduled.indexOf(scheduled), 1); Promise.all(promises).then(() => { emitter.end(); }); } }; this.scheduled.push(scheduled); }); return stream; } tick(elapsed) { for (const ticker of this.scheduled) { ticker(elapsed); } } }