refactor: collision systems

This commit is contained in:
cha0s 2024-07-28 18:40:58 -05:00
parent ab626f8f9a
commit 99b8d0f633
7 changed files with 67 additions and 51 deletions

View File

@ -167,7 +167,7 @@ export default class Collider extends Component {
}
closest(aabb) {
const entity = ecs.get(this.entity);
return Array.from(ecs.system('Colliders').within(aabb))
return Array.from(ecs.system('MaintainColliderHash').within(aabb))
.filter((other) => other !== entity)
.sort(({Position: l}, {Position: r}) => {
return distance(entity.Position, l) > distance(entity.Position, r) ? -1 : 1;

View File

@ -20,7 +20,7 @@ export default class Attract extends System {
};
let s = Magnet.strength;
s = s * s;
for (const other of this.ecs.system('Colliders').within(aabb)) {
for (const other of this.ecs.system('MaintainColliderHash').within(aabb)) {
if (other === entity || !other.Magnetic) {
continue;
}

View File

@ -1,53 +1,15 @@
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',
after: 'MaintainColliderHash',
};
}
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;
}
this.hash.update(entity.Collider.aabb, entity.id);
}
tick() {
const checked = new Map();
for (const entity of this.ecs.changed(['Direction'])) {
if (!entity.Collider) {
continue;
}
entity.Collider.updateAabbs();
}
for (const entity of this.ecs.changed(['Position'])) {
this.updateHash(entity);
}
for (const entity of this.ecs.changed(['Position'])) {
if (!entity.Collider) {
continue;
@ -55,7 +17,7 @@ export default class Colliders extends System {
if (!checked.has(entity)) {
checked.set(entity, new Set());
}
const within = this.within(entity.Collider.aabb);
const within = this.ecs.system('MaintainColliderHash').within(entity.Collider.aabb);
for (const other of within) {
if (entity === other || !other.Collider) {
continue;
@ -77,12 +39,4 @@ export default class Colliders extends System {
}
}
within(query) {
const within = new Set();
for (const id of this.hash.within(query)) {
within.add(this.ecs.get(id));
}
return within;
}
}

View File

@ -0,0 +1,60 @@
import {System} from '@/ecs/index.js';
import SpatialHash from '@/util/spatial-hash.js';
export default class MaintainColliderHash 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;
}
this.hash.update(entity.Collider.aabb, entity.id);
}
tick() {
for (const entity of this.ecs.changed(['Direction'])) {
if (!entity.Collider) {
continue;
}
entity.Collider.updateAabbs();
}
for (const entity of this.ecs.changed(['Position'])) {
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;
}
}

View File

@ -11,6 +11,7 @@ export default class ClientEcs extends Ecs {
constructor(specification) {
super(specification);
[
'MaintainColliderHash',
].forEach((defaultSystem) => {
const System = this.system(defaultSystem);
if (System) {

View File

@ -14,6 +14,7 @@ export default function createEcs(Ecs) {
'PlantGrowth',
'FollowCamera',
'VisibleAabbs',
'MaintainColliderHash',
'Colliders',
'ControlDirection',
'SpriteDirection',

View File

@ -6,7 +6,7 @@ const filtered = []
for (const position of projected) {
const x0 = position.x * tileSize.x;
const y0 = position.y * tileSize.y;
const entities = ecs.system('Colliders').within({
const entities = ecs.system('MaintainColliderHash').within({
x0,
x1: x0 + tileSize.x - 1,
y0,