1 /** 2 * The Render Engine 3 * 4 * StateMachine component 5 * 6 * @author: Brett Fattori (brettf@renderengine.com) 7 * 8 * @author: $Author: bfattori $ 9 * @version: $Revision: 1555 $ 10 * 11 * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com) 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy 14 * of this software and associated documentation files (the "Software"), to deal 15 * in the Software without restriction, including without limitation the rights 16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 * copies of the Software, and to permit persons to whom the Software is 18 * furnished to do so, subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in 21 * all copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 * THE SOFTWARE. 30 * 31 */ 32 33 // The class this file defines and its required classes 34 R.Engine.define({ 35 "class":"R.components.logic.StateMachine", 36 "requires":[], 37 "includes":[ 38 "/libs/machine.js" 39 ] 40 }); 41 42 /** 43 * @class A component that uses a behavior tree to process state changes. This is 44 * based on Mary Rose Cook's excellent Machine.js (which is linked in) so for now 45 * look to: 46 * <blockquote> 47 * http://machinejs.maryrosecook.com/ 48 * </blockquote> 49 * The states, themselves, should exist on your {@link R.engine.GameObject} for 50 * which this component is used. 51 * 52 * @param name {String} The name of the component 53 * @param [states=null] {Object} A states control object, if <code>null</code> assumes the state 54 * methods exist on the host. 55 * @param [priority=1.0] {Number} The priority of this component 56 * @extends R.components.Logic 57 * @constructor 58 * @description Creates a state machine which is used to drive the behaviors of your game object. 59 */ 60 R.components.logic.StateMachine = function () { 61 "use strict"; 62 return R.components.Logic.extend(/** @scope R.components.logic.StateMachine.prototype */{ 63 64 machine:null, 65 states:null, 66 updateInterval:0, 67 lastUpdate:0, 68 69 /** @private */ 70 constructor:function (name, states, priority) { 71 if (R.isNumber(states)) { 72 priority = states; 73 states = null; 74 } 75 76 this.base(name, priority); 77 this.states = states; 78 this.machine = null; 79 this.updateInterval = 0; 80 this.lastUpdate = 0; 81 }, 82 83 /** 84 * Set the behavior tree for the state machine. This is also used to configure how 85 * often the machine is updated. By tweaking the speed at which decisions are made, 86 * it is possible to simulate faster or slower "behavior" or "thought" processing. 87 * 88 * @param stateTree {Object} The behavior tree object 89 * @param [updateInterval=1000] {Number} The number of milliseconds between state changes 90 */ 91 setBehaviorTree:function (stateTree, updateInterval) { 92 this.updateInterval = updateInterval || R.components.logic.StateMachine.DEFAULT_INTERVAL; 93 this.machine = new MachineJS(); 94 95 // Create the state machine on the game object 96 this.getGameObject().setObjectDataModel(R.components.logic.StateMachine.MACHINE_STATE, 97 this.machine.generateTree(stateTree, this.getGameObject(), this.states)); 98 }, 99 100 /** 101 * Set the interval at which the machine's state is updated. 102 * @param updateInterval {Number} The number of milliseconds between state changes 103 */ 104 setUpdateInterval:function (updateInterval) { 105 this.updateInterval = updateInterval; 106 this.lastUpdate = 0; 107 }, 108 109 /** 110 * Update the state machine for each step of the engine. 111 * 112 * @param renderContext {R.rendercontexts.AbstractRenderContext} The rendering context 113 * @param time {Number} The engine time in milliseconds 114 * @param dt {Number} The delta between the world time and the last time the world was updated 115 * in milliseconds. 116 */ 117 execute:function (renderContext, time, dt) { 118 if (time - this.lastUpdate > this.updateInterval) { 119 // Transition to the next state 120 var state = this.getGameObject() 121 .getObjectDataModel(R.components.logic.StateMachine.MACHINE_STATE); 122 123 state = state.tick(); 124 this.lastUpdate = time; 125 } 126 } 127 128 }, /** @scope R.components.logic.StateMachine.prototype */{ 129 getClassName:function () { 130 return "R.components.logic.StateMachine"; 131 }, 132 133 /** 134 * The default time between state changes (1000 milliseconds) 135 * @type {Number} 136 */ 137 DEFAULT_INTERVAL:1000, 138 139 /** 140 * The machine state data model location. 141 * @type {String} 142 */ 143 MACHINE_STATE:"MachineState" 144 }); 145 };