import {System} from '@/ecs/index.js'; import SpatialHash from '@/util/spatial-hash.js'; export default class Colliders 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.Collider) { return; } entity.Collider.recalculateAabbs(); this.hash.update(entity.Collider.aabb, entity.id); } tick() { const seen = {}; for (const entity of this.ecs.changed(['Position'])) { if (seen[entity.id]) { continue; } seen[entity.id] = true; if (!entity.Collider) { continue; } this.updateHash(entity); for (const other of this.within(entity.Collider.aabb)) { if (seen[other.id]) { continue; } seen[other.id] = true; if (!other.Collider) { continue; } if (entity.Collider.isCollidingWith(other.Collider)) { console.log('collide', entity, other); } } } } within(query) { const {x0, x1, y0, y1} = query; const [cx0, cy0] = this.hash.chunkIndex(x0, y0); const [cx1, cy1] = this.hash.chunkIndex(x1, y1); const seen = {}; const within = new Set(); for (let cy = cy0; cy <= cy1; ++cy) { for (let cx = cx0; cx <= cx1; ++cx) { for (const id of this.hash.chunks[cx][cy]) { if (seen[id]) { continue; } seen[id] = true; const entity = this.ecs.get(id); if (entity.Collider.isWithin(query)) { within.add(entity); } } } } return within; } }