]> git.r.bdr.sh - rbdr/sumo/commitdiff
Add Grab System (#9)
authorRubén Beltrán del Río <redacted>
Tue, 29 May 2018 02:35:38 +0000 (21:35 -0500)
committerGitHub <redacted>
Tue, 29 May 2018 02:35:38 +0000 (21:35 -0500)
* Remove unused code

* Adds grab components

* Adds grab nodes

* Add sensors to the physics world

* Add grab systems

* Add new sprites

* Attach grab components

* Add grab system to engine

* Update changelog

15 files changed:
CHANGELOG.md
lib/components/grab.js [new file with mode: 0644]
lib/components/grab_area.js [new file with mode: 0644]
lib/components/grabbable.js [new file with mode: 0644]
lib/factories/pixi.js
lib/factories/sumo.js
lib/nodes/drawn_grabber.js [new file with mode: 0644]
lib/nodes/grab_area.js [new file with mode: 0644]
lib/nodes/grabbable.js [new file with mode: 0644]
lib/nodes/grabber.js [new file with mode: 0644]
lib/sumo.js
lib/systems/draw_dash.js
lib/systems/draw_grab.js [new file with mode: 0644]
lib/systems/grab.js [new file with mode: 0644]
lib/systems/physics_world_control.js

index 83de4a76e060d62797da71ac1fade250d89cd58b..c038284acf76e8c6a9fae50a30e8eee0eefe493d 100644 (file)
@@ -18,5 +18,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 - Matter-js powered physics system
 - Scripts to setup hooks, linting, docs, and bundling
 - Keyboard Support
 - Matter-js powered physics system
 - Scripts to setup hooks, linting, docs, and bundling
 - Keyboard Support
+- Dash & grab mechanics
 
 [Unreleased]: https://github.com/rbdr/sumo/compare/master...develop
 
 [Unreleased]: https://github.com/rbdr/sumo/compare/master...develop
diff --git a/lib/components/grab.js b/lib/components/grab.js
new file mode 100644 (file)
index 0000000..ab808a8
--- /dev/null
@@ -0,0 +1,60 @@
+import { Component } from '@serpentity/serpentity';
+
+/**
+ * Component that stores a dash skill
+ *
+ * @extends {external:Serpentity.Component}
+ * @class GrabComponent
+ * @param {object} config a configuration object to extend.
+ */
+export default class GrabComponent extends Component {
+  constructor(config) {
+
+    super(config);
+
+    /**
+     * The properthy that holds the grab state
+     *
+     * @property {boolean} grabbing
+     * @instance
+     * @memberof GrabComponent
+     */
+    this.dashing = this.grabbing || false;
+
+    /**
+     * The constraint used for the grab
+     *
+     * @property {external:MatterJs.Constraint} constraint
+     * @instance
+     * @memberof GrabComponent
+     */
+    this.constraint = this.constraint || null;
+
+    /**
+     * Whether the grab is locked from occuring
+     *
+     * @property {boolean} locked
+     * @instance
+     * @memberof GrabComponent
+     */
+    this.locked = this.locked || false;
+
+    /**
+     * Cooldown before lock is removed
+     *
+     * @property {number} cooldown
+     * @instance
+     * @memberof GrabComponent
+     */
+    this.cooldown = this.cooldown || 3000;
+
+    /**
+     * Current cooldown
+     *
+     * @property {number} currentCooldown
+     * @instance
+     * @memberof GrabComponent
+     */
+    this.currentCooldown = 0;
+  }
+};
diff --git a/lib/components/grab_area.js b/lib/components/grab_area.js
new file mode 100644 (file)
index 0000000..3966c83
--- /dev/null
@@ -0,0 +1,34 @@
+import { Component } from '@serpentity/serpentity';
+
+/**
+ * Component that stores an area used to grab things
+ *
+ * @extends {external:Serpentity.Component}
+ * @class GrabAreaComponent
+ * @param {object} config a configuration object to extend.
+ */
+export default class GrabAreaComponent extends Component {
+  constructor(config) {
+
+    super(config);
+
+    /**
+     * The properthy that holds the angle. Assumes the area behaves as a sensor
+     *
+     * @property {external:MatterJs.Body} area
+     * @instance
+     * @memberof GrabAreaComponent
+     */
+    this.area = this.area || null;
+
+    /**
+     * The constraint that ties this area to its parent
+     *
+     * @property {external:MatterJs.Constraint} constraint
+     * @instance
+     * @memberof GrabAreaComponent
+     */
+    this.constraint = this.constraint || null;
+  }
+};
+
diff --git a/lib/components/grabbable.js b/lib/components/grabbable.js
new file mode 100644 (file)
index 0000000..223b95c
--- /dev/null
@@ -0,0 +1,11 @@
+import { Component } from '@serpentity/serpentity';
+
+/**
+ * Component that stores grab status
+ *
+ * @extends {external:Serpentity.Component}
+ * @class GrabbableComponent
+ * @param {object} config a configuration object to extend.
+ */
+export default class GrabbableComponent extends Component {};
+
index 786639f79e6ddcc77d6b3dc8f12d2ad199956490..f941ffeba0dbec556874319db5c48b8f67e6a82f 100644 (file)
@@ -68,6 +68,9 @@ export default {
 
     body.addChild(this.createBlush({ radius }));
 
 
     body.addChild(this.createBlush({ radius }));
 
+    body.addChild(this.createEffortMark({ radius }));
+    body.addChild(this.createShadow({ radius }));
+
     // The group
     body.addChild(smile);
     body.addChild(frown);
     // The group
     body.addChild(smile);
     body.addChild(frown);
@@ -203,5 +206,108 @@ export default {
     blush.addChild(rightBlush);
 
     return blush;
     blush.addChild(rightBlush);
 
     return blush;
+  },
+
+  /**
+   * Creates an effort mark
+   *
+   * @function createEffortMark
+   * @memberof PixiFactory
+   * @return {external:CreateJs.Container} the created container
+   */
+  createEffortMark(config) {
+
+    const radius = config.radius;
+
+    const effortMark = new Graphics();
+
+    const centerX = -3 * radius / 4;
+    const centerY = -3 * radius / 4;
+
+    effortMark.name = 'effort';
+    effortMark.visible = false;
+
+    const color = 0xff00ff;
+    const lineWidth = 2;
+
+    const topRightArch = new Graphics();
+    topRightArch.lineStyle(lineWidth, color, 1)
+      .arc(
+        centerX + 2 * radius / 7, centerY - 2 * radius / 7,
+        radius / 5,
+        Math.PI / 2,
+        Math.PI
+      );
+
+    const topLeftArch = new Graphics();
+    topLeftArch.lineStyle(lineWidth, color, 1)
+      .arc(
+        centerX - 2 * radius / 7, centerY - radius / 4,
+        radius / 5,
+        0,
+        Math.PI / 2
+      );
+
+    const bottomRightArch = new Graphics();
+    bottomRightArch.lineStyle(lineWidth, color, 1)
+      .arc(
+        centerX + 2 * radius / 7, centerY + radius / 4,
+        radius / 5,
+        Math.PI,
+        3 * Math.PI / 2
+      );
+
+    const bottomLeftArch = new Graphics();
+    bottomLeftArch.lineStyle(lineWidth, color, 1)
+      .arc(
+        centerX - 2 * radius / 7, centerY + 2 * radius / 7,
+        radius / 5,
+        3 * Math.PI / 2,
+        0
+      );
+
+    effortMark.addChild(topRightArch);
+    effortMark.addChild(topLeftArch);
+    effortMark.addChild(bottomRightArch);
+    effortMark.addChild(bottomLeftArch);
+
+    return effortMark;
+  },
+
+  /**
+   * Creates a shadow for the eye
+   *
+   * @function createShadow
+   * @memberof PixiFactory
+   * @return {external:CreateJs.Container} the created container
+   */
+  createShadow(config) {
+
+    const radius = config.radius;
+
+    const shadow = new Graphics();
+
+    const centerX = radius / 2;
+    const centerY = -3 * radius / 4;
+
+    shadow.name = 'shadow';
+    shadow.visible = false;
+
+    const color = 0x9900ff;
+    const lineWidth = 2;
+
+    shadow.lineStyle(lineWidth, color, 1)
+      .moveTo(centerX - radius / 4, centerY - radius / 3)
+      .lineTo(centerX - radius / 4, centerY + radius / 5)
+      .moveTo(centerX - radius / 8, centerY - radius / 4)
+      .lineTo(centerX - radius / 8, centerY + radius / 5)
+      .moveTo(centerX, centerY - radius / 5)
+      .lineTo(centerX, centerY + radius / 5)
+      .moveTo(centerX + radius / 8, centerY - radius / 6)
+      .lineTo(centerX + radius / 8, centerY + radius / 6)
+      .moveTo(centerX + radius / 4, centerY - radius / 5)
+      .lineTo(centerX + radius / 4, centerY + radius / 5);
+
+    return shadow;
   }
 };
   }
 };
index e8417f9532667416b556077ca8bb9164a906997c..7b50f8ae50493ce087d8d8f570e23a12c08f7a9a 100644 (file)
@@ -10,6 +10,9 @@ import CoupledEntitiesComponent from '../components/coupled_entities';
 import DashComponent from '../components/dash';
 import ElasticComponent from '../components/elastic';
 import ForceComponent from '../components/force';
 import DashComponent from '../components/dash';
 import ElasticComponent from '../components/elastic';
 import ForceComponent from '../components/force';
+import GrabAreaComponent from '../components/grab_area';
+import GrabbableComponent from '../components/grabbable';
+import GrabComponent from '../components/grab';
 import MaxVelocityComponent from '../components/max_velocity';
 import PositionComponent from '@serpentity/components.position';
 import PixiContainerComponent from '../components/pixi_container';
 import MaxVelocityComponent from '../components/max_velocity';
 import PositionComponent from '@serpentity/components.position';
 import PixiContainerComponent from '../components/pixi_container';
@@ -96,6 +99,18 @@ export default {
     });
     entity.addComponent(new BodyComponent({ body }));
 
     });
     entity.addComponent(new BodyComponent({ body }));
 
+    // GRAB
+
+    const areaSizeFactor = 2; // Multiplier vs the radius
+    const area = Bodies.circle(position.x / Config.meterSize, position.y / Config.meterSize, (radius * areaSizeFactor) / Config.meterSize, {
+      label: 'Sumo Grab Area',
+      isSensor: true
+    });
+
+    entity.addComponent(new GrabAreaComponent({ area }));
+    entity.addComponent(new GrabComponent({ body }));
+    entity.addComponent(new GrabbableComponent({ body }));
+
     if (engine) {
       engine.addEntity(entity);
     }
     if (engine) {
       engine.addEntity(entity);
     }
@@ -235,6 +250,16 @@ export default {
             component: DashComponent,
             property: 'dashing'
           }
             component: DashComponent,
             property: 'dashing'
           }
+        },
+        {
+          source: {
+            type: 'keyboard',
+            index: 88 // X
+          },
+          target: {
+            component: GrabComponent,
+            property: 'grabbing'
+          }
         }
       ]
     }));
         }
       ]
     }));
diff --git a/lib/nodes/drawn_grabber.js b/lib/nodes/drawn_grabber.js
new file mode 100644 (file)
index 0000000..49af6d4
--- /dev/null
@@ -0,0 +1,27 @@
+import { Node } from '@serpentity/serpentity';
+
+import GrabComponent from '../components/grab';
+import PixiContainerComponent from '../components/pixi_container';
+
+/**
+ * Node identifying an entity that can grab and is drawn
+ *
+ * @extends {external:Serpentity.Node}
+ * @class DrawnGrabberNode
+ */
+export default class DrawnGrabberNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify a drawn grabber entity
+ *
+ * @property {object} types
+ * @name types
+ * @memberof DrawnGrabberNode
+ */
+DrawnGrabberNode.types = {
+  container: PixiContainerComponent,
+  grab: GrabComponent
+};
+
diff --git a/lib/nodes/grab_area.js b/lib/nodes/grab_area.js
new file mode 100644 (file)
index 0000000..9f6c3e0
--- /dev/null
@@ -0,0 +1,25 @@
+import { Node } from '@serpentity/serpentity';
+
+import GrabAreaComponent from '../components/grab_area';
+
+/**
+ * Node identifying an entity that have a physical grab area
+ *
+ * @extends {external:Serpentity.Node}
+ * @class GrabAreaNode
+ */
+export default class GrabAreaNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify an entity with a grab
+ * area
+ *
+ * @property {object} types
+ * @name types
+ * @memberof GrabAreaNode
+ */
+GrabAreaNode.types = {
+  grabArea: GrabAreaComponent
+};
diff --git a/lib/nodes/grabbable.js b/lib/nodes/grabbable.js
new file mode 100644 (file)
index 0000000..4711764
--- /dev/null
@@ -0,0 +1,27 @@
+import { Node } from '@serpentity/serpentity';
+
+import BodyComponent from '../components/body';
+import GrabbableComponent from '../components/grabbable';
+
+/**
+ * Node identifying an entity that can grab another
+ *
+ * @extends {external:Serpentity.Node}
+ * @class GrabbableNode
+ */
+export default class GrabbableNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify a grabbable entity
+ *
+ * @property {object} types
+ * @name types
+ * @memberof GrabbableNode
+ */
+GrabbableNode.types = {
+  body: BodyComponent,
+  grabbable: GrabbableComponent
+};
+
diff --git a/lib/nodes/grabber.js b/lib/nodes/grabber.js
new file mode 100644 (file)
index 0000000..db61365
--- /dev/null
@@ -0,0 +1,29 @@
+import { Node } from '@serpentity/serpentity';
+
+import BodyComponent from '../components/body';
+import GrabAreaComponent from '../components/grab_area';
+import GrabComponent from '../components/grab';
+
+/**
+ * Node identifying an entity that can grab another
+ *
+ * @extends {external:Serpentity.Node}
+ * @class GrabberNode
+ */
+export default class GrabberNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify a grabber entity
+ *
+ * @property {object} types
+ * @name types
+ * @memberof GrabberNode
+ */
+GrabberNode.types = {
+  body: BodyComponent,
+  grabArea: GrabAreaComponent,
+  grab: GrabComponent
+};
+
index 47850871092b3bc5b1d777001ff40098dcba8f49..d39c055eaece84e07eed6ee579437ca0375bdcbf 100644 (file)
@@ -9,7 +9,9 @@ import CreateCouplingLineSystem from './systems/create_coupling_line';
 import ControlMapperSystem from './systems/control_mapper';
 import DashSystem from './systems/dash';
 import DrawDashSystem from './systems/draw_dash';
 import ControlMapperSystem from './systems/control_mapper';
 import DashSystem from './systems/dash';
 import DrawDashSystem from './systems/draw_dash';
+import DrawGrabSystem from './systems/draw_grab';
 import ElasticSystem from './systems/elastic';
 import ElasticSystem from './systems/elastic';
+import GrabSystem from './systems/grab';
 import PhysicsWorldControlSystem from './systems/physics_world_control';
 import PhysicsToAttributesSystem from './systems/physics_to_attributes';
 import RenderSystem from './systems/render';
 import PhysicsWorldControlSystem from './systems/physics_world_control';
 import PhysicsToAttributesSystem from './systems/physics_to_attributes';
 import RenderSystem from './systems/render';
@@ -197,6 +199,10 @@ internals.Sumo = class Sumo {
 
     this._engine.addSystem(new DashSystem());
 
 
     this._engine.addSystem(new DashSystem());
 
+    this._engine.addSystem(new GrabSystem({
+      engine: this._matterJs
+    }));
+
     this._engine.addSystem(new ApplyForceSystem());
 
     this._engine.addSystem(new PhysicsWorldControlSystem({
     this._engine.addSystem(new ApplyForceSystem());
 
     this._engine.addSystem(new PhysicsWorldControlSystem({
@@ -213,6 +219,8 @@ internals.Sumo = class Sumo {
 
     this._engine.addSystem(new DrawDashSystem());
 
 
     this._engine.addSystem(new DrawDashSystem());
 
+    this._engine.addSystem(new DrawGrabSystem());
+
     this._engine.addSystem(new RenderSystem({
       application: this._pixi
     }));
     this._engine.addSystem(new RenderSystem({
       application: this._pixi
     }));
index 118ce1cc1fdf2fb271989021eb6802163bdc0fce..5ce9043cf9cf1c0bdd170f0dd0034474ac933eb9 100644 (file)
@@ -2,10 +2,6 @@ import { System } from '@serpentity/serpentity';
 
 import DrawnDasherNode from '../nodes/drawn_dasher';
 
 
 import DrawnDasherNode from '../nodes/drawn_dasher';
 
-const internals = {
-  kBlushRadius: 25
-};
-
 /**
  * Shows a different graphic during the duration of lock
  *
 /**
  * Shows a different graphic during the duration of lock
  *
diff --git a/lib/systems/draw_grab.js b/lib/systems/draw_grab.js
new file mode 100644 (file)
index 0000000..21ffdcd
--- /dev/null
@@ -0,0 +1,115 @@
+import { System } from '@serpentity/serpentity';
+
+import DrawnGrabberNode from '../nodes/drawn_grabber';
+
+/**
+ * Shows a different graphic during the duration of lock
+ *
+ * @extends {external:Serpentity.System}
+ * @class DrawGrabSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class DrawGrabSystem extends System {
+
+  constructor(config = {}) {
+
+    super();
+
+    /**
+     * The node collection of grabbers
+     *
+     * @property {external:Serpentity.NodeCollection} drawnGrabbers
+     * @instance
+     * @memberof DrawGrabSystem
+     */
+    this.drawnGrabbers = null;
+  }
+
+  /**
+   * Initializes system when added. Requests drawn grabber nodes
+   *
+   * @function added
+   * @memberof DrawGrabSystem
+   * @instance
+   * @param {external:Serpentity.Engine} engine the serpentity engine to
+   * which we are getting added
+   */
+  added(engine) {
+
+    this.drawnGrabbers = engine.getNodes(DrawnGrabberNode);
+  }
+
+  /**
+   * Clears system resources when removed.
+   *
+   * @function removed
+   * @instance
+   * @memberof DrawGrabSystem
+   */
+  removed() {
+
+    this.drawnGrabbers = null;
+  }
+
+  /**
+   * Runs on every update of the loop. Updates image depending on if
+   * grab is locked and active
+   *
+   * @function update
+   * @instance
+   * @param {Number} currentFrameDuration the duration of the current
+   * frame
+   * @memberof DrawGrabSystem
+   */
+  update(currentFrameDuration) {
+
+    for (const drawnGrabber of this.drawnGrabbers) {
+
+      const grab = drawnGrabber.grab;
+      const container = drawnGrabber.container.container;
+
+      if (grab.locked && grab.constraint) {
+        this._drawGrabFace(container);
+        continue;
+      }
+
+      if (grab.locked) {
+        this._drawGrabCooldownFace(container);
+        continue;
+      }
+
+      this._removeGrabFace(container);
+    }
+  }
+
+  // Draws the grab face
+
+  _drawGrabFace(container) {
+
+    const effort = container.getChildByName('effort');
+    const shadow = container.getChildByName('shadow');
+    effort.visible = true;
+    shadow.visible = false;
+  }
+
+  // Draws the grab cooldown face
+
+  _drawGrabCooldownFace(container) {
+
+    const effort = container.getChildByName('effort');
+    const shadow = container.getChildByName('shadow');
+    effort.visible = false;
+    shadow.visible = true;
+  }
+
+  // Removes the dash face
+
+  _removeGrabFace(container) {
+
+    const effort = container.getChildByName('effort');
+    const shadow = container.getChildByName('shadow');
+    effort.visible = false;
+    shadow.visible = false;
+  }
+};
+
diff --git a/lib/systems/grab.js b/lib/systems/grab.js
new file mode 100644 (file)
index 0000000..43e6246
--- /dev/null
@@ -0,0 +1,183 @@
+import { System } from '@serpentity/serpentity';
+import { Body, Constraint, SAT, World } from 'matter-js';
+
+import GrabberNode from '../nodes/grabber';
+import GrabbableNode from '../nodes/grabbable';
+
+import Config from '../config';
+
+const internals = {
+  kGrabRadius: 50,
+  kNoEngine: 'No matter js physics engine found. Make sure you set the `engine` key in the config object when initializing.'
+};
+
+/**
+ * Handles grabbing between entities
+ *
+ * @extends {external:Serpentity.System}
+ * @class GrabSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class GrabSystem extends System {
+
+  constructor(config = {}) {
+
+    super();
+
+    /**
+     * The node collection of grabbers
+     *
+     * @property {external:Serpentity.NodeCollection} grabbers
+     * @instance
+     * @memberof GrabSystem
+     */
+    this.grabbers = null;
+
+    /**
+     * The node collection of grabbables
+     *
+     * @property {external:Serpentity.NodeCollection} grabbables
+     * @instance
+     * @memberof GrabSystem
+     */
+    this.grabbables = null;
+
+    /**
+     * The matter-js engine we will use to add and remove constraints
+     *
+     * @property {external:MatterJs.Engine} engine
+     * @instance
+     * @memberof GrabSystem
+     */
+    this.engine = config.engine;
+
+    if (!this.engine) {
+      throw new Error(internals.kNoEngine);
+    }
+  }
+
+  /**
+   * Initializes system when added. Requests grabber and grabbable nodes
+   *
+   * @function added
+   * @memberof GrabSystem
+   * @instance
+   * @param {external:Serpentity.Engine} engine the serpentity engine to
+   * which we are getting added
+   */
+  added(engine) {
+
+    this.grabbers = engine.getNodes(GrabberNode);
+    this.grabbables = engine.getNodes(GrabbableNode);
+  }
+
+  /**
+   * Clears system resources when removed.
+   *
+   * @function removed
+   * @instance
+   * @memberof GrabSystem
+   */
+  removed() {
+
+    this.grabbers = null;
+    this.grabbables = null;
+  }
+
+  /**
+   * Runs on every update of the loop. Triggers grab and manages cooldown
+   *
+   * @function update
+   * @instance
+   * @param {Number} currentFrameDuration the duration of the current
+   * frame
+   * @memberof GrabSystem
+   */
+  update(currentFrameDuration) {
+
+    for (const grabber of this.grabbers) {
+
+      const grab = grabber.grab;
+
+      if (grab.grabbing && !grab.locked) {
+        this._grab(grabber);
+      }
+
+      const isGrabReleased = !grab.grabbing || grab.currentCooldown >= grab.cooldown;
+      if (grab.constraint && isGrabReleased) {
+        this._release(grabber);
+      }
+
+      if (!grab.grabbing && grab.locked && grab.currentCooldown >= grab.cooldown) {
+        this._unlock(grabber);
+      }
+
+      if (grab.locked) {
+        grab.currentCooldown += currentFrameDuration;
+      }
+
+      grab.grabbing = 0;
+    }
+  }
+
+  // Executes the dash action
+
+  _grab(grabber) {
+
+    const grab = grabber.grab;
+
+    grab.locked = true;
+    grab.currentCooldown = 0;
+
+    Body.setPosition(grabber.grabArea.area, grabber.body.body.position);
+
+    console.log('Grab!');
+
+    for (const grabbable of this.grabbables) {
+
+      if (grabbable.entity === grabber.entity) {
+        continue;
+      }
+
+      const collision = SAT.collides(grabber.grabArea.area, grabbable.body.body);
+      if (collision.collided) {
+        grab.constraint = this._createConstraint(grabber.body.body, grabbable.body.body);
+        console.log('Grabbing', grab.constraint);
+      }
+    }
+  }
+
+  // Executes the unlock action
+
+  _unlock(grabber) {
+
+    grabber.grab.locked = false;
+  }
+
+  // Releases a constraint
+
+  _release(grabber) {
+
+    console.log('Releasing', grabber.grab.constraint);
+    World.remove(this.engine.world, grabber.grab.constraint);
+    grabber.grab.currentCooldown = 0;
+    grabber.grab.constraint = null;
+  }
+
+  // Performs a grab between two entities
+
+  _createConstraint(grabber, grabbable) {
+
+    const constraint = Constraint.create({ // Attach the sensor to the body
+      bodyA: grabber,
+      bodyB: grabbable,
+      damping: 0,
+      length: internals.kGrabRadius / Config.meterSize,
+      stiffness: 1
+    });
+
+    World.add(this.engine.world, [constraint]);
+
+    return constraint;
+  }
+};
index a658d5cc8cca89e013b4347d485f5507e1bb8e40..370701eca7d92a077af8fb919d973e6a61f5cc71 100644 (file)
@@ -2,6 +2,7 @@ import { System } from '@serpentity/serpentity';
 import { Engine, World } from 'matter-js';
 
 import PhysicalNode from '../nodes/physical';
 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.'
 
 const internals = {
   kNoEngine: 'No matter js physics engine found. Make sure you set the `engine` key in the config object when initializing.'
@@ -56,6 +57,8 @@ export default class PhysicsWorldControlSystem extends System {
   added(engine) {
 
     this.physicalEntities = engine.getNodes(PhysicalNode);
   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('nodeAdded', (event) => {
 
       World.add(this.engine.world, [event.node.body.body]);
@@ -64,6 +67,15 @@ export default class PhysicsWorldControlSystem extends System {
 
       World.remove(this.engine.world, [event.node.body.body]);
     });
 
       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]);
+    });
   }
 
   /**
   }
 
   /**
@@ -78,6 +90,10 @@ export default class PhysicsWorldControlSystem extends System {
     this.physicalEntities.removeAllListeners('nodeAdded');
     this.physicalEntities.removeAllListeners('nodeRemoved');
     this.physicalEntities = null;
     this.physicalEntities.removeAllListeners('nodeAdded');
     this.physicalEntities.removeAllListeners('nodeRemoved');
     this.physicalEntities = null;
+
+    this.grabAreaEntities.removeAllListeners('nodeAdded');
+    this.grabAreaEntities.removeAllListeners('nodeRemoved');
+    this.grabAreaEntities = null;
   }
 
   /**
   }
 
   /**
@@ -95,4 +111,3 @@ export default class PhysicsWorldControlSystem extends System {
   }
 };
 
   }
 };
 
-