UNPKG

complex-engine

Version:

JS Component Entity Framework for Gamedevelopment

500 lines (423 loc) 12.5 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: World.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: World.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>import Entity from './Entity'; import Manager from './Manager'; import System from './System'; import EntitySystem from './System/EntitySystem'; import VoidSystem from './System/VoidSystem'; /** * The world contains all entities, systems and managers */ class World { constructor() { /** @var {Entity[]}*/ this.entities = []; /** @var {VoidSystem[]} */ this.voidSystems = []; /** @var {EntitySystem[]} */ this.entitySystems = []; /** @var {Manager[]} */ this.managers = []; /** @var { boolean} */ this.initialized = false; /** @var {number} */ this.ticks = 0; } /** * Creates and adds a new entity * @param {Component[]} components * @return {Entity} */ createEntity(components) { let slot = this._getFreeEntitySlot(); const entity = new Entity(); if (slot != null) { this.entities[slot] = entity; } else { slot = this.entities.length; this.entities.push(entity); } components.forEach(c => entity.addComponent(c)); entity.setIndex(slot); this._entityAdded(entity); return entity; } /** * Add entity to the world * @param { Entity} entity * @returns { World } */ addEntity(entity) { let slot = this._getFreeEntitySlot(); if (slot != null) { this.entities[slot] = entity; } else { slot = this.entities.length; this.entities.push(entity); } entity.setIndex(slot); this._entityAdded(entity); return this; } /** * remove entity from the world * @param {Entity} entity * @returns {World} * @private * @throws Error */ _removeEntity(entity) { const index = entity.getIndex(); if (index === null) { throw new Error('Entity has no index'); } this._entityDeleted(entity); return this; } /** * Get entity from world by its id * @param {number} index * @returns {Entity} * @throws Error */ getEntity(index) { if (this.entities[index] == undefined) { throw new Error('No entity found'); } return this.entities[index]; } /** * Get all entities from wold * @returns {Entity[]} */ getEntities() { return this.entities; } /** * Add new void system to the world * @param {VoidSystem} system */ addVoidSystem(system) { system.setWorld(this); let slot = this._getFreeEntitySystemSlot(); if (slot != null) { this.voidSystems[slot] = system; } else { this.voidSystems.push(system); } return this; } /** * Add new entity system to the world * @param {EntitySystem} system */ addEntitySystem(system) { system.setWorld(this); let slot = this._getFreeEntitySystemSlot(); if (slot != null) { this.entitySystems[slot] = system; } else { this.entitySystems.push(system); } return this; } /** * After all systems has been added, this should be called to initiate them * @return {World} */ init() { for (let i = 0, len = this.entitySystems.length; i &lt; len; i++) { let system = this.entitySystems[i]; system.addedToWorld(); } for (let i = 0, len = this.voidSystems.length; i &lt; len; i++) { let system = this.voidSystems[i]; system.addedToWorld(); } this.initialized = true; return this; } /** * get a System * @param {Function} systemClass Class constructor * @return {System} * @throws Error */ getSystem(systemClass) { for (let i = 0, len = this.entitySystems.length; i &lt; len; i++) { let s = this.entitySystems[i]; if (s instanceof systemClass) { return s; } } for (let i = 0, len = this.voidSystems.length; i &lt; len; i++) { let s = this.voidSystems[i]; if (s instanceof systemClass) { return s; } } throw 'System ' + systemClass + ' not found'; } /** * Remove System * @param {Function} systemClass Class constructor * @returns {World} */ removeSystem(systemClass) { const entitySystems = this.entitySystems; const eLen = entitySystems.length; const newESystems = []; for (let i = 0; i &lt; eLen; i++) { const system = entitySystems[i]; if (!system instanceof systemClass) { newESystems.push(system); } } this.entitySystems = newESystems; const voidSystems = this.voidSystems; const vLen = voidSystems.length; const newVSystems = []; for (let i = 0; i &lt; vLen; i++) { const system = voidSystems[i]; if (!system instanceof systemClass) { newVSystems.push(system); } } this.voidSystems = newVSystems; return this; } /** * Add Manager * @param {Manager} manager Manager instance * @returns {World} */ addManager(manager) { manager.setWorld(this); this.managers.push(manager); return this; } /** * Get a manager * @param { Function} managerClass Manager class constructor * @returns {Manager} * @throws Error */ getManager(managerClass) { for (let i = 0, len = this.managers.length; i &lt; len; i++) { let manager = this.managers[i]; if (manager instanceof managerClass) { return this.managers[i]; } } throw 'Manager ' + name + ' not found'; } /** * Update the world * @throws Error */ update() { if (this.initialized === false) { throw new Error('Not initialized'); } this._updateEntities() ._updateVoidSystem() ._updateEntitySystem(); this.ticks++; } /** * Update void systems * @private * @returns {World} */ _updateVoidSystem() { for (let s = 0, sLen = this.voidSystems.length; s &lt; sLen; s++) { let system = this.voidSystems[s]; system.update(); } return this; } /** * Update entity systems * @private * @returns {World} */ _updateEntitySystem() { for (let s = 0, sLen = this.entitySystems.length; s &lt; sLen; s++) { const system = this.entitySystems[s]; const entities = this.getEntitiesWithComponents(system.components); system.processEntities(entities); } } /** * * @param {Entity} entity * @param components * @private */ _checkIfEntityHasComponents(entity, components) { for (let i = 0; i &lt; components.length; i++) { if (!entity.hasComponent(components[i])) { return false; } } return true; } /** * Get a list of entities that match a component * @param {Function} component * @returns {Entity[]} */ getEntitiesWithComponent(component) { const entities = this.entities; const entitiesLength = entities.length; const filteredComponents = []; for (let i = 0; i &lt; entitiesLength; i++) { const entity = entities[i]; if (entity.hasComponent(component)) { filteredComponents.push(entity); } } return filteredComponents; } /** * Get a list of entities that match a component * @param {Function[]} components * @returns {Entity[]} */ getEntitiesWithComponents(components) { const matchingEntities = []; for (let i = 0; i &lt; this.entities.length; i++) { const entity = this.entities[i]; if (this._checkIfEntityHasComponents(entity, components)) { matchingEntities.push(entity); } } return matchingEntities; } /** * Update all entities state * @private * @returns {World} */ _updateEntities() { this.entities = this.entities.filter((entity) => { if (!entity.isAlive() &amp;&amp; entity.isRemove()) { this._removeEntity(entity); return false; } return true; }); return this; } /** * recycle entityslots * @private * @returns {number | null} */ _getFreeEntitySlot() { for (let e = 0, len = this.entities.length; e &lt; len; e++) { let entity = this.entities[e]; if (entity === null || entity === undefined) { return e; } } return null; } /** * recycle systemslot * @private * @return {number | null} */ _getFreeEntitySystemSlot() { for (let s = 0, len = this.entitySystems.length; s &lt; len; s++) { let system = this.entitySystems[s]; if (system === undefined || system === null) { return s; } } return null; } /** * notify systems for new entity * @param {Entity} entity * @private * @returns {World} */ _entityAdded(entity) { for (let s = 0, len = this.voidSystems.length; s &lt; len; s++) { let system = this.voidSystems[s]; system.added(entity); } for (let s = 0, len = this.entitySystems.length; s &lt; len; s++) { let system = this.entitySystems[s]; system.added(entity); } return this; } /** * notify systems for deleted entity * @param {Entity} entity * @private * @returns {World} */ _entityDeleted(entity) { for (let s = 0, len = this.voidSystems.length; s &lt; len; s++) { let system = this.voidSystems[s]; system.removed(entity); } for (let s = 0, len = this.entitySystems.length; s &lt; len; s++) { let system = this.entitySystems[s]; system.removed(entity); } } /** * @return {EntitySystem[]} */ getEntitySystems() { return this.entitySystems; } /** * @returns {VoidSystem[]} */ getVoidSystems() { return this.voidSystems; } /** * @return {Manager[]} */ getManagers() { return this.managers; } } export default World; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Component.html">Component</a></li><li><a href="Engine.html">Engine</a></li><li><a href="Entity.html">Entity</a></li><li><a href="EntitySystem.html">EntitySystem</a></li><li><a href="GroupManager.html">GroupManager</a></li><li><a href="Manager.html">Manager</a></li><li><a href="Scene.html">Scene</a></li><li><a href="System.html">System</a></li><li><a href="VoidSystem.html">VoidSystem</a></li><li><a href="World.html">World</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.3</a> on Sun Sep 08 2019 20:40:30 GMT+0200 (Central European Summer Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>