import { System } from '@serpentity/serpentity'; import { Body, Vector } from 'matter-js'; const internals = { kForce: 0.0001 }; import PhysicalWithExternalForceNode from '../nodes/physical_with_external_force'; /** * Applies physica from external forces (eg. controls) to the physics body * * @extends {external:Serpentity.System} * @class ApplyForceSystem * @param {object} config a configuration object to extend. */ export default class ApplyForceSystem extends System { constructor(config = {}) { super(); /** * The node collection of entities that have external force * * @property {external:Serpentity.NodeCollection} physicalEntities * @instance * @memberof ApplyForceSystem */ this.physicalEntities = null; } /** * Initializes system when added. Requests physics nodes * * @function added * @memberof ApplyForceSystem * @instance * @param {external:Serpentity.Engine} engine the serpentity engine to * which we are getting added */ added(engine) { this.physicalEntities = engine.getNodes(PhysicalWithExternalForceNode); } /** * Clears system resources when removed. * * @function removed * @instance * @memberof ApplyForceSystem */ removed() { this.physicalEntities = null; } /** * Runs on every update of the loop. Updates the body based on the force * component * * @function update * @instance * @param {Number} currentFrameDuration the duration of the current * frame * @memberof ApplyForceSystem */ update(currentFrameDuration) { for (const physicalEntity of this.physicalEntities) { const body = physicalEntity.body.body; const force = physicalEntity.force; const forceVector = Vector.create(force.x * internals.kForce, force.y * internals.kForce); // Store the last angle and apply force on non-zero forces if (force.x || force.y) { force.lastAngle = Math.atan2(force.y, force.x); Body.applyForce(body, { x: body.position.x, y: body.position.y }, forceVector ); } // Reset the force force.x = 0; force.y = 0; } } }