perf: use detached entities
This commit is contained in:
parent
172b457a8c
commit
623aabf525
|
@ -8,32 +8,32 @@ export default class Emitter {
|
|||
this.ecs = ecs;
|
||||
this.scheduled = [];
|
||||
}
|
||||
async allocate({entity, fields, shape}) {
|
||||
const allocated = this.ecs.get(await this.ecs.create(entity));
|
||||
async configure(entityId, {fields, shape}) {
|
||||
const entity = this.ecs.get(entityId);
|
||||
if (shape) {
|
||||
switch (shape.type) {
|
||||
case 'circle': {
|
||||
const r = Math.random() * TAU;
|
||||
allocated.Position.x += Math.cos(r) * shape.payload.radius;
|
||||
allocated.Position.y += Math.sin(r) * shape.payload.radius;
|
||||
entity.Position.x += Math.cos(r) * shape.payload.radius;
|
||||
entity.Position.y += Math.sin(r) * shape.payload.radius;
|
||||
break;
|
||||
}
|
||||
case 'filledCircle': {
|
||||
const r = Math.random() * TAU;
|
||||
allocated.Position.x += Math.cos(r) * Math.random() * shape.payload.radius;
|
||||
allocated.Position.y += Math.sin(r) * Math.random() * shape.payload.radius;
|
||||
entity.Position.x += Math.cos(r) * Math.random() * shape.payload.radius;
|
||||
entity.Position.y += Math.sin(r) * Math.random() * shape.payload.radius;
|
||||
break;
|
||||
}
|
||||
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);
|
||||
entity.Position.x += Math.random() * shape.payload.width - (shape.payload.width / 2);
|
||||
entity.Position.y += Math.random() * shape.payload.height - (shape.payload.height / 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fields) {
|
||||
for (const {easing = 'linear', path, value} of fields) {
|
||||
let walk = allocated;
|
||||
let walk = entity;
|
||||
const pathCopy = path.slice(0);
|
||||
const final = pathCopy.pop();
|
||||
for (const key of pathCopy) {
|
||||
|
@ -44,7 +44,7 @@ export default class Emitter {
|
|||
walk[final] = easings[easing](c - i, value[i], value[i + 1] - value[i], 1);
|
||||
}
|
||||
}
|
||||
return allocated;
|
||||
return entity;
|
||||
}
|
||||
emit(particle) {
|
||||
particle = {
|
||||
|
@ -52,59 +52,47 @@ export default class Emitter {
|
|||
entity: {
|
||||
Position: {},
|
||||
Sprite: {},
|
||||
VisibleAabb: {},
|
||||
...particle.entity,
|
||||
},
|
||||
}
|
||||
let {count = 1} = particle;
|
||||
const {frequency = 0} = particle;
|
||||
const stream = K.stream((emitter) => {
|
||||
const {entity, frequency = 0} = particle;
|
||||
const specifications = Array(count);
|
||||
for (let i = 0; i < count; ++i) {
|
||||
specifications[i] = entity;
|
||||
}
|
||||
const stream = K.stream(async (emitter) => {
|
||||
const entityIds = await this.ecs.createManyDetached(specifications);
|
||||
if (0 === frequency) {
|
||||
const promises = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
promises.push(
|
||||
this.allocate(particle)
|
||||
.then((entity) => {
|
||||
emitter.emit(entity);
|
||||
}),
|
||||
);
|
||||
this.ecs.attach(entityIds);
|
||||
for (const entityId of entityIds) {
|
||||
emitter.emit(this.configure(entityId, particle));
|
||||
}
|
||||
Promise.all(promises)
|
||||
.then(() => {
|
||||
emitter.end();
|
||||
});
|
||||
emitter.end();
|
||||
return;
|
||||
}
|
||||
const promise = this.allocate(particle)
|
||||
.then((entity) => {
|
||||
emitter.emit(entity);
|
||||
});
|
||||
const it = entityIds.values();
|
||||
const entityId = it.next().value;
|
||||
this.ecs.attach(new Set([entityId]));
|
||||
emitter.emit(this.configure(entityId, particle));
|
||||
count -= 1;
|
||||
if (0 === count) {
|
||||
promise.then(() => {
|
||||
emitter.end();
|
||||
});
|
||||
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);
|
||||
}),
|
||||
);
|
||||
const entityId = it.next().value;
|
||||
this.ecs.attach(new Set([entityId]));
|
||||
emitter.emit(this.configure(entityId, particle));
|
||||
accumulated -= frequency;
|
||||
count -= 1;
|
||||
}
|
||||
if (0 === count) {
|
||||
this.scheduled.splice(this.scheduled.indexOf(scheduled), 1);
|
||||
Promise.all(promises).then(() => {
|
||||
emitter.end();
|
||||
});
|
||||
emitter.end();
|
||||
}
|
||||
};
|
||||
this.scheduled.push(scheduled);
|
||||
|
|
|
@ -33,6 +33,9 @@ function tick(now) {
|
|||
const lastNearby = new Set(memory.values());
|
||||
for (const id in ecs.$$entities) {
|
||||
const entity = ecs.$$entities[id];
|
||||
if (ecs.$$detached.has(entity.id)) {
|
||||
continue;
|
||||
}
|
||||
lastNearby.delete(id);
|
||||
if (!memory.has(id)) {
|
||||
update[id] = entity.toJSON();
|
||||
|
|
Loading…
Reference in New Issue
Block a user