]> git.r.bdr.sh - rbdr/sumo/commitdiff
Draw the Arena (#7)
authorRubén Beltrán del Río <redacted>
Mon, 23 Apr 2018 12:58:20 +0000 (07:58 -0500)
committerGitHub <redacted>
Mon, 23 Apr 2018 12:58:20 +0000 (07:58 -0500)
* Add defaults to config

* Create arena sprite

* Draw the arena

* Draw a face when cooling down the dash

* Correct linter issues

lib/components/dash.js
lib/config.js
lib/factories/pixi.js
lib/factories/sumo.js
lib/nodes/drawn_dasher.js [new file with mode: 0644]
lib/sumo.js
lib/systems/dash.js
lib/systems/draw_dash.js [new file with mode: 0644]
lib/systems/render.js

index de1fe2c58b2d9a244d1f3549d16d9905d11ace64..77807efd1b87c989048fdc074ec67f4b0f51e27e 100644 (file)
@@ -37,7 +37,7 @@ export default class DashComponent extends Component {
      * @instance
      * @memberof DashComponent
      */
-    this.cooldown = this.cooldown || 4000;
+    this.cooldown = this.cooldown || 3000;
 
     /**
      * Current cooldown
index ba02ed82ee38d513f6018e20835e510efefddbdf..856fc1879193d592eb6c2ce710bf6c60ae67c867 100644 (file)
@@ -4,7 +4,7 @@
  * @name Config
  * @type object
  */
-export default {
+const config = {
 
   /**
    * How many pixels to use per meter
@@ -12,5 +12,32 @@ export default {
    * @property {number} meterSize
    * @memberof Config
    */
-  meterSize: 25
+  meterSize: 25,
+
+  /**
+   * Aspect Ratio the aspect ratio expressed as an array of two numbers
+   *
+   * @property {number} aspectRatio
+   * @memberof Config
+   */
+  aspectRatio: [2.76, 1],
+
+  /**
+   * Target vertical resolution
+   *
+   * @property {number} verticalResolution
+   * @memberof Config
+   */
+  verticalResolution: 224
+
 };
+
+/**
+ * How many pixels to use per meter
+ *
+ * @property {number} meterSize
+ * @memberof Config
+ */
+config.horizontalResolution = Math.round(config.verticalResolution * config.aspectRatio[0] / config.aspectRatio[1]);
+
+export default config;
index 839e59315620949541cf3b2f502469349d4bbd44..786639f79e6ddcc77d6b3dc8f12d2ad199956490 100644 (file)
@@ -27,8 +27,9 @@ export default {
       .endFill();
 
     // The mouth
-    const mouth = new Graphics();
-    mouth.lineStyle(10, 0xff0080, 1)
+    const smile = new Graphics();
+    smile.name = 'smile';
+    smile.lineStyle(10, 0xff0080, 1)
       .arc(
         0, 0, // center
         radius * 0.6,
@@ -36,6 +37,18 @@ export default {
         5 * Math.PI / 6
       );
 
+    const frown = new Graphics();
+    frown.name = 'frown';
+    frown.visible = false;
+    frown.lineStyle(10, 0xff0080, 1)
+      .arc(
+        0, radius,
+        radius * 0.6,
+        -Math.PI / 5,
+        -4 * Math.PI / 5,
+        true
+      );
+
     const leftEye = new Graphics();
     leftEye.beginFill(0xffffff)
       .drawCircle(-radius / 3 - radius / 8, -radius / 4, radius / 5)
@@ -53,8 +66,11 @@ export default {
     leftPupil.beginFill(0x11)
       .drawCircle(radius / 3 + radius / 8, -radius / 4, radius / 10);
 
+    body.addChild(this.createBlush({ radius }));
+
     // The group
-    body.addChild(mouth);
+    body.addChild(smile);
+    body.addChild(frown);
     body.addChild(leftEye);
     body.addChild(rightEye);
     body.addChild(leftPupil);
@@ -101,6 +117,91 @@ export default {
     body.addChild(center);
 
     return body;
+  },
+
+  /**
+   * Creates an arena graphic
+   *
+   * @function createArena
+   * @memberof PixiFactory
+   * @return {external:CreateJs.Container} the created container
+   */
+  createArena(config) {
+
+    const radius = config.radius;
+
+    const lineThickness = 20;
+
+    // The body
+    const arena = new Graphics();
+    arena.lineStyle(lineThickness, 0xdfd4b2, 1)
+      .drawCircle(0, 0, radius);
+
+    const leftLine = new Graphics();
+    leftLine.lineStyle(20, 0xbdb08b, 1)
+      .moveTo(-radius / 4, -radius / 8)
+      .lineTo(-radius / 4, radius / 8);
+
+    const rightLine = new Graphics();
+    rightLine.lineStyle(20, 0xbdb08b, 1)
+      .moveTo(radius / 4, -radius / 8)
+      .lineTo(radius / 4, radius / 8);
+
+    arena.addChild(leftLine);
+    arena.addChild(rightLine);
+
+    return arena;
+  },
+
+  /**
+   * Creates a blush for the face
+   *
+   * @function createBlush
+   * @memberof PixiFactory
+   * @return {external:CreateJs.Container} the created container
+   */
+  createBlush(config) {
+
+    const radius = config.radius;
+
+    const blush = new Graphics();
+
+    blush.name = 'blush';
+    blush.visible = false;
+
+    const leftEyebrow = new Graphics();
+    leftEyebrow.lineStyle(4, 0x11, 1)
+      .arc(
+        -radius / 3 - radius / 4, -radius / 2 - radius / 4,
+        radius / 3,
+        Math.PI / 8,
+        2 * Math.PI / 3
+      );
+
+    const leftBlush = new Graphics();
+    leftBlush.lineStyle(4, 0xe7bfe6, 1)
+      .moveTo(-radius / 3 - radius / 4, radius / 10)
+      .lineTo(-radius / 3, 0);
+
+    const rightEyebrow = new Graphics();
+    rightEyebrow.lineStyle(4, 0x11, 1)
+      .arc(
+        radius / 3 + radius / 4, -radius / 2 - radius / 4,
+        radius / 3,
+        Math.PI / 3,
+        7 * Math.PI / 8
+      );
+
+    const rightBlush = new Graphics();
+    rightBlush.lineStyle(4, 0xe7bfe6, 1)
+      .moveTo(radius / 3 + radius / 4, radius / 10)
+      .lineTo(radius / 3, 0);
+
+    blush.addChild(leftEyebrow);
+    blush.addChild(leftBlush);
+    blush.addChild(rightEyebrow);
+    blush.addChild(rightBlush);
+
+    return blush;
   }
 };
-
index ea5a71c753ace339f301377cd2cc2526b0b1d3f3..dad99870ed9634d5deae699e01484068cf51d614 100644 (file)
@@ -82,8 +82,8 @@ export default {
     const frictionAir = 0.02;
     const friction = 1;
     const frictionStatic = 1;
-    const restitution = 0.9;
-    const density = 1;
+    const restitution = 1;
+    const density = 1.5;
 
     const body = Bodies.circle(position.x / Config.meterSize, position.y / Config.meterSize, radius / Config.meterSize, {
       label: 'Sumo body',
@@ -296,6 +296,44 @@ export default {
       engine.addEntity(entity);
     }
 
+    return entity;
+  },
+
+  /**
+   * Creates a static arena entity
+   *
+   * @function createArena
+   * @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, accepts
+   * the key `position` as an object with an x and y property.
+   * @return {external:Serpentity.Entity} the created entity
+   */
+  createArena(engine, config = {}) {
+
+    const entity = new Entity();
+
+    // POSITION
+
+    entity.addComponent(new PositionComponent(config.position));
+    const position = entity.getComponent(PositionComponent);
+
+    // RENDERING
+
+    const radius = 300;
+
+    const container = config.container || {
+      container: PixiFactory.createArena({ radius })
+    };
+    container.container.position.x = position.x;
+    container.container.position.y = position.y;
+    entity.addComponent(new PixiContainerComponent(container));
+
+    if (engine) {
+      engine.addEntity(entity);
+    }
+
     return entity;
   }
 };
diff --git a/lib/nodes/drawn_dasher.js b/lib/nodes/drawn_dasher.js
new file mode 100644 (file)
index 0000000..162593f
--- /dev/null
@@ -0,0 +1,27 @@
+import { Node } from '@serpentity/serpentity';
+
+import DashComponent from '../components/dash';
+import PixiContainerComponent from '../components/pixi_container';
+
+/**
+ * Node identifying an entity that can dash and is drawn
+ *
+ * @extends {external:Serpentity.Node}
+ * @class DrawnDasherNode
+ */
+export default class DrawnDasherNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify a drawn dasher entity
+ *
+ * @property {object} types
+ * @name types
+ * @memberof DrawnDasherNode
+ */
+DrawnDasherNode.types = {
+  container: PixiContainerComponent,
+  dash: DashComponent
+};
+
index 2b6f085bce02b488a70a4236a1cb4d1825656ea9..eef80d759ef547ab807163a7a3b7fa50c403411c 100644 (file)
@@ -1,10 +1,14 @@
 import 'babel-polyfill';
 
+import Config from './config';
+
 // Systems
+
 import ApplyForceSystem from './systems/apply_force';
 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 ElasticSystem from './systems/elastic';
 import PhysicsWorldControlSystem from './systems/physics_world_control';
 import PhysicsToAttributesSystem from './systems/physics_to_attributes';
@@ -31,13 +35,13 @@ const internals = {
 
   onLoad() {
 
-    const sumo = new internals.Sumo({
+    const sumo = new internals.Sumo(Object.assign({
       element: document.getElementById('sumo-app-entry-point')
-    });
+    }, Config));
 
     sumo.startLoop();
 
-    internals.exports.sumo = sumo;
+    window.sumo = sumo;
   }
 };
 
@@ -61,6 +65,7 @@ internals.Sumo = class Sumo {
 
   constructor(config) {
 
+    // These defaults can get overridden by config
     this.fps = 60;
     this.aspectRatio = [2.76, 1];
     this.verticalResolution = 224;
@@ -206,6 +211,8 @@ internals.Sumo = class Sumo {
 
     this._engine.addSystem(new CreateCouplingLineSystem());
 
+    this._engine.addSystem(new DrawDashSystem());
+
     this._engine.addSystem(new RenderSystem({
       application: this._pixi
     }));
@@ -215,24 +222,31 @@ internals.Sumo = class Sumo {
 
   _initializeEntities() {
 
+    SumoFactory.createArena(this._engine, {
+      position: {
+        x: this.horizontalResolution / 2,
+        y: this.verticalResolution / 2
+      }
+    });
+
     const sumoA = SumoFactory.createSumo(null, {
       position: {
-        x: 50,
-        y: 50
+        x: this.horizontalResolution / 2 - 100,
+        y: this.verticalResolution / 2
       }
     });
 
     const sumoB = SumoFactory.createControllableSumo(null, {
       position: {
-        x: 500,
-        y: 78
+        x: this.horizontalResolution / 2 + 100,
+        y: this.verticalResolution / 2
       }
     });
 
     const harness = SumoFactory.createHarness(null, {
       position: {
-        x: 309,
-        y: 112
+        x: this.horizontalResolution / 2,
+        y: this.verticalResolution / 2
       }
     });
 
index d05e9ea7b68533385c96722faf459789a1737711..f648d36ea03bb0977492c9c74b4e88951cb77ee6 100644 (file)
@@ -1,7 +1,7 @@
 import { System } from '@serpentity/serpentity';
 
 const internals = {
-  kForce: 10
+  kForce: 20
 };
 
 import DasherNode from '../nodes/dasher';
diff --git a/lib/systems/draw_dash.js b/lib/systems/draw_dash.js
new file mode 100644 (file)
index 0000000..118ce1c
--- /dev/null
@@ -0,0 +1,107 @@
+import { System } from '@serpentity/serpentity';
+
+import DrawnDasherNode from '../nodes/drawn_dasher';
+
+const internals = {
+  kBlushRadius: 25
+};
+
+/**
+ * Shows a different graphic during the duration of lock
+ *
+ * @extends {external:Serpentity.System}
+ * @class DrawDashSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class DrawDashSystem extends System {
+
+  constructor(config = {}) {
+
+    super();
+
+    /**
+     * The node collection of dashers
+     *
+     * @property {external:Serpentity.NodeCollection} drawnDashers
+     * @instance
+     * @memberof DrawDashSystem
+     */
+    this.drawnDashers = null;
+  }
+
+  /**
+   * Initializes system when added. Requests drawn dasher nodes
+   *
+   * @function added
+   * @memberof DrawDashSystem
+   * @instance
+   * @param {external:Serpentity.Engine} engine the serpentity engine to
+   * which we are getting added
+   */
+  added(engine) {
+
+    this.drawnDashers = engine.getNodes(DrawnDasherNode);
+  }
+
+  /**
+   * Clears system resources when removed.
+   *
+   * @function removed
+   * @instance
+   * @memberof DrawDashSystem
+   */
+  removed() {
+
+    this.drawnDashers = null;
+  }
+
+  /**
+   * Runs on every update of the loop. Updates image depending on if
+   * dash is locked
+   *
+   * @function update
+   * @instance
+   * @param {Number} currentFrameDuration the duration of the current
+   * frame
+   * @memberof DrawDashSystem
+   */
+  update(currentFrameDuration) {
+
+    for (const drawnDasher of this.drawnDashers) {
+
+      const dash = drawnDasher.dash;
+      const container = drawnDasher.container.container;
+
+      if (dash.locked) {
+        this._drawDashFace(container);
+        continue;
+      }
+
+      this._removeDashFace(container);
+    }
+  }
+
+  // Draws the dash face
+
+  _drawDashFace(container) {
+
+    const blush = container.getChildByName('blush');
+    const smile = container.getChildByName('smile');
+    const frown = container.getChildByName('frown');
+    blush.visible = true;
+    frown.visible = true;
+    smile.visible = false;
+  }
+
+  // Removes the dash face
+
+  _removeDashFace(container) {
+
+    const blush = container.getChildByName('blush');
+    const smile = container.getChildByName('smile');
+    const frown = container.getChildByName('frown');
+    blush.visible = false;
+    frown.visible = false;
+    smile.visible = true;
+  }
+};
index 06d0e603642432fceee069d8c6f2e33f877474e3..83c740dce94b30d9bc641dc28f3240feaabe0094 100644 (file)
@@ -88,5 +88,8 @@ export default class RenderSystem extends System {
    * frame
    * @memberof RenderSystem
    */
-  update(currentFrameDuration) {}
+  update(currentFrameDuration) {
+
+    this.application.render();
+  }
 };