silphius/app/ecs/systems/visible-aabbs.js
2024-07-30 09:56:53 -05:00

87 lines
2.0 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) {
const {AreaSize} = this.ecs.get(1)
if (AreaSize) {
const {x, y} = AreaSize;
if (
!this.hash ||
(
this.hash.area.x !== x
|| this.hash.area.y !== y
)
) {
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 (!this.hash) {
return;
}
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) {
size = Sprite.size;
}
/* 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;
}
}