refactor: collision systems
This commit is contained in:
parent
ab626f8f9a
commit
99b8d0f633
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
60
app/ecs/systems/maintain-collider-hash.js
Normal file
60
app/ecs/systems/maintain-collider-hash.js
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@ export default class ClientEcs extends Ecs {
|
|||
constructor(specification) {
|
||||
super(specification);
|
||||
[
|
||||
'MaintainColliderHash',
|
||||
].forEach((defaultSystem) => {
|
||||
const System = this.system(defaultSystem);
|
||||
if (System) {
|
||||
|
|
|
@ -14,6 +14,7 @@ export default function createEcs(Ecs) {
|
|||
'PlantGrowth',
|
||||
'FollowCamera',
|
||||
'VisibleAabbs',
|
||||
'MaintainColliderHash',
|
||||
'Colliders',
|
||||
'ControlDirection',
|
||||
'SpriteDirection',
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user