aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRubén Beltrán del Río <ben@nsovocal.com>2018-04-21 03:48:01 -0500
committerGitHub <noreply@github.com>2018-04-21 03:48:01 -0500
commit0616b3f00653c66b5e34814653e33413b9ec034e (patch)
tree520e8c6390d5fd4b0e7b02541803bf052c244ecf /lib
parent11be5ebabcdab8272d938f7b90ef0ea9be29a421 (diff)
Render Sumo (#3)
* Use corrected components * Add renderable node * Add render system * Add sumo factory * Add systems and entities to app * Remove reference to weight / accel component * Update dependencies, add pixi and babel-polyfill * Use babel polyfill * Add component to store pixi containers * Add pixi container to the renderable support * Update factories to produce renderables * Update the renderable to use pixi It also uses the new event emitters in serpentity 2.1.0 * Initialize pixi and pass it to renderable system
Diffstat (limited to 'lib')
-rw-r--r--lib/components/pixi_container.js25
-rw-r--r--lib/factories/pixi.js66
-rw-r--r--lib/factories/sumo.js51
-rw-r--r--lib/nodes/renderable.js27
-rw-r--r--lib/sumo.js33
-rw-r--r--lib/systems/render.js99
6 files changed, 301 insertions, 0 deletions
diff --git a/lib/components/pixi_container.js b/lib/components/pixi_container.js
new file mode 100644
index 0000000..5e5cb1f
--- /dev/null
+++ b/lib/components/pixi_container.js
@@ -0,0 +1,25 @@
+import { Component } from '@serpentity/serpentity';
+
+/**
+ * Component that stores a pixi container
+ *
+ * @extends {external:Serpentity.Component}
+ * @class PixiContainerComponent
+ * @param {object} config a configuration object to extend.
+ */
+export default class PixiContainerComponent extends Component {
+ constructor(config) {
+
+ super(config);
+
+ /**
+ * The properthy that holds the pixi container
+ *
+ * @property {external:PixiJs.Container} container
+ * @name container
+ * @instance
+ * @memberof PixiContainerComponent
+ */
+ this.container = this.container || null;
+ }
+};
diff --git a/lib/factories/pixi.js b/lib/factories/pixi.js
new file mode 100644
index 0000000..e3c1b5a
--- /dev/null
+++ b/lib/factories/pixi.js
@@ -0,0 +1,66 @@
+import { Graphics } from 'pixi.js';
+
+/**
+ * Factory object that contains many methods to create prefab pixi
+ * objects
+ *
+ * @type object
+ * @name PixiFactory
+ */
+export default {
+
+ /**
+ * Creates a sumo container
+ *
+ * @function createSumo
+ * @memberof PixiFactory
+ * @return {external:CreateJs.Container} the created container
+ */
+ createSumo() {
+
+ const radius = 25;
+
+ // The body
+ const body = new Graphics();
+ body.beginFill(0x87c5ea)
+ .drawCircle(0, 0, radius)
+ .endFill();
+
+ // The mouth
+ const mouth = new Graphics();
+ mouth.lineStyle(10, 0xff0080, 1)
+ .arc(
+ 0, 0, // center
+ radius * 0.6,
+ Math.PI / 6,
+ 5 * Math.PI / 6
+ );
+
+ const leftEye = new Graphics();
+ leftEye.beginFill(0xffffff)
+ .drawCircle(-radius / 3 - radius / 8, -radius / 4, radius / 5)
+ .endFill();
+
+ const rightEye = new Graphics();
+ rightEye.beginFill(0xffffff)
+ .drawCircle(radius / 3 + radius / 8, -radius / 4, radius / 5);
+
+ const leftPupil = new Graphics();
+ leftPupil.beginFill(0x11)
+ .drawCircle(-radius / 3 - radius / 8, -radius / 4, radius / 10);
+
+ const rightPupil = new Graphics();
+ leftPupil.beginFill(0x11)
+ .drawCircle(radius / 3 + radius / 8, -radius / 4, radius / 10);
+
+ // The group
+ body.addChild(mouth);
+ body.addChild(leftEye);
+ body.addChild(rightEye);
+ body.addChild(leftPupil);
+ body.addChild(rightPupil);
+
+ return body;
+ }
+};
+
diff --git a/lib/factories/sumo.js b/lib/factories/sumo.js
new file mode 100644
index 0000000..b0e5416
--- /dev/null
+++ b/lib/factories/sumo.js
@@ -0,0 +1,51 @@
+import { Entity } from '@serpentity/serpentity';
+
+import PositionComponent from '@serpentity/components.position';
+import PixiContainerComponent from '../components/pixi_container';
+import PixiFactory from '../factories/pixi';
+
+/**
+ * Factory object that contains many methods to create prefab entities.
+ *
+ * @type object
+ * @name SumoFactory
+ */
+export default {
+
+ /**
+ * Creates a sumo entity and adds it to the engine. Can override
+ * position in the config object
+ *
+ * @function createSumo
+ * @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
+ */
+ createSumo(engine, config = {}) {
+
+ const entity = new Entity();
+
+ entity.addComponent(new PositionComponent(config.position));
+
+ const container = config.container || {
+ container: PixiFactory.createSumo()
+ };
+
+ // 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;
+
+ entity.addComponent(new PixiContainerComponent(container));
+
+ if (engine) {
+ engine.addEntity(entity);
+ }
+
+ return entity;
+ }
+};
diff --git a/lib/nodes/renderable.js b/lib/nodes/renderable.js
new file mode 100644
index 0000000..0a3a111
--- /dev/null
+++ b/lib/nodes/renderable.js
@@ -0,0 +1,27 @@
+import { Node } from '@serpentity/serpentity';
+
+import PixiContainerComponent from '../components/pixi_container';
+import PositionComponent from '@serpentity/components.position';
+
+/**
+ * Node identifying a renderable entity, should have position and a
+ * symbol to render
+ *
+ * @extends {external:Serpentity.Node}
+ * @class RenderableNode
+ */
+export default class RenderableNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify a wave entity
+ *
+ * @property {object} types
+ * @name types
+ * @memberof WaveNode
+ */
+RenderableNode.types = {
+ position: PositionComponent,
+ container: PixiContainerComponent
+};
diff --git a/lib/sumo.js b/lib/sumo.js
index da72991..81f948f 100644
--- a/lib/sumo.js
+++ b/lib/sumo.js
@@ -1,8 +1,12 @@
+import RenderSystem from './systems/render';
+import SumoFactory from './factories/sumo';
import Serpentity from '@serpentity/serpentity';
+import { Application } from 'pixi.js';
/* global window document */
const internals = {
+ kBackgroundColor: 0xd8c590,
kNoElementError: 'No element found. Cannot render.',
// Handler for the window load event. Initializes and runs the app.
@@ -56,6 +60,7 @@ internals.Sumo = class Sumo {
// Initialization functions
this._initializeCanvas();
+ this._initializePixi();
this._initializeSystems();
this._initializeEntities();
}
@@ -119,6 +124,18 @@ internals.Sumo = class Sumo {
window.addEventListener('resize', this._resizeCanvas.bind(this));
}
+ // Initialize Pixi
+
+ _initializePixi() {
+
+ this._pixi = new Application({
+ backgroundColor: internals.kBackgroundColor,
+ view: this._canvas,
+ width: this._canvas.width,
+ height: this._canvas.height
+ });
+ }
+
// Resizes the canvas to a square the size of the smallest magnitude
// of the window.
@@ -143,12 +160,28 @@ internals.Sumo = class Sumo {
_initializeSystems() {
+ this._engine.addSystem(new RenderSystem({
+ application: this._pixi
+ }));
}
// Initializes the serpentity entities
_initializeEntities() {
+ SumoFactory.createSumo(this._engine, {
+ position: {
+ x: 50,
+ y: 50
+ }
+ });
+
+ SumoFactory.createSumo(this._engine, {
+ position: {
+ x: 309,
+ y: 112
+ }
+ });
}
};
diff --git a/lib/systems/render.js b/lib/systems/render.js
new file mode 100644
index 0000000..8d3d446
--- /dev/null
+++ b/lib/systems/render.js
@@ -0,0 +1,99 @@
+import { System } from '@serpentity/serpentity';
+
+import RenderableNode from '../nodes/renderable';
+
+const internals = {
+ kNoPixiError: 'No pixi application passed to render system. Make sure you set the `application` key in the config object when initializing.'
+};
+
+/**
+ * Renders renderable objects to console
+ *
+ * @extends {external:Serpentity.System}
+ * @class RenderSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class RenderSystem extends System {
+
+ constructor(config = {}) {
+
+ super();
+
+ /**
+ * The node collection of renderable entities
+ *
+ * @property {external:Serpentity.NodeCollection} renderables
+ * @instance
+ * @memberof RenderSystem
+ */
+ this.renderables = null;
+
+ /**
+ * The pixi engine we will use to render
+ *
+ * @property {external:PixiJs.Application} renderables
+ * @instance
+ * @memberof RenderSystem
+ */
+ this._application = config.application;
+
+ if (!this._application) {
+ throw new Error(internals.kNoPixiError);
+ }
+ }
+
+ /**
+ * Initializes system when added. Requests renderable nodes and
+ * attaches to event listeners to add / remove them to pixi stage
+ *
+ * @function added
+ * @memberof RenderSystem
+ * @instance
+ * @param {external:Serpentity.Engine} engine the serpentity engine to
+ * which we are getting added
+ */
+ added(engine) {
+
+ this.renderables = engine.getNodes(RenderableNode);
+ this.renderables.on('nodeAdded', (event) => {
+
+ this._application.stage.addChild(event.node.container.container);
+ });
+ this.renderables.on('nodeRemoved', (event) => {
+
+ this._application.stage.removeChild(event.node.container.container);
+ });
+ }
+
+ /**
+ * Clears system resources when removed.
+ *
+ * @function removed
+ * @instance
+ * @memberof RenderSystem
+ */
+ removed() {
+
+ this.renderables.removeAllListeners('nodeAdded');
+ this.renderables.removeAllListeners('nodeRemoved');
+ this.renderables = null;
+ }
+
+ /**
+ * Runs on every update of the loop. Prints the location of every
+ * renderable
+ *
+ * @function update
+ * @instance
+ * @param {Number} currentFrameDuration the duration of the current
+ * frame
+ * @memberof RenderSystem
+ */
+ update(currentFrameDuration) {
+
+ for (const renderable of this.renderables) {
+ renderable.container.container.position.x = renderable.position.x;
+ renderable.container.container.position.y = renderable.position.y;
+ }
+ }
+};