import { System } from '@serpentity/serpentity'; import { Engine, World } from 'matter-js'; import PhysicalNode from '../nodes/physical'; import GrabAreaNode from '../nodes/grab_area'; const internals = { kNoEngine: 'No matter js physics engine found. Make sure you set the `engine` key in the config object when initializing.' }; /** * Adds and removes objects to the physics world and calls update * * @extends {external:Serpentity.System} * @class PhysicsWorldControlSystem * @param {object} config a configuration object to extend. */ export default class PhysicsWorldControlSystem extends System { constructor(config = {}) { super(); /** * The node collection of physics entities * * @property {external:Serpentity.NodeCollection} physicalEntities * @instance * @memberof PhysicsWorldControlSystem */ this.physicalEntities = null; /** * The matter-js engine we will use to process physics * * @property {external:MatterJs.Engine} engine * @instance * @memberof PhysicsWorldControlSystem */ this.engine = config.engine; if (!this.engine) { throw new Error(internals.kNoEngine); } } /** * Initializes system when added. Requests physics nodes and * attaches to event listeners to add / remove them to pixi stage * * @function added * @memberof PhysicsWorldControlSystem * @instance * @param {external:Serpentity.Engine} engine the serpentity engine to * which we are getting added */ added(engine) { this.physicalEntities = engine.getNodes(PhysicalNode); this.grabAreaEntities = engine.getNodes(GrabAreaNode); this.physicalEntities.on('nodeAdded', (event) => { World.add(this.engine.world, [event.node.body.body]); }); this.physicalEntities.on('nodeRemoved', (event) => { World.remove(this.engine.world, [event.node.body.body]); }); this.grabAreaEntities.on('nodeAdded', (event) => { World.add(this.engine.world, [event.node.grabArea.area]); }); this.grabAreaEntities.on('nodeRemoved', (event) => { World.remove(this.engine.world, [event.node.grabArea.area]); }); } /** * Clears system resources when removed. * * @function removed * @instance * @memberof PhysicsWorldControlSystem */ removed() { this.physicalEntities.removeAllListeners('nodeAdded'); this.physicalEntities.removeAllListeners('nodeRemoved'); this.physicalEntities = null; this.grabAreaEntities.removeAllListeners('nodeAdded'); this.grabAreaEntities.removeAllListeners('nodeRemoved'); this.grabAreaEntities = null; } /** * Runs on every update of the loop. Updates the physics * * @function update * @instance * @param {Number} currentFrameDuration the duration of the current * frame * @memberof PhysicsWorldControlSystem */ update(currentFrameDuration) { Engine.update(this.engine, currentFrameDuration); } }