]> git.r.bdr.sh - rbdr/serpentity/blobdiff - dist/serpentity.js
Replace code and lab with ndoe test runner
[rbdr/serpentity] / dist / serpentity.js
index 8871985bc710ea7debe9f4b1c1c1093b71d13a5d..c3b6f62861c05bb98dad1674cf8bf98fc06a9845 100644 (file)
@@ -1,521 +1 @@
-'use strict';
-
-/*
-Serpentity is a simple entity framework inspired by Ash.
-
-Usage:
-
-    let Serpentity = require('serpentity');
-
-## Instantiating an engine
-
-    let engine = 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.
-
-    let 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"
-
-    let 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.
-
-    let 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.
-
-    let TestSystem = class TestSystem extends Serpentity.System {
-      added (engine){
-        this.nodeList = engine.getNodes(MovementNode);
-      },
-      removed (engine){
-        this.nodeList = undefined;
-      }
-      update (dt){
-        let node;
-        for (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
-
-*/
-let Serpentity = class Serpentity {
-
-  constructor (config) {
-    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
-   */
-  addSystem (system, priority) {
-    let lastIndex, found;
-
-    if (this.systems.indexOf(system) >= 0) {
-      return false;
-    }
-
-    system.priority = priority;
-
-    found = false;
-    lastIndex = 0;
-
-    this.systems.some(function findPriority(existingSystem, i) {
-      lastIndex = i;
-      if (existingSystem.priority >= system.priority) {
-        found = true;
-        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
-   */
-  removeSystem (system) {
-    let position;
-
-    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
-   */
-  addEntity (entity) {
-    if (this.entities.indexOf(entity) >= 0) {
-      return false;
-    }
-    this.entities.push(entity);
-
-    this._nodeCollections.forEach(function (collection) {
-      collection.add(entity);
-    });
-
-    return true;
-  }
-
-  /*
-   * Removes entity from system, removing from all node collections
-   *
-   * returns true if removed, false if not present
-   */
-  removeEntity (entity) {
-    let position;
-
-    position = this.entities.indexOf(entity);
-    if (position >= 0) {
-      this._nodeCollections.forEach(function (collection) {
-        collection.remove(entity);
-      });
-
-      this.entities.splice(position, 1);
-      return true;
-    }
-
-    return false;
-  }
-
-  /*
-   * Given a Node Class, retrieves a list of all the nodes for each
-   * applicable entity.
-   */
-  getNodes (nodeType) {
-    let position, nodeCollection;
-
-    position = this._nodeCollectionKeys.indexOf(nodeType);
-
-    if (position >= 0) {
-      return this._nodeCollections[position].nodes;
-    }
-
-    nodeCollection = new Serpentity.NodeCollection({
-      type : nodeType
-    });
-
-    this._nodeCollectionKeys.push(nodeType);
-    this._nodeCollections.push(nodeCollection);
-
-    this.entities.forEach(function (entity) {
-      nodeCollection.add(entity);
-    });
-
-    return nodeCollection.nodes;
-  }
-
-  /*
-   * Calls update for every loaded system.
-   */
-  update (dt) {
-    this.systems.forEach(function (system) {
-      system.update(dt);
-    });
-  }
-};
-
-// Add namespaced objects.
-if (typeof module !== 'undefined' && this.module !== module) {
-  Serpentity.Component = require('./serpentity/component.js');
-  Serpentity.Entity = require('./serpentity/entity.js');
-  Serpentity.Node = require('./serpentity/node.js');
-  Serpentity.NodeCollection = require('./serpentity/node_collection.js');
-  Serpentity.System = require('./serpentity/system.js');
-
-  module.exports = Serpentity;
-} else {
-  window.Serpentity = Serpentity;
-}
-
-'use strict';
-
-/* global Serpentity */
-
-/*
- * The entity gives the entity framework its name. It exists only
- * to hold components.
- */
-
-let Entity = class Entity {
-  constructor (config) {
-    this._componentKeys = [];
-    this._components = [];
-
-    Object.assign(this, config || {});
-  }
-
-  /*
-   * Adds a component to the entity.
-   *
-   * returns true if added, false if already present
-   */
-  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
-   */
-  hasComponent (componentClass) {
-    if (this._componentKeys.indexOf(componentClass) >= 0) {
-      return true;
-    }
-    return false;
-  }
-
-  /*
-   * returns the component associated with that key
-   */
-  getComponent (componentClass) {
-    let position;
-    position = this._componentKeys.indexOf(componentClass);
-    if (position >= 0) {
-      return this._components[position];
-    }
-  }
-};
-
-if (typeof module !== 'undefined' && this.module !== module) {
-  module.exports = Entity;
-} else {
-  Serpentity.Entity = Entity;
-}
-
-'use strict';
-
-/* global Serpentity */
-
-/*
- * A node describes a set of components in order to describe entities
- * that include them.
- */
-let Node = class Node {
-
-  /*
-   * Returns true if the given entity matches the defined protocol,
-   * false otherwise
-   */
-  static matches (entity) {
-    let property, types;
-
-    types = this.types;
-
-    for (property in types) {
-      if (types.hasOwnProperty(property)) {
-        let matched, type;
-
-        matched = false;
-        type = types[property];
-        if (entity.hasComponent(type)) {
-          matched = true;
-        }
-        if (!matched) {
-          return false;
-        }
-      }
-    }
-
-    return true;
-  }
-
-  constructor (config) {
-    this.types = {};
-
-    Object.assign(this, config || {});
-  }
-};
-
-if (typeof module !== 'undefined' && this.module !== module) {
-  module.exports = Node;
-} else {
-  Serpentity.Node = Node;
-}
-
-'use strict';
-
-/* global Serpentity */
-
-/*
- * 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.
- */
-
-let NodeCollection = class NodeCollection {
-
-  constructor (config) {
-    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.
-   */
-  add (entity) {
-
-    if (this.type.matches(entity) && !this._entityExists(entity)) {
-      let node, types, property;
-
-      node = new this.type({});
-      node.entity = entity;
-      types = this.type.types;
-
-      for (property in types) {
-        if (types.hasOwnProperty(property)) {
-          node[property] = entity.getComponent(types[property]);
-        }
-      }
-
-      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.
-   */
-  remove (entity) {
-    let found;
-
-    found = -1;
-    this.nodes.forEach(function (node, i) {
-      if (node.entity === entity) {
-        found = i;
-      }
-    });
-
-    if (found >= 0) {
-      this.nodes.splice(found, 1);
-      return true;
-    }
-
-    return false;
-  }
-
-  /*
-   * Checks whether we already have nodes for this entity.
-   */
-  _entityExists (entity) {
-    let found, node;
-
-    found = false;
-    for (node of this.nodes) {
-      if (node.entity === entity) {
-        found = true;
-      }
-    }
-
-    return found;
-  }
-};
-
-if (typeof module !== 'undefined' && this.module !== module) {
-  module.exports = NodeCollection;
-} else {
-  Serpentity.NodeCollection = NodeCollection;
-}
-
-'use strict';
-
-/* global Serpentity */
-
-/*
- * 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.
- */
-
-let Component = class Component {
-  constructor (config) {
-    Object.assign(this, config || {});
-  }
-};
-
-if (typeof module !== 'undefined' && this.module !== module) {
-  module.exports = Component;
-} else {
-  Serpentity.Component = Component;
-}
-
-'use strict';
-
-/* global Serpentity */
-
-/*
- * 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.
- */
-
-let System = class System {
-
-  /*
-   * This will be run when the system is added to the engine
-   */
-  added () {
-    // Override with added(engine)
-    // Receives an instance of the serpentity engine
-  }
-
-  /*
-   * This will be run when the system is removed from the engine
-   */
-  removed () {
-    // Override with removed(engine)
-    // Receives an instance of the serpentity engine
-  }
-
-  /*
-   * This will run every time the engine's update method is called
-   */
-  update () {
-    // Override with update(dt)
-    // Receives a delta of the time
-  }
-};
-
-if (typeof module !== 'undefined' && this.module !== module) {
-  module.exports = System;
-} else {
-  Serpentity.System = System;
-}
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Serpentity=t():e.Serpentity=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t,n){"use strict";var r,i="object"==typeof Reflect?Reflect:null,s=i&&"function"==typeof i.apply?i.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=i&&"function"==typeof i.ownKeys?i.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var o=Number.isNaN||function(e){return e!=e};function u(){u.init.call(this)}e.exports=u,u.EventEmitter=u,u.prototype._events=void 0,u.prototype._eventsCount=0,u.prototype._maxListeners=void 0;var c=10;function f(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function p(e){return void 0===e._maxListeners?u.defaultMaxListeners:e._maxListeners}function l(e,t,n,r){var i,s,o,u;if(f(n),void 0===(s=e._events)?(s=e._events=Object.create(null),e._eventsCount=0):(void 0!==s.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),s=e._events),o=s[t]),void 0===o)o=s[t]=n,++e._eventsCount;else if("function"==typeof o?o=s[t]=r?[n,o]:[o,n]:r?o.unshift(n):o.push(n),(i=p(e))>0&&o.length>i&&!o.warned){o.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=o.length,u=c,console&&console.warn&&console.warn(u)}return e}function h(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function a(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},i=h.bind(r);return i.listener=n,r.wrapFn=i,i}function d(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];return void 0===i?[]:"function"==typeof i?n?[i.listener||i]:[i]:n?function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(i):v(i,i.length)}function y(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function v(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}Object.defineProperty(u,"defaultMaxListeners",{enumerable:!0,get:function(){return c},set:function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");c=e}}),u.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},u.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},u.prototype.getMaxListeners=function(){return p(this)},u.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var r="error"===e,i=this._events;if(void 0!==i)r=r&&void 0===i.error;else if(!r)return!1;if(r){var o;if(t.length>0&&(o=t[0]),o instanceof Error)throw o;var u=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw u.context=o,u}var c=i[e];if(void 0===c)return!1;if("function"==typeof c)s(c,this,t);else{var f=c.length,p=v(c,f);for(n=0;n<f;++n)s(p[n],this,t)}return!0},u.prototype.addListener=function(e,t){return l(this,e,t,!1)},u.prototype.on=u.prototype.addListener,u.prototype.prependListener=function(e,t){return l(this,e,t,!0)},u.prototype.once=function(e,t){return f(t),this.on(e,a(this,e,t)),this},u.prototype.prependOnceListener=function(e,t){return f(t),this.prependListener(e,a(this,e,t)),this},u.prototype.removeListener=function(e,t){var n,r,i,s,o;if(f(t),void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(i=-1,s=n.length-1;s>=0;s--)if(n[s]===t||n[s].listener===t){o=n[s].listener,i=s;break}if(i<0)return this;0===i?n.shift():function(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}(n,i),1===n.length&&(r[e]=n[0]),void 0!==r.removeListener&&this.emit("removeListener",e,o||t)}return this},u.prototype.off=u.prototype.removeListener,u.prototype.removeAllListeners=function(e){var t,n,r;if(void 0===(n=this._events))return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[e]),this;if(0===arguments.length){var i,s=Object.keys(n);for(r=0;r<s.length;++r)"removeListener"!==(i=s[r])&&this.removeAllListeners(i);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(t=n[e]))this.removeListener(e,t);else if(void 0!==t)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this},u.prototype.listeners=function(e){return d(this,e,!0)},u.prototype.rawListeners=function(e){return d(this,e,!1)},u.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):y.call(e,t)},u.prototype.listenerCount=y,u.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){"use strict";n.r(t),n.d(t,"Component",(function(){return r})),n.d(t,"Entity",(function(){return i})),n.d(t,"Node",(function(){return s})),n.d(t,"System",(function(){return o})),n.d(t,"default",(function(){return p}));class r{constructor(e){Object.assign(this,e)}}class i{constructor(e){this._componentKeys=[],this._components=[],Object.assign(this,e)}addComponent(e){return!(this._componentKeys.indexOf(e.constructor)>=0)&&(this._componentKeys.push(e.constructor),this._components.push(e),!0)}hasComponent(e){return this._componentKeys.indexOf(e)>=0}getComponent(e){const t=this._componentKeys.indexOf(e);if(t>=0)return this._components[t]}}class s{static matches(e){const t=Object.keys(this.types);for(const n of t){const t=this.types[n];let r=!1;if(e.hasComponent(t)&&(r=!0),!r)return!1}return!0}constructor(e){this.types={},Object.assign(this,e)}}class o{added(){}removed(){}update(){}}var u=n(0),c=n.n(u);class f extends c.a{constructor(e){super(),this.nodes=[],this.type=null,Object.assign(this,e)}add(e){if(this.type.matches(e)&&!this._entityExists(e)){const t=new this.type({}),n=this.type.types,r=Object.keys(n);t.entity=e;for(const i of r)t[i]=e.getComponent(n[i]);return this.nodes.push(t),this.emit("nodeAdded",{node:t}),!0}return!1}remove(e){let t=-1,n=null;const r=this.nodes.some((r,i)=>{if(r.entity===e)return t=i,n=r,!0});return r&&(this.nodes.splice(t,1),this.emit("nodeRemoved",{node:n})),r}_entityExists(e){let t=!1;for(const n of this.nodes)n.entity===e&&(t=!0);return t}}f.prototype[Symbol.iterator]=function*(){yield*this.nodes};class p{constructor(e){this.systems=[],this.entities=[],this._nodeCollections=[],this._nodeCollectionKeys=[],Object.assign(this,e)}addSystem(e,t){if(this.systems.indexOf(e)>=0)return!1;e.priority=t;let n=0;return this.systems.some((t,r)=>{if(n=r,t.priority>=e.priority)return!0})||(n+=1),this.systems.splice(n,0,e),e.added(this),!0}removeSystem(e){const t=this.systems.indexOf(e);return t>=0&&(this.systems[t].removed(this),this.systems.splice(t,1),!0)}addEntity(e){if(this.entities.indexOf(e)>=0)return!1;this.entities.push(e);for(const t of this._nodeCollections)t.add(e);return!0}removeEntity(e){const t=this.entities.indexOf(e);if(t>=0){for(const t of this._nodeCollections)t.remove(e);return this.entities.splice(t,1),!0}return!1}getNodes(e){const t=this._nodeCollectionKeys.indexOf(e);if(t>=0)return this._nodeCollections[t].nodes;const n=new f({type:e});this._nodeCollectionKeys.push(e),this._nodeCollections.push(n);for(const e of this.entities)n.add(e);return n}update(e){for(const t of this.systems)t.update(e)}}}])}));
\ No newline at end of file