]> git.r.bdr.sh - rbdr/serpentity/blobdiff - dist/serpentity.js
Merge branch 'release/2.0.0' into develop
[rbdr/serpentity] / dist / serpentity.js
index 2950427d9872c9e393effd1dcd70479f8db3beb2..d59bd638401b72ac523f069efb9ee3f6f24d35bf 100644 (file)
@@ -1,6 +1,848 @@
-"undefined"!=typeof require&&require("neon"),Class("Serpentity")({prototype:{systems:null,entities:null,_nodeCollections:null,_nodeCollectionKeys:null,init:function(e){var t;e=e||{},this.systems=[],this.entities=[],this._nodeCollections=[],this._nodeCollectionKeys=[];for(t in e)e.hasOwnProperty(t)&&(this[t]=e[t])},addSystem:function(e,t){var i,s;return this.systems.indexOf(e)>=0?!1:(e.priority=t,s=!1,i=0,this.systems.some(function(t,n){return i=n,t.priority>=e.priority?(s=!0,!0):void 0}),s||(i+=1),this.systems.splice(i,0,e),e.added(this),!0)},removeSystem:function(e){var t;return t=this.systems.indexOf(e),t>=0?(this.systems[t].removed(this),this.systems.splice(t,1),!0):!1},addEntity:function(e){return this.entities.indexOf(e)>=0?!1:(this.entities.push(e),this._nodeCollections.forEach(function(t){t.add(e)}),!0)},removeEntity:function(e){var t;return t=this.entities.indexOf(e),t>=0?(this._nodeCollections.forEach(function(t){t.remove(e)}),this.entities.splice(t,1),!0):!1},getNodes:function(e){var t,i;return t=this._nodeCollectionKeys.indexOf(e),t>=0?this._nodeCollections[t].nodes:(i=new Serpentity.NodeCollection({type:e}),this._nodeCollectionKeys.push(e),this._nodeCollections.push(i),this.entities.forEach(function(e){i.add(e)}),i.nodes)},update:function(e){this.systems.forEach(function(t){t.update(e)})}}}),"undefined"!=typeof require&&(require("./component.js"),require("./entity.js"),require("./node.js"),require("./node_collection.js"),require("./system.js"));
-Class(Serpentity,"Entity")({prototype:{_components:null,_componentKeys:null,init:function(n){var t;this._componentKeys=[],this._components=[];for(t in n)n.hasOwnProperty(t)&&(this[t]=n[t])},add:function(n){return this._componentKeys.indexOf(n.constructor)>=0?!1:(this._componentKeys.push(n.constructor),this._components.push(n),!0)},hasComponent:function(n){return this._componentKeys.indexOf(n)>=0?!0:!1},getComponent:function(n){var t;return t=this._componentKeys.indexOf(n),t>=0?this._components[t]:void 0}}});
-Class(Serpentity,"Node")({matches:function(t){var s,r,n;n=this.types;for(s in this.types)if(this.types.hasOwnProperty(s)&&(r=!1,t.hasComponent(n[s])&&(r=!0),!r))return!1;return!0},prototype:{types:null,init:function(){var t;this.types={};for(t in this.constructor)this.constructor.hasOwnProperty(t)&&(this.types[t]=this.constructor[t])}}});
-Class(Serpentity,"NodeCollection")({prototype:{type:null,nodes:null,init:function(t){var n;t=t||{},this.nodes=[];for(n in t)t.hasOwnProperty(n)&&(this[n]=t[n])},add:function(t){var n,e,i;if(this.type.matches(t)&&!this._entityExists(t)){n=new this.type({}),n.entity=t,e=this.type.types;for(i in e)e.hasOwnProperty(i)&&(n[i]=t.getComponent(e[i]));return this.nodes.push(n),!0}return!1},remove:function(t){var n;return n=-1,this.nodes.forEach(function(e,i){e.entity===t&&(n=i)}),n>=0?(this.nodes.splice(n,1),!0):!1},_entityExists:function(t){var n;return n=!1,this.nodes.forEach(function(e){e.entity===t&&(n=!0)}),n}}});
-Class(Serpentity,"Component")({});
-Class(Serpentity,"System")({prototype:{added:function(){},removed:function(){},update:function(){}}});
\ No newline at end of file
+(function webpackUniversalModuleDefinition(root, factory) {
+       if(typeof exports === 'object' && typeof module === 'object')
+               module.exports = factory();
+       else if(typeof define === 'function' && define.amd)
+               define([], factory);
+       else if(typeof exports === 'object')
+               exports["Serpentity"] = factory();
+       else
+               root["Serpentity"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/       // The module cache
+/******/       var installedModules = {};
+/******/
+/******/       // The require function
+/******/       function __webpack_require__(moduleId) {
+/******/
+/******/               // Check if module is in cache
+/******/               if(installedModules[moduleId])
+/******/                       return installedModules[moduleId].exports;
+/******/
+/******/               // Create a new module (and put it into the cache)
+/******/               var module = installedModules[moduleId] = {
+/******/                       i: moduleId,
+/******/                       l: false,
+/******/                       exports: {}
+/******/               };
+/******/
+/******/               // Execute the module function
+/******/               modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/               // Flag the module as loaded
+/******/               module.l = true;
+/******/
+/******/               // Return the exports of the module
+/******/               return module.exports;
+/******/       }
+/******/
+/******/
+/******/       // expose the modules object (__webpack_modules__)
+/******/       __webpack_require__.m = modules;
+/******/
+/******/       // expose the module cache
+/******/       __webpack_require__.c = installedModules;
+/******/
+/******/       // identity function for calling harmony imports with the correct context
+/******/       __webpack_require__.i = function(value) { return value; };
+/******/
+/******/       // define getter function for harmony exports
+/******/       __webpack_require__.d = function(exports, name, getter) {
+/******/               if(!__webpack_require__.o(exports, name)) {
+/******/                       Object.defineProperty(exports, name, {
+/******/                               configurable: false,
+/******/                               enumerable: true,
+/******/                               get: getter
+/******/                       });
+/******/               }
+/******/       };
+/******/
+/******/       // getDefaultExport function for compatibility with non-harmony modules
+/******/       __webpack_require__.n = function(module) {
+/******/               var getter = module && module.__esModule ?
+/******/                       function getDefault() { return module['default']; } :
+/******/                       function getModuleExports() { return module; };
+/******/               __webpack_require__.d(getter, 'a', getter);
+/******/               return getter;
+/******/       };
+/******/
+/******/       // Object.prototype.hasOwnProperty.call
+/******/       __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/       // __webpack_public_path__
+/******/       __webpack_require__.p = "";
+/******/
+/******/       // Load entry module and return exports
+/******/       return __webpack_require__(__webpack_require__.s = 5);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/*
+ * Components store data. Nothing to say here really, just
+ * inherit and add a prototype, or don't even inherit, see?
+ * It's just an empty class, so what I'm trying to say is your
+ * components can be any class whatsoever.
+ */
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Component = function Component(config) {
+  _classCallCheck(this, Component);
+
+  Object.assign(this, config);
+};
+
+module.exports = Component;
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/*
+ * The entity gives the entity framework its name. It exists only
+ * to hold components.
+ */
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Entity = function () {
+  function Entity(config) {
+    _classCallCheck(this, Entity);
+
+    this._componentKeys = [];
+    this._components = [];
+
+    Object.assign(this, config);
+  }
+
+  /*
+   * Adds a component to the entity.
+   *
+   * returns true if added, false if already present
+   */
+
+
+  _createClass(Entity, [{
+    key: 'addComponent',
+    value: function addComponent(component) {
+
+      if (this._componentKeys.indexOf(component.constructor) >= 0) {
+        return false;
+      }
+      this._componentKeys.push(component.constructor);
+      this._components.push(component);
+      return true;
+    }
+
+    /*
+     * returns true if component is included, false otherwise
+     */
+
+  }, {
+    key: 'hasComponent',
+    value: function hasComponent(componentClass) {
+
+      if (this._componentKeys.indexOf(componentClass) >= 0) {
+        return true;
+      }
+      return false;
+    }
+
+    /*
+     * returns the component associated with that key
+     */
+
+  }, {
+    key: 'getComponent',
+    value: function getComponent(componentClass) {
+
+      var position = this._componentKeys.indexOf(componentClass);
+      if (position >= 0) {
+        return this._components[position];
+      }
+    }
+  }]);
+
+  return Entity;
+}();
+
+module.exports = Entity;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/*
+ * A node describes a set of components in order to describe entities
+ * that include them.
+ */
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Node = function () {
+  _createClass(Node, null, [{
+    key: 'matches',
+
+
+    /*
+     * Returns true if the given entity matches the defined protocol,
+     * false otherwise
+     */
+    value: function matches(entity) {
+
+      var typeNames = Object.keys(this.types);
+
+      var _iteratorNormalCompletion = true;
+      var _didIteratorError = false;
+      var _iteratorError = undefined;
+
+      try {
+        for (var _iterator = typeNames[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+          var typeName = _step.value;
+
+
+          var type = this.types[typeName];
+          var matched = false;
+
+          if (entity.hasComponent(type)) {
+            matched = true;
+          }
+
+          if (!matched) {
+            return false;
+          }
+        }
+      } catch (err) {
+        _didIteratorError = true;
+        _iteratorError = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion && _iterator.return) {
+            _iterator.return();
+          }
+        } finally {
+          if (_didIteratorError) {
+            throw _iteratorError;
+          }
+        }
+      }
+
+      return true;
+    }
+  }]);
+
+  function Node(config) {
+    _classCallCheck(this, Node);
+
+    this.types = {};
+
+    Object.assign(this, config);
+  }
+
+  return Node;
+}();
+
+module.exports = Node;
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/*
+ * Node Collections contain nodes, in order to keep the lists of nodes
+ * that belong to each type.
+ *
+ * It has a type which is the class name of the node, and an array of
+ * instances of that class.
+ */
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var NodeCollection = function () {
+  function NodeCollection(config) {
+    _classCallCheck(this, NodeCollection);
+
+    this.nodes = [];
+    this.type = null;
+
+    Object.assign(this, config);
+  }
+
+  /*
+   * Creates a node for an entity if it matches, and adds it to the
+   * node list.
+   *
+   * Returns true if added, false otherwise.
+   */
+
+
+  _createClass(NodeCollection, [{
+    key: 'add',
+    value: function add(entity) {
+
+      if (this.type.matches(entity) && !this._entityExists(entity)) {
+
+        var node = new this.type({});
+        var types = this.type.types;
+        var typeNames = Object.keys(types);
+
+        node.entity = entity;
+
+        var _iteratorNormalCompletion = true;
+        var _didIteratorError = false;
+        var _iteratorError = undefined;
+
+        try {
+          for (var _iterator = typeNames[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+            var typeName = _step.value;
+
+            node[typeName] = entity.getComponent(types[typeName]);
+          }
+        } catch (err) {
+          _didIteratorError = true;
+          _iteratorError = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion && _iterator.return) {
+              _iterator.return();
+            }
+          } finally {
+            if (_didIteratorError) {
+              throw _iteratorError;
+            }
+          }
+        }
+
+        this.nodes.push(node);
+
+        return true;
+      }
+
+      return false;
+    }
+
+    /*
+     * Removes an entity by removing its related node from the list of nodes
+     *
+     * returns true if it was removed, false otherwise.
+     */
+
+  }, {
+    key: 'remove',
+    value: function remove(entity) {
+
+      var foundIndex = -1;
+
+      var found = this.nodes.some(function (node, i) {
+
+        if (node.entity === entity) {
+          foundIndex = i;
+          return true;
+        }
+      });
+
+      if (found) {
+        this.nodes.splice(foundIndex, 1);
+      }
+
+      return found;
+    }
+
+    /*
+     * Checks whether we already have nodes for this entity.
+     */
+
+  }, {
+    key: '_entityExists',
+    value: function _entityExists(entity) {
+
+      var found = false;
+
+      var _iteratorNormalCompletion2 = true;
+      var _didIteratorError2 = false;
+      var _iteratorError2 = undefined;
+
+      try {
+        for (var _iterator2 = this.nodes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+          var node = _step2.value;
+
+          if (node.entity === entity) {
+            found = true;
+          }
+        }
+      } catch (err) {
+        _didIteratorError2 = true;
+        _iteratorError2 = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion2 && _iterator2.return) {
+            _iterator2.return();
+          }
+        } finally {
+          if (_didIteratorError2) {
+            throw _iteratorError2;
+          }
+        }
+      }
+
+      return found;
+    }
+  }]);
+
+  return NodeCollection;
+}();
+
+module.exports = NodeCollection;
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/*
+ * Systems contain most of the logic, and work with nodes in order to
+ * act and change their values.
+ *
+ * You usually want to inherit from this class and override the
+ * three methods. They are shown here to document the interface.
+ */
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var System = function () {
+  function System() {
+    _classCallCheck(this, System);
+  }
+
+  _createClass(System, [{
+    key: 'added',
+
+
+    /*
+     * This will be run when the system is added to the engine
+     */
+    value: function added() {}
+    // Override with added(engine)
+    // Receives an instance of the serpentity engine
+
+
+    /*
+     * This will be run when the system is removed from the engine
+     */
+
+  }, {
+    key: 'removed',
+    value: function removed() {}
+    // Override with removed(engine)
+    // Receives an instance of the serpentity engine
+
+
+    /*
+     * This will run every time the engine's update method is called
+     */
+
+  }, {
+    key: 'update',
+    value: function update() {
+      // Override with update(dt)
+      // Receives a delta of the time
+    }
+  }]);
+
+  return System;
+}();
+
+module.exports = System;
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+/*
+Serpentity is a simple entity framework inspired by Ash.
+
+Usage:
+
+    const Serpentity = require('serpentity');
+
+## Instantiating an engine
+
+    const engine = new Serpentity();
+
+Add entities or systems, systems are added with a priority (the smaller
+the number, the earlier it will be called):
+
+    engine.addEntity(entityFactory());
+    engine.addSystem(new GameSystem(), priority);
+
+Update all systems:
+
+    engine.update(dt);
+
+Remove entities or systems:
+
+    engine.removeEntity(entityReference);
+    engine.removeSystem(systemReference);
+
+## Creating Entities
+
+Entities are the basic object of Serpentity, and they do nothing.
+
+    const entity = new Serpentity.Entity();
+
+All the behavior is added through components
+
+## Creating Components
+
+Components define data that we can add to an entity. This data will
+eventually be consumed by "Systems"
+
+    const PositionComponent = class PositionComponent extends Serpentity.Component {
+      constructor(config) {
+
+        this.x = 0;
+        this.y = 0;
+
+        super(config);
+      }
+    };
+
+You can add components to entities by using the add method:
+
+    entity.addComponent(new PositionComponent());
+
+
+Systems can refer to entities by requesting nodes.
+
+## Working with Nodes
+
+Nodes are sets of components that you define, so your system can require
+entities that always follow the API defined in the node.
+
+    const MovementNode = class MovementNode extends Serpentity.Node;
+    MovementNode.position = PositionComponent;
+    MovementNode.motion = MotionComponent;
+
+You can then request an array of all the nodes representing entities
+that comply with that API
+
+    engine.getNodes(MovementNode);
+
+## Creating Systems
+
+Systems are called on every update, and they use components through nodes.
+
+    const TestSystem = class TestSystem extends Serpentity.System {
+      added(engine){
+
+        this.nodeList = engine.getNodes(MovementNode);
+      }
+
+      removed(engine){
+
+        this.nodeList = undefined;
+      }
+
+      update(dt){
+
+        for (const node of this.nodeList) {
+          console.log(`Current position is: ${node.position.x},${node.position.y}`);
+        }
+      }
+    };
+
+## That's it
+
+Just run `engine.update(dt)` in your game loop :D
+
+*/
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Serpentity = function () {
+  function Serpentity(config) {
+    _classCallCheck(this, Serpentity);
+
+    this.systems = [];
+    this.entities = [];
+    this._nodeCollections = [];
+    this._nodeCollectionKeys = [];
+
+    Object.assign(this, config);
+  }
+
+  /*
+   * Adds a system to the engine, so its update method will be called
+   * with the others. Triggers added hook.
+   *
+   * returns true if added succesfully, false if already added
+   */
+
+
+  _createClass(Serpentity, [{
+    key: 'addSystem',
+    value: function addSystem(system, priority) {
+
+      if (this.systems.indexOf(system) >= 0) {
+        return false;
+      }
+
+      system.priority = priority;
+
+      var lastIndex = 0;
+
+      var found = this.systems.some(function (existingSystem, i) {
+
+        lastIndex = i;
+        if (existingSystem.priority >= system.priority) {
+          return true;
+        }
+      });
+
+      if (!found) {
+        lastIndex += 1;
+      }
+
+      this.systems.splice(lastIndex, 0, system);
+      system.added(this);
+      return true;
+    }
+
+    /*
+     * Removes a system from the engine, so its update method will no
+     * longer will be called. Triggers the removed hook.
+     *
+     * returns true if removed succesfully, false if already added
+     */
+
+  }, {
+    key: 'removeSystem',
+    value: function removeSystem(system) {
+
+      var position = this.systems.indexOf(system);
+      if (position >= 0) {
+        this.systems[position].removed(this);
+        this.systems.splice(position, 1);
+        return true;
+      }
+
+      return false;
+    }
+
+    /*
+     * Adds an entity to the engine, adds to existing node collections
+     *
+     * returns true if added, false if already there
+     */
+
+  }, {
+    key: 'addEntity',
+    value: function addEntity(entity) {
+
+      if (this.entities.indexOf(entity) >= 0) {
+        return false;
+      }
+      this.entities.push(entity);
+
+      var _iteratorNormalCompletion = true;
+      var _didIteratorError = false;
+      var _iteratorError = undefined;
+
+      try {
+        for (var _iterator = this._nodeCollections[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+          var collection = _step.value;
+
+          collection.add(entity);
+        }
+      } catch (err) {
+        _didIteratorError = true;
+        _iteratorError = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion && _iterator.return) {
+            _iterator.return();
+          }
+        } finally {
+          if (_didIteratorError) {
+            throw _iteratorError;
+          }
+        }
+      }
+
+      return true;
+    }
+
+    /*
+     * Removes entity from system, removing from all node collections
+     *
+     * returns true if removed, false if not present
+     */
+
+  }, {
+    key: 'removeEntity',
+    value: function removeEntity(entity) {
+
+      var position = this.entities.indexOf(entity);
+      if (position >= 0) {
+        var _iteratorNormalCompletion2 = true;
+        var _didIteratorError2 = false;
+        var _iteratorError2 = undefined;
+
+        try {
+          for (var _iterator2 = this._nodeCollections[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+            var collection = _step2.value;
+
+            collection.remove(entity);
+          }
+        } catch (err) {
+          _didIteratorError2 = true;
+          _iteratorError2 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion2 && _iterator2.return) {
+              _iterator2.return();
+            }
+          } finally {
+            if (_didIteratorError2) {
+              throw _iteratorError2;
+            }
+          }
+        }
+
+        this.entities.splice(position, 1);
+        return true;
+      }
+
+      return false;
+    }
+
+    /*
+     * Given a Node Class, retrieves a list of all the nodes for each
+     * applicable entity.
+     */
+
+  }, {
+    key: 'getNodes',
+    value: function getNodes(nodeType) {
+
+      var position = this._nodeCollectionKeys.indexOf(nodeType);
+
+      if (position >= 0) {
+        return this._nodeCollections[position].nodes;
+      }
+
+      var nodeCollection = new Serpentity.NodeCollection({
+        type: nodeType
+      });
+
+      this._nodeCollectionKeys.push(nodeType);
+      this._nodeCollections.push(nodeCollection);
+
+      var _iteratorNormalCompletion3 = true;
+      var _didIteratorError3 = false;
+      var _iteratorError3 = undefined;
+
+      try {
+        for (var _iterator3 = this.entities[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+          var entity = _step3.value;
+
+          nodeCollection.add(entity);
+        }
+      } catch (err) {
+        _didIteratorError3 = true;
+        _iteratorError3 = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion3 && _iterator3.return) {
+            _iterator3.return();
+          }
+        } finally {
+          if (_didIteratorError3) {
+            throw _iteratorError3;
+          }
+        }
+      }
+
+      return nodeCollection.nodes;
+    }
+
+    /*
+     * Calls update for every loaded system.
+     */
+
+  }, {
+    key: 'update',
+    value: function update(dt) {
+      var _iteratorNormalCompletion4 = true;
+      var _didIteratorError4 = false;
+      var _iteratorError4 = undefined;
+
+      try {
+
+        for (var _iterator4 = this.systems[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+          var system = _step4.value;
+
+          system.update(dt);
+        }
+      } catch (err) {
+        _didIteratorError4 = true;
+        _iteratorError4 = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion4 && _iterator4.return) {
+            _iterator4.return();
+          }
+        } finally {
+          if (_didIteratorError4) {
+            throw _iteratorError4;
+          }
+        }
+      }
+    }
+  }]);
+
+  return Serpentity;
+}();
+
+// Add namespaced objects.
+Serpentity.Component = __webpack_require__(0);
+Serpentity.Entity = __webpack_require__(1);
+Serpentity.Node = __webpack_require__(2);
+Serpentity.NodeCollection = __webpack_require__(3);
+Serpentity.System = __webpack_require__(4);
+
+module.exports = Serpentity;
+
+/***/ })
+/******/ ]);
+});
\ No newline at end of file