complex-engine
Version:
JS Component Entity Framework for Gamedevelopment
500 lines (423 loc) • 12.5 kB
HTML
<!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 < len; i++) {
let system = this.entitySystems[i];
system.addedToWorld();
}
for (let i = 0, len = this.voidSystems.length; i < 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 < len; i++) {
let s = this.entitySystems[i];
if (s instanceof systemClass) {
return s;
}
}
for (let i = 0, len = this.voidSystems.length; i < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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() && 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 < 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 < 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 < len; s++) {
let system = this.voidSystems[s];
system.added(entity);
}
for (let s = 0, len = this.entitySystems.length; s < 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 < len; s++) {
let system = this.voidSystems[s];
system.removed(entity);
}
for (let s = 0, len = this.entitySystems.length; s < 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>