75 lines
1.8 KiB
JavaScript
75 lines
1.8 KiB
JavaScript
import {System} from '@/ecs/index.js';
|
|
import SpatialHash from '@/util/spatial-hash.js';
|
|
|
|
export default class VisibleAabbs extends System {
|
|
|
|
hash;
|
|
|
|
deindex(entities) {
|
|
super.deindex(entities);
|
|
for (const id of entities) {
|
|
this.hash.remove(id);
|
|
}
|
|
}
|
|
|
|
static get priority() {
|
|
return {
|
|
after: 'IntegratePhysics',
|
|
};
|
|
}
|
|
|
|
reindex(entities) {
|
|
for (const id of entities) {
|
|
if (1 === id) {
|
|
this.hash = new SpatialHash(this.ecs.get(1).AreaSize);
|
|
}
|
|
}
|
|
super.reindex(entities);
|
|
for (const id of entities) {
|
|
this.updateHash(this.ecs.get(id));
|
|
}
|
|
}
|
|
|
|
updateHash(entity) {
|
|
if (!entity.VisibleAabb) {
|
|
this.hash.remove(entity.id);
|
|
return;
|
|
}
|
|
this.hash.update(entity.VisibleAabb, entity.id);
|
|
}
|
|
|
|
tick() {
|
|
for (const entity of this.ecs.changed(['Position'])) {
|
|
const {Position: {x, y}, Sprite, VisibleAabb} = entity;
|
|
if (VisibleAabb) {
|
|
let size = undefined;
|
|
if (Sprite) {
|
|
const frame = Sprite.animation
|
|
? Sprite.$$sourceJson.animations[Sprite.animation][Sprite.frame]
|
|
: '';
|
|
size = Sprite.$$sourceJson.frames[frame].sourceSize;
|
|
}
|
|
/* v8 ignore next 3 */
|
|
if (!size) {
|
|
throw new Error(`no size for aabb for entity ${entity.id}(${JSON.stringify(entity.toJSON(), null, 2)})`);
|
|
}
|
|
VisibleAabb.x0 = x - Sprite.anchor.x * size.w;
|
|
VisibleAabb.x1 = x + (1 - Sprite.anchor.x) * size.w;
|
|
VisibleAabb.y0 = y - Sprite.anchor.y * size.h;
|
|
VisibleAabb.y1 = y + (1 - Sprite.anchor.y) * size.h;
|
|
this.updateHash(entity);
|
|
}
|
|
}
|
|
}
|
|
|
|
within(query) {
|
|
const within = new Set();
|
|
for (const id of this.hash.within(query)) {
|
|
within.add(this.ecs.get(id));
|
|
}
|
|
return within;
|
|
}
|
|
|
|
}
|
|
|