Source: ComponentGroup.js

Source: ComponentGroup.js

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

/**
 * Represents the group of components.
 * Basically it's a criteria for finding Entity.
 * ComponentGroup has three BitSet which will be used to search Entity:
 * contain, intersect, exclude.
 * contain will only match if a Entity has all the Component in BitSet.
 * intersect will match if a Entity has at least one of the Component in BitSet.
 * exclude will match if a Entity doesn't have a Component in BitSet.
 * This class can be generated by a {@link ComponentGroup.createBuilder}.
 * @constructor
 * @extends EventEmitter
 * @see BitSet
 * @see Entity
 * @see Component
 */
function ComponentGroup(contain, intersect, exclude) {
  EventEmitter.call(this);
  /**
   * The ID of this object.
   * This will be given by Engine, and it shouldn't be edited.
   * @readonly
   * @var {Number}
   */
  this.id = null;
  /**
   * The Engine associated with this object.
   * @private
   * @var {Engine}
   */
  this._engine = null;
  /**
   * The 'contain' criteria. 
   * This will only match if a Entity has all the Component in this BitSet.
   * @var {BitSet}
   */
  this.contain = contain;
  /**
   * The 'intersect' criteria. 
   * This will match if a Entity has at least one of the Component in BitSet.
   * @var {BitSet}
   */
  this.intersect = intersect;
  /**
   * The 'exclude' criteria. 
   * This will match if a Entity doesn't have a Component in this BitSet.
   * @var {BitSet}
   */
  this.exclude = exclude;
}

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

/**
 * Checkes whether if the Entity matches its criteria.
 * @param entity {Entity} - The Entity to check.
 * @returns {Boolean} Whether if the Entity matches its criteria.
 */
ComponentGroup.prototype.matches = function(entity) {
  var compBits = entity.componentBits;
  
  if(compBits.isEmpty()) return false;
  if(!compBits.contains(this.contain)) return false;
  if(!this.intersect.isEmpty() && !this.intersect.intersects(compBits)) return false;
  if(this.exclude.intersects(compBits)) return false;
  return true;
}

/**
 * Checkes whether if the ComponentGroup equals the other.
 * The ComponentGroups are equal if they have same criteria.
 * @param o {ComponentGroup} - The other ComponentGroup.
 * @returns {Boolean} Whether if the ComponentGroups are equal.
 */
ComponentGroup.prototype.equals = function(o) {
  if(!this.contain.equals(o.contain)) return false;
  if(!this.intersect.equals(o.intersect)) return false;
  if(!this.exclude.equals(o.exclude)) return false;
  return true;
}

/**
 * Creates a Builder object that helps to make ComponentGroup object.
 * @static
 * @param engine {Engine} - The Engine which will use this ComponentGroup.
 * @returns {ComponentGroup.Builder} A Builder object.
 */
ComponentGroup.createBuilder = function(engine) {
  return new ComponentGroup.Builder(engine);
}

/**
 * This class helps to create a ComponentGroup object.
 * @constructor
 * @param engine {Engine} - The Engine which will use this object.
 */
ComponentGroup.Builder = function(engine) {
  this._engine = engine;
  this._contain = new BitSet();
  this._intersect = new BitSet();
  this._exclude = new BitSet();
}

/**
 * Resets the criteria of this object.
 * @returns {ComponentGroup.Builder} The Builder itself to make it chainable.
 */
ComponentGroup.Builder.prototype.reset = function() {
  this._contain = new BitSet();
  this._intersect = new BitSet();
  this._exclude = new BitSet();
  return this;
}

/**
 * Sets contain condition of the object.
 * @param args... {Function} - The list of component constructors.
 * @returns {ComponentGroup.Builder} The Builder itself to make it chainable.
 */
ComponentGroup.Builder.prototype.contain = function(args) {
  this._contain.or(this._engine.getComponentsBitSet(arguments));
  return this;
}

/**
 * Sets intersect condition of the object.
 * @param args... {Function} - The list of component constructors.
 * @returns {ComponentGroup.Builder} The Builder itself to make it chainable.
 */
ComponentGroup.Builder.prototype.intersect = function(args) {
  this._intersect.or(this._engine.getComponentsBitSet(arguments));
  return this;
}

/**
 * Sets exclude condition of the object.
 * @param args... {Function} - The list of component constructors.
 * @returns {ComponentGroup.Builder} The Builder itself to make it chainable.
 */
ComponentGroup.Builder.prototype.exclude = function(args) {
  this._exclude.or(this._engine.getComponentsBitSet(arguments));
  return this;
}

/**
 * Builds ComponentGroup object.
 * @returns {ComponentGroup} The CompoentGroup object.
 */
ComponentGroup.Builder.prototype.build = function() {
  return new ComponentGroup(this._contain, this._intersect, this._exclude);
}

/**
 * This event is fired to ComponentGroup when a Entity matching its criteria
 * has added to {@link Engine}.
 *
 * @event ComponentGroup#entityAdded
 * @type {Entity}
 * @see Engine
 */

/**
 * This event is fired to ComponentGroup when a Entity matching its criteria
 * has removed from {@link Engine}.
 *
 * @event ComponentGroup#entityRemoved
 * @type {Entity}
 * @see Engine
 */

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