]> git.r.bdr.sh - rbdr/sumo/blobdiff - lib/factories/sumo.js
Physics Engine (#4)
[rbdr/sumo] / lib / factories / sumo.js
index b0e5416bf545f652fb82dcc9c95d4e05ce7f6fdf..d1f31f0628bf04ddcbbbb1b3ad9322e74737a982 100644 (file)
@@ -1,9 +1,18 @@
+import { Bodies, Constraint } from 'matter-js';
 import { Entity } from '@serpentity/serpentity';
 
+import AngleComponent from '../components/angle';
+import BodyComponent from '../components/body';
+import CoupledEntitiesComponent from '../components/coupled_entities';
 import PositionComponent from '@serpentity/components.position';
 import PixiContainerComponent from '../components/pixi_container';
 import PixiFactory from '../factories/pixi';
 
+const internals = {
+  kNoEntityError: 'Entity Not Found: This method requires entityA and entityB to be set in the config.',
+  kEntityHasNoBodyError: 'Entity Has No Body: This method requires entities have a BodyComponent.'
+};
+
 /**
  * Factory object that contains many methods to create prefab entities.
  *
@@ -28,20 +37,103 @@ export default {
 
     const entity = new Entity();
 
+    // POSITION
+
     entity.addComponent(new PositionComponent(config.position));
+    const position = entity.getComponent(PositionComponent);
+
+    entity.addComponent(new AngleComponent(config.angle));
+    const angle = entity.getComponent(AngleComponent);
+
+    // RENDERING
+
+    const radius = 25;
 
     const container = config.container || {
-      container: PixiFactory.createSumo()
+      container: PixiFactory.createSumo({ radius })
     };
-
-    // Match the symbol position with the entity position on init
-    // Otherwise it's up to systems
-    const position = entity.getComponent(PositionComponent);
     container.container.position.x = position.x;
     container.container.position.y = position.y;
+    container.container.rotation = angle.angle;
+    entity.addComponent(new PixiContainerComponent(container));
+
+    // PHYSICS
+
+    const frictionAir = 0.00001;
+    const friction = 0.00001;
+    const restitution = 0.9;
+    const density = 0.5;
+
+    const body = Bodies.circle(position.x, position.y, radius, {
+      angle: angle.angle,
+      density,
+      frictionAir,
+      friction,
+      restitution
+    });
+    entity.addComponent(new BodyComponent({ body }));
+
+    if (engine) {
+      engine.addEntity(entity);
+    }
+
+    return entity;
+  },
+
+  /**
+   * Creates a rubber band entity and adds it to the engine.
+   *
+   * @function createRubberBand
+   * @memberof SumoFactory
+   * @param {external:Serpentity} [engine] the serpentity engine to attach
+   * to. If not sent, it will not be attached.
+   * @param {object} [config] the config to override the entity, it
+   * must include entityA and entityB which will be tied by it. If they
+   * are not sent or don't have a physics body, this will throw.
+   * @return {external:Serpentity.Entity} the created entity
+   */
+  createRubberBand(engine, config = {}) {
+
+    const entity = new Entity();
+
+    if (!config.entityA || !config.entityB) {
+      throw new Error(internals.kNoEntityError);
+    }
+
+    if (!config.entityA.hasComponent(BodyComponent) || !config.entityB.hasComponent(BodyComponent)) {
+      throw new Error(internals.kEntityHasNoBodyError);
+    }
 
+    // RENDERING
+
+    const container = config.container || {
+      container: PixiFactory.createEmptyGraphic()
+    };
     entity.addComponent(new PixiContainerComponent(container));
 
+    // PHYSICS
+
+    const bodyA = config.entityA.getComponent(BodyComponent).body;
+    const bodyB = config.entityB.getComponent(BodyComponent).body;
+    const damping = 0.01;
+    const length = 100;
+    const stiffness = 0.0001;
+    const angularStiffness = 0.0001;
+
+    const body = Constraint.create({
+      bodyA,
+      bodyB,
+      damping,
+      length,
+      stiffness,
+      angularStiffness
+    });
+    entity.addComponent(new BodyComponent({ body }));
+
+    entity.addComponent(new CoupledEntitiesComponent({
+      coupledEntities: [config.entityA, config.entityB]
+    }));
+
     if (engine) {
       engine.addEntity(entity);
     }