Source: Entity.js

Source: Entity.js

var EventEmitter = require('./EventEmitter');
var BitSet = require('./BitSet');

/**
 * Represents a Entity.
 * Entity is a simple object that holds {@link Component}.
 * @constructor
 * @extends EventEmitter
 * @param engine {Engine} - The Engine associated with this object.
 */
function Entity(engine) {
  EventEmitter.call(this);
  /**
   * The ID of this object.
   * This will be given by Engine, and it shouldn't be edited after
   * being added to the Engine.
   * Otherwise, You can edit the value to what you want.
   * @var {Number}
   */
  this.id = null;
  /**
   * The Engine associated with this object.
   * @private
   * @var {Engine}
   */
  this._engine = engine;
  /**
   * The BitSet holding information about what kind of Component this has.
   * @var {BitSet}
   */
  this.componentBits = new BitSet();
  /**
   * The BitSet holding information about what ComponentGroup this matches.
   * @var {BitSet}
   */
  this.componentGroupBits = new BitSet();
  /**
   * The key-value storage of Components.
   * @var {Object}
   */
  this.components = {};
}

Entity.prototype = Object.create(EventEmitter.prototype);
Entity.prototype.constructor = Entity;

/**
 * Adds the Component to the Entity.
 * @param key {String} - The key of the Component.
 * @param component {Component} - The Component to add.
 * @fires Entity#componentAdded
 */
Entity.prototype.add = function(key, component) {
  var bitPos = this._engine.getComponentBit(key);
  this.componentBits.set(bitPos, true);
  this.components[bitPos] = component;
  /**
   * This event is fired when a Component is added to the Entity.
   * @event Entity#componentAdded
   * @property {Entity} 0 - the Entity.
   * @property {String} 1 - the Component key added to Entity.
   * @property {Component} 2 - the Component added to Entity.
   */
  this.emit('componentAdded', this, key, component);
}

/**
 * Creates new Component with the args and adds to the Entity.
 * @param key {String} - The key of the Component.
 * @param args {Object} - A key-value storage to create the Component.
 * @return {Entity} the Entity to allow chains.
 */
Entity.prototype.create = function(key, args) {
  var constructor = this._engine.getComponentConstructor(key);
  var component = new constructor(args);
  this.add(key, component);
  return this;
}

/**
 * Executes Component related functions by its arguments.
 *
 * If only a key is provided, it returns the Component with that ID.
 * Otherwise, it creates the Component with the options.
 * @param {String} key - The Component's key
 * @param {Object} args - The options
 */
Entity.prototype.c = function(key, args) {
  if(args == null) return this.get(key);
  return this.create(key, args);
}

/**
 * Removes the Component from the Entity.
 * @param key {String} - The key of the Component.
 * @fires Entity#componentRemoved
 */
Entity.prototype.remove = function(key) {
  var bitPos = this._engine.getComponentBit(key);
  this.componentBits.set(bitPos, false);
  var orig = this.components[bitPos];
  delete this.components[bitPos];
  /**
   * This event is fired when a Component is removed from the Entity.
   * @event Entity#componentRemoved
   * @property {Entity} 0 - the Entity.
   * @property {String} 1 - the Component key removed from the Entity.
   */
  this.emit('componentRemoved', this, key);
}

/**
 * Returns the Component which this Entity has.
 * @param key {String} - The key of the Component.
 * @returns {Component} The component.
 */
Entity.prototype.get = function(key) {
  var bitPos = this._engine.getComponentBit(key);
  return this.components[bitPos];
}

/**
 * Checks whether if this Entity has the Component.
 * @param key {String} - The key of the Component to check.
 * @returns {Boolean} Whether if this Entity has the Component.
 */
Entity.prototype.has = function(key) {
  var bitPos = this._engine.getComponentBit(key);
  return this.componentBits.get(bitPos);
}

/**
 * Serializes the Entity object.
 * Components should be serializable in order to do this.
 * @return {Object} serialized Entity object
 */
Entity.prototype.toJSON = function() {
  var obj = {};
  obj.id = this.id;
  obj.components = {};
  for(var key in this.components) {
    var name = this._engine.getComponentName(key);
    obj.components[name] = this.components[key];
    if(this.components[key].toJSON) {
      obj.components[name] = this.components[key].toJSON();
    }
  }
  return obj;
}

Entity.prototype.serialize = Entity.prototype.toJSON;

/**
 * Returns new deserialized Entity object.
 * @param engine {Engine} the Engine object
 * @param data {Object} serialized Entity object
 * @return {Entity} the Entity object
 */
Entity.fromJSON = function(engine, data) {
  var entity = new Entity(engine);
  entity.id = data.id;
  for(var name in data.components) {
    entity.c(name, data.components[name]);
  }
  return entity;
}

Entity.deserialize = Entity.fromJSON;

if(typeof module !== 'undefined') {
  module.exports = Entity;
}