diff options
| author | Rubén Beltrán del Río <ben@nsovocal.com> | 2018-04-21 03:48:01 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-04-21 03:48:01 -0500 |
| commit | 0616b3f00653c66b5e34814653e33413b9ec034e (patch) | |
| tree | 520e8c6390d5fd4b0e7b02541803bf052c244ecf /lib | |
| parent | 11be5ebabcdab8272d938f7b90ef0ea9be29a421 (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.js | 25 | ||||
| -rw-r--r-- | lib/factories/pixi.js | 66 | ||||
| -rw-r--r-- | lib/factories/sumo.js | 51 | ||||
| -rw-r--r-- | lib/nodes/renderable.js | 27 | ||||
| -rw-r--r-- | lib/sumo.js | 33 | ||||
| -rw-r--r-- | lib/systems/render.js | 99 |
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; + } + } +}; |