API Docs for: 0.3.0
Show:

File: modules/GameLogic/GameState.js

/**
 * @module GameLogic
 * @namespace GameLogic
 */

var TW = TW || {};
define(['../Utils/copyParam'], function(copyParam) {

	TW.GameLogic = TW.GameLogic || {};


	/**
	 * The GameState class provides an object which handle severals methods which can be called by the GameStateStack.
	 * Each GameState object contains some methods :
	 *
	 * - onUpdate       this method is called when the GameState is updating.
	 * - onDraw         this method is called when the GameState is drawing
	 * - onCreation     this method is called when the GameState is added to a GameStateStack
	 * - onDelete       this method is called when the GameState is removed from a GameStateStack
	 * - onSleep        this method is called when the GameState looses the focus.
	 * - onWakeUp       this method is called when the GameState takes back the focus.
	 *
	 * There are two ways to define these methods:
	 *
	 * - If you have a lot of code for the state, you can inherit from `GameState` and override these methods.
	 *   Or more simply directly redefine a method of an instance :
	 *
	 *         var myGameState = new GameState();
	 *         myGameState.onUpdate = myOnUpdateFunc;
	 *         myGameState.onDraw = myOnDrawFunc;
	 *
	 * - For a little state, with just few code, methods can be passed in arguments:
	 *
	 *         new GameState({
	 *              onUpdate: function(elapsedTime) {
	 *                  //before update
	 *              },
	 *              onDraw() {
	 *                  //before draw
	 *              }
	 *         });
	 *
	 *
	 * You can also insert Layers into the GameState. You can sort them by their z-index in asc or desc order.
	 * Layers allows you to render something on the context of the GameStateStack.
	 *
	 * You can also insert Callbacks into the GameState some callbacks which will be executed when the
	 * GameState is updating.
	 * Notice that callbacks are executed after the onUpdate event.
	 * You can sort the callbacks by specifiying a priority order.
	 *
	 * Note that you can also interact with the GameStateStack which own the GameState object.
	 * You can :
	 * - push states
	 * - pop states
	 * - go to a special state in the stack
	 *
	 * Here is an example on which i show how you can push state, pop state and go to a special state :
	 *
	 *     this.getGameStateStack().push(newState);
	 *     this.getGameStateStack().pop();
	 *     this.getGameStateStack().goToState("state_name");
	 *
	 * @class GameState
	 * @constructor
	 * @param {Object} params this object should contain severals members
	 *   @param {String} [params.name] which is the name of the State.
	 *   @param {Boolean} [params.sortLayerAsc=true] which is a boolean.
	 *   It must be equal to true if you want to sort Layers by ascendant order.
	 *   Otherwise it must be equal to false. Default value equals true.
	 *   @param {Boolean} [params.sortCallbackAsc=true] which is a boolean. It must be equal to true if you
	 *   want to sort Callbacks by ascendant order. Otherwise it must be equal to false. default value equals true.
	 *   @param {Function} [params.onUpdate] called when the GameState is updating.
	 *   @param {Function} [params.onDraw] called when the GameState is drawing.
	 *   @param {Function} [params.onCreation] called when the GameState is added to a GameStateStack.
	 *   @param {Function} [params.onDelete] called when the GameState is removed from a GameStateStack.
	 *   @param {Function} [params.onSleep] called when the GameState looses the focus.
	 *   @param {Function} [params.onWakeUp] called when the GameState takes back the focus.
	 */
	function GameState(params) {
		this._gameStateStack = null;
		this._layerList = [];
		this._callbackList = [];

		copyParam(this, params, {

			/**
			 * the name which is associated to the current GameState
			 *
			 * @property {String} name
			 */
			name:            "",

			/**
			 * The setSortLayer order allows you to define the sort order of the Layers.
			 * Note that the Layers are ordered by their z-index values.
			 *
			 * If it is `true` the  layers will be sort by ascendant order.
			 * Otherwise, your layers will be sorted by descendant order.
			 *
			 * @property {Boolean} sortLayerAsc
			 */
			sortLayerAsc:    true,

			/**
			 * The setCallbackOrder order allows you to define the sort order of the Callbacks
			 * If it is `true` the layers will be sort by ascendant order.
			 * Otherwise, the layers will be sorted by descendant order.
			 *
			 * @property {Boolean} sortCallbackAsc
			 */
			sortCallbackAsc: true,

			/**
			 * method called before each update. Can be overridden or given as argument to the constructor.
			 *
			 * @method onUpdate
			 * @param {Number} elapsedTime represents the amount of milliseconds elapsed since the last update call.
			 */
			/* jshint unused:false */
			onUpdate:        function(elapsedTime) {
			},

			/**
			 * method called before each draw. Can be overridden or given as argument to the constructor.
			 *
			 * @method onDraw
			 */
			onDraw: function() {
			},

			/**
			 * method called when the state is created and placed on the stack.
			 * Can be overridden or given as argument to the constructor.
			 *
			 * @method onCreation
			 */
			onCreation: function() {
			},

			/**
			 * method called when the state is removed from the stack.
			 * Can be overridden or given as argument to the constructor.
			 *
			 * **Note:** The state object is not always really deleted, and can be reused later.
			 * This method should put the GameState as if it has never been used.
			 *
			 * @method onDelete
			 */
			onDelete: function() {
			},

			/**
			 * method called when the state becomes active.
			 * Can be overridden or given as argument to the constructor.
			 *
			 * @method onWakeUp
			 */
			onWakeUp: function() {
			},

			/**
			 * method called when the state is put to sleep (another state becomes active).
			 * Can be overridden or given as argument to the constructor.
			 *
			 * @method onSleep
			 */
			onSleep: function() {
			}
		});
	}


	/**
	 * The addLayer function allow you to add a Layer to the GameState.
	 * By default the addLayer method order Layers by ascendant order by their z-depth values.
	 *
	 * @method addLayer
	 * @param {TW.Graphic.Layer} layer the Layer which will have to be added to the GameState.
	 */
	GameState.prototype.addLayer = function(layer) {
		this._layerList.push(layer);
		this.sortLayers();
	};

	/**
	 * This method allows you to remove a layer from the GameState.
	 *
	 * @method removeLayer
	 * @param {TW.Graphic.Layer} refLayer a reference to the layer that you want to suppress from the GameState.
	 * @return {Boolean} if the refLayer have been successfully finded and suppressed from the GameState object it will
	 * returns true. Otherwise it will returns false.
	 */
	GameState.prototype.removeLayer = function(refLayer) {
		for (var i = 0; i < this._layerList.length; i++) {
			if (refLayer === this._layerList[i]) {
				this._layerList.splice(i, 1);
				return true;
			}
		}
		return false;
	};

	/**
	 * The addCallback function allow you to add a callback to the current GameState object.
	 *
	 * @method addCallback
	 * @param {Object} param This object must contain a number called 'priority' and a reference to the callback
	 * called 'callback'.
	 * @param {Number} [param.priority] represent the execution priority of the callback.
	 * @param {Function} [param.callback] represent the function to execute.
	 * @return {Boolean} return true if param contains a priority and a callback members. otherwise it will
	 * returns false.
	 */
	GameState.prototype.addCallback = function(param) {
		if (param.priority && param.callback) {
			this._callbackList.push(param);
			this.sortCallbacks();
			return true;
		} else {
			return false;
		}
	};

	/**
	 * This method allows you to remove a callback from the current GameState object.
	 *
	 * @method removeCallback
	 * @param {Function} refCallback a reference to the callback function to remove from the current GameState object.
	 * @return {Boolean} if the refCallback have been successfully finded and suppressed then the method will return
	 * true. Otherwise it will return false.
	 */
	GameState.prototype.removeCallback = function(refCallback) {
		for (var i = 0; i < this._callbackList.length; i++) {
			if (refCallback === this._callbackList[i]) {
				this._callbackList.splice(i, 1);
				return true;
			}
		}
		return false;
	};

	/**
	 * The sortLayers method allow you to sort layers by their z-order.
	 *
	 * @method sortLayers
	 */
	GameState.prototype.sortLayers = function() {
		if (this.sortLayerAsc === true) {
			this._layerList.sort(function(a, b) {
				return a.zIndex - b.zIndex;
			});
		} else {
			this._layerList.sort(function(a, b) {
				return b.zIndex - a.zIndex;
			});
		}
	};

	/**
	 * The sortCallbacks method allow you yo sort callbacks by their priority member.
	 *
	 * @method sortCallbacks
	 */
	GameState.prototype.sortCallbacks = function() {
		if (this.sortCallbackAsc === true) {
			this._callbackList.sort(function(a, b) {
				return a.priority - b.priority;
			});
		} else {
			this._callbackList.sort(function(a, b) {
				return b.priority - a.priority;
			});
		}
	};

	/**
	 * This method allows you to set the GameStateStack parent of the gameState. Note that this method
	 * is use internally
	 * by the GameStateStack implementation.
	 * You should not use it from your own.
	 *
	 * @private
	 * @method setGameStateStack
	 * @param {GameStateStack} gameStateStack represents the gameStateStack object which the GameState object
	 * belongs to.
	 */
	GameState.prototype.setGameStateStack = function(gameStateStack) {
		this._gameStateStack = gameStateStack;
	};

	/**
	 * This method allows you to get the GameStateStack pattern which the current gameState belongs to.
	 *
	 * @method getGameStateStack
	 * @return {GameStateStack} if the current GameState object have not already been linked with a GameStateStack
	 * it will return null.
	 */
	GameState.prototype.getGameStateStack = function() {
		return this._gameStateStack;
	};

	/**
	 * This method is private, you do not have to use it, it is used internally by the GameStateStack class.
	 *
	 * @method update
	 * @param {Number} elapsedTime time elapsed since last update call.
	 */
	GameState.prototype.update = function(elapsedTime) {
		this.onUpdate(elapsedTime);
		for (var i = 0; i < this._callbackList.length; i++) {
			this._callbackList[i]();
		}
	};

	/**
	 * This method is private, you do not have to use it, it is used internally by the GameStateStack class.
	 *
	 * @method draw
	 * @param {CanvasRenderingContext2D} canvasContext graphicalContext on which graphical contents will be drawn.
	 */
	GameState.prototype.draw = function(canvasContext) {
		this.onDraw();
		for (var i = 0; i < this._layerList.length; i++) {
			this._layerList[i].draw(canvasContext);
		}
	};

	TW.GameLogic.GameState = GameState;
	return GameState;
});