diff --git a/app/create-ecs.js b/app/create-ecs.js index 78e4c23..417653d 100644 --- a/app/create-ecs.js +++ b/app/create-ecs.js @@ -4,6 +4,7 @@ import Systems from '@/ecs-systems/index.js'; export default function createEcs(Ecs) { const ecs = new Ecs({Components, Systems}); const defaultSystems = [ + 'Attract', 'ResetForces', 'ApplyControlMovement', 'IntegratePhysics', diff --git a/app/create-player.js b/app/create-player.js index 20fd8c7..c820738 100644 --- a/app/create-player.js +++ b/app/create-player.js @@ -40,6 +40,7 @@ export default async function createPlayer(id) { }, }, Health: {health: 100}, + Magnet: {strength: 24}, Position: {x: 128, y: 128}, Speed: {speed: 100}, Sound: {}, diff --git a/app/ecs-components/magnet.js b/app/ecs-components/magnet.js new file mode 100644 index 0000000..d7c670e --- /dev/null +++ b/app/ecs-components/magnet.js @@ -0,0 +1,7 @@ +import Component from '@/ecs/component.js'; + +export default class Magnet extends Component { + static properties = { + strength: {type: 'uint8'}, + }; +} diff --git a/app/ecs-components/magnetic.js b/app/ecs-components/magnetic.js new file mode 100644 index 0000000..9200d00 --- /dev/null +++ b/app/ecs-components/magnetic.js @@ -0,0 +1,4 @@ +import Component from '@/ecs/component.js'; + +export default class Magnetic extends Component { +} diff --git a/app/ecs-systems/apply-control-movement.js b/app/ecs-systems/apply-control-movement.js index d4304f2..5e27a07 100644 --- a/app/ecs-systems/apply-control-movement.js +++ b/app/ecs-systems/apply-control-movement.js @@ -14,6 +14,7 @@ export default class ApplyControlMovement extends System { default: ['Controlled', 'Forces', 'Speed'], }; } + tick() { for (const {Controlled, Forces, Speed} of this.select('default')) { if (!Controlled.locked) { diff --git a/app/ecs-systems/attract.js b/app/ecs-systems/attract.js new file mode 100644 index 0000000..3d5fc87 --- /dev/null +++ b/app/ecs-systems/attract.js @@ -0,0 +1,39 @@ +import {System} from '@/ecs/index.js'; +import {normalizeVector} from '@/util/math.js'; + +export default class Attract extends System { + + static queries() { + return { + default: ['Magnet'], + }; + } + + tick() { + 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, + }; + 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); + other.Forces.applyImpulse({ + x: Math.abs(toward.x) * 8 * Magnet.strength / difference.x, + y: Math.abs(toward.y) * 8 * Magnet.strength / difference.y, + }); + } + } + } + +} + diff --git a/app/ecs-systems/colliders.js b/app/ecs-systems/colliders.js index 40f24d2..f589754 100644 --- a/app/ecs-systems/colliders.js +++ b/app/ecs-systems/colliders.js @@ -90,6 +90,9 @@ export default class Colliders extends System { for (const otherId in wasCollidingWith) { if (!entity.Collider.collidingWith[otherId]) { const other = this.ecs.get(otherId); + if (!other || !other.Collider) { + continue; + } if (entity.Collider.collisionEndScriptInstance) { entity.Collider.collisionEndScriptInstance.context.other = other; Ticking.addTickingPromise(entity.Collider.collisionEndScriptInstance.tickingPromise()); diff --git a/app/ecs-systems/interactions.js b/app/ecs-systems/interactions.js index 36dd600..0d62cdc 100644 --- a/app/ecs-systems/interactions.js +++ b/app/ecs-systems/interactions.js @@ -13,7 +13,6 @@ export default class Interactions extends System { for (const entity of this.select('default')) { const {Interacts} = entity; Interacts.willInteractWith = 0 - // todo sort const entities = Array.from(this.ecs.system('Colliders').within(Interacts.aabb())) .filter((other) => other !== entity) .sort(({Position: l}, {Position: r}) => {