silphius/app/ecs-systems/attract.js
2024-07-04 12:58:33 -05:00

53 lines
1.6 KiB
JavaScript

import {System} from '@/ecs/index.js';
import {distance, normalizeVector} from '@/util/math.js';
export default class Attract extends System {
static queries() {
return {
default: ['Magnet'],
};
}
tick(elapsed) {
for (const entity of this.select('default')) {
const {Magnet, Position} = entity;
const aabb = {
x0: Position.x - Magnet.strength / 2,
x1: Position.x + (Magnet.strength / 2) - 1,
y0: Position.y - Magnet.strength / 2,
y1: Position.y + (Magnet.strength / 2) - 1,
};
let s = Magnet.strength;
s = s * s;
for (const other of this.ecs.system('Colliders').within(aabb)) {
if (other === entity || !other.Magnetic) {
continue;
}
const difference = {
x: entity.Position.x - other.Position.x,
y: entity.Position.y - other.Position.y,
};
const toward = normalizeVector(difference);
let d = distance(entity.Position, other.Position);
if (d > 0) {
const inv = s * (1 / (d * d));
let impulse = {
x: toward.x * inv,
y: toward.y * inv,
};
if (Math.sign(entity.Position.x - (impulse.x * elapsed + other.Position.x)) !== Math.sign(difference.x)) {
impulse.x = difference.x / elapsed;
}
if (Math.sign(entity.Position.y - (impulse.y * elapsed + other.Position.y)) !== Math.sign(difference.y)) {
impulse.y = difference.y / elapsed;
}
other.Forces.applyImpulse(impulse);
}
}
}
}
}