const Path = require('path');
module.exports = {
- entry: './lib/sumo',
+ entry: ['babel-polyfill', './lib/sumo'],
output: {
path: Path.resolve(__dirname, '../assets'),
--- /dev/null
+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;
+ }
+};
--- /dev/null
+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;
+ }
+};
+
--- /dev/null
+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;
+ }
+};
--- /dev/null
+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
+};
+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.
// Initialization functions
this._initializeCanvas();
+ this._initializePixi();
this._initializeSystems();
this._initializeEntities();
}
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.
_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
+ }
+ });
}
};
--- /dev/null
+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;
+ }
+ }
+};
"requires": true,
"dependencies": {
"@serpentity/components.debug": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@serpentity/components.debug/-/components.debug-1.0.0.tgz",
- "integrity": "sha1-1mPRCQcWxVf3ShZYRDZjijWIfj4="
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@serpentity/components.debug/-/components.debug-2.0.0.tgz",
+ "integrity": "sha512-IYFPQYuwhSSL6+jfQ5H9IVgkGwX2336Mowuk+8jK1t8Bqc373uZv6CPR3MSh/tc+Bi6bHEn+pZp1FMUxS8o12g=="
},
- "@serpentity/serpentity": {
+ "@serpentity/components.position": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@serpentity/serpentity/-/serpentity-2.0.0.tgz",
- "integrity": "sha1-MEbOJKQ80vXLUbaVnkhXqZ6Bbl4="
+ "resolved": "https://registry.npmjs.org/@serpentity/components.position/-/components.position-2.0.0.tgz",
+ "integrity": "sha512-umCLx12S3dV8d23bBSnB5CAvmqSjh9iCl2/JyOZmtOex2BkUUjIf2aqA3ZWVwpgoDmbPJMnejvghwuWHlkV4ww=="
+ },
+ "@serpentity/serpentity": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@serpentity/serpentity/-/serpentity-2.1.0.tgz",
+ "integrity": "sha512-tt+WMauSRdi/bnem9pxHfoOtpi17RZjgB/tQuNCK8X6EMcoly5FgjJotpsa4FsjpWARJvq9P2zJFilNwYOZRYg==",
+ "requires": {
+ "events": "2.0.0"
+ }
},
"@sindresorhus/is": {
"version": "0.7.0",
"babel-types": "6.26.0"
}
},
+ "babel-polyfill": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
+ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "core-js": "2.5.5",
+ "regenerator-runtime": "0.10.5"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
+ "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
+ "dev": true
+ }
+ }
+ },
"babel-preset-env": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz",
"integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==",
"dev": true
},
+ "bit-twiddle": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz",
+ "integrity": "sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4="
+ },
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"stream-shift": "1.0.0"
}
},
+ "earcut": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.1.3.tgz",
+ "integrity": "sha512-AxdCdWUk1zzK/NuZ7e1ljj6IGC+VAdC3Qb7QQDsXpfNrc5IM8tL9nNXUmEGE6jRHTfZ10zhzRhtDmWVsR5pd3A=="
+ },
"editions": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
},
+ "eventemitter3": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
+ "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo="
+ },
"events": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
- "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
- "dev": true
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-2.0.0.tgz",
+ "integrity": "sha512-r/M5YkNg9zwI8QbSf7tsDWWJvO3PGwZXyG7GpFAxtMASnHL2eblFd7iHiGPtyGKKFPZ59S63NeX10Ws6WqGDcg=="
},
"evp_bytestokey": {
"version": "1.0.3",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
+ "ismobilejs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-0.4.1.tgz",
+ "integrity": "sha1-Gl8SbHD+05yT2jgPpiy65XI+fcI="
+ },
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=",
"dev": true
},
+ "mini-signals": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mini-signals/-/mini-signals-1.2.0.tgz",
+ "integrity": "sha1-RbCAE8X65RokqhqTXNMXye1yHXQ="
+ },
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"vm-browserify": "0.0.4"
},
"dependencies": {
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
+ "dev": true
+ },
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
- "dev": true
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"object-copy": {
"version": "0.1.0",
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true
},
+ "parse-uri": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-uri/-/parse-uri-1.0.0.tgz",
+ "integrity": "sha1-KHLcwi8aeXrN4Vg9igrClVLdrCA="
+ },
"pascalcase": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
"pinkie": "2.0.4"
}
},
+ "pixi-gl-core": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/pixi-gl-core/-/pixi-gl-core-1.1.4.tgz",
+ "integrity": "sha1-i0tcQzsx5Bm8N53FZc4bg1qRs3I="
+ },
+ "pixi.js": {
+ "version": "4.7.3",
+ "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-4.7.3.tgz",
+ "integrity": "sha512-uYCTtjYiqSpwN2kZLmjwAL+1yrdCL/pVI+waYlkVqAHBnuQCpOuGA/0UunbxZ4T13xVZ4wN+ftPlEjxWl0th3w==",
+ "requires": {
+ "bit-twiddle": "1.0.2",
+ "earcut": "2.1.3",
+ "eventemitter3": "2.0.3",
+ "ismobilejs": "0.4.1",
+ "object-assign": "4.1.1",
+ "pixi-gl-core": "1.1.4",
+ "remove-array-items": "1.0.0",
+ "resource-loader": "2.1.1"
+ }
+ },
"pkg-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
}
}
},
+ "remove-array-items": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/remove-array-items/-/remove-array-items-1.0.0.tgz",
+ "integrity": "sha1-B79CyzMvTPboXq2DteToltIyayE="
+ },
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
"dev": true
},
+ "resource-loader": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/resource-loader/-/resource-loader-2.1.1.tgz",
+ "integrity": "sha512-jRMGYUfa4AGk9ib45Wxc93lobhQVoiCUAUkWqsbb/fhGPge97YT1S8aC0xBEQpolMsrdmB3o7SH8VmIEvIDOLA==",
+ "requires": {
+ "mini-signals": "1.2.0",
+ "parse-uri": "1.0.0"
+ }
+ },
"responselike": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
},
"homepage": "https://github.com/rbdr/sumo#readme",
"dependencies": {
- "@serpentity/components.debug": "^1.0.0",
- "@serpentity/serpentity": "^2.0.0"
+ "@serpentity/components.debug": "^2.0.0",
+ "@serpentity/components.position": "^2.0.0",
+ "@serpentity/serpentity": "^2.1.0",
+ "pixi.js": "^4.7.3"
},
"browserslist": "last two versions",
"devDependencies": {
"babel-core": "^6.26.0",
+ "babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-loader": "^7.1.4",
"code": "^5.2.0",