94 lines
2.2 KiB
JavaScript
94 lines
2.2 KiB
JavaScript
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|