1 /** 2 * The Render Engine 3 * SeekBehavior 4 * 5 * @fileoverview Seek behavior, based on Craig Reynolds "Autonomous Steering Behaviors" article. 6 * The seek behavior will move the game object toward the provided destination 7 * position. 8 * 9 * @author: Brett Fattori (brettf@renderengine.com) 10 * @author: $Author: bfattori $ 11 * @version: $Revision: 1555 $ 12 * 13 * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com) 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining a copy 16 * of this software and associated documentation files (the "Software"), to deal 17 * in the Software without restriction, including without limitation the rights 18 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 * copies of the Software, and to permit persons to whom the Software is 20 * furnished to do so, subject to the following conditions: 21 * 22 * The above copyright notice and this permission notice shall be included in 23 * all copies or substantial portions of the Software. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 * THE SOFTWARE 32 */ 33 34 // Load all required engine components 35 R.Engine.define({ 36 "class":"R.components.logic.behaviors.Seek", 37 "requires":[ 38 "R.components.logic.behaviors.BaseBehavior" 39 ] 40 }); 41 42 // Add behavior options 43 if (R.Engine.options.behaviors === undefined) { 44 R.Engine.options.behaviors = {}; 45 } 46 47 $.extend(R.Engine.options.behaviors, { 48 "seekNearDistance":10 49 }); 50 51 /** 52 * @class The seek behavior component. Causes an object to move toward a target. 53 * @param target {R.math.Point2D|R.objects.Object2D} The point, or {@link R.objects.Object2D}, toward which the vehicle should seek 54 * @extends R.components.logic.behaviors.BaseBehavior 55 * @constructor 56 */ 57 R.components.logic.behaviors.Seek = function () { 58 "use strict"; 59 return R.components.logic.behaviors.BaseBehavior.extend(/** @scope R.components.logic.behaviors.Seek.prototype */{ 60 61 target:null, 62 arrived:false, 63 64 /** @private */ 65 constructor:function (target) { 66 this.base("seek"); 67 this.setTarget(target); 68 this.arrived = false; 69 }, 70 71 destroy:function () { 72 this.base(); 73 this.destPt.destroy(); 74 }, 75 76 reset:function () { 77 this.arrived = false; 78 this.base(); 79 }, 80 81 /** 82 * Set the target to seek. 83 * @param target {R.math.Point2D|R.objects.Object2D} The point, or object, 84 * to seek. 85 */ 86 setTarget:function (target) { 87 this.target = target; 88 }, 89 90 /** 91 * This method is called by the game object to run the component, 92 * updating its state. 93 * 94 * @param renderContext {R.rendercontexts.AbstractRenderContext} The context the component will render within. 95 * @param time {Number} The global engine time 96 * @param dt {Number} The delta between the world time and the last time the world was updated 97 * in milliseconds. 98 */ 99 execute:function (time, dt) { 100 var destPt = R.math.Vector2D.create(0, 0); 101 if (this.target.__POINT2D) { 102 destPt.set(this.target); 103 } else if (this.target instanceof R.objects.Object2D && !this.target.isDestroyed()) { 104 destPt.set(this.target.getOriginPosition()); 105 } else { 106 // Not a point or object, return zero steering 107 return R.math.Vector2D.ZERO; 108 } 109 110 // Calculate the desired velocity to steer toward the destination 111 var gO = this.getGameObject(), mC = this.getTransformComponent(), pt = R.clone(gO.getPosition()).add(gO.getOrigin()), 112 offs = R.clone(destPt).sub(pt), distance = offs.len(), steering = R.math.Vector2D.create(0, 0); 113 114 offs.normalize().mul(mC.getMaxSpeed()); 115 steering.set(offs.sub(mC.getVelocity())); 116 117 offs.destroy(); 118 119 if (this.nearPoint(pt, destPt, R.Engine.options.behaviors.seekNearDistance)) { 120 this.arrived = true; 121 } 122 123 pt.destroy(); 124 destPt.destroy(); 125 return steering; 126 }, 127 128 /** 129 * True if the object is near its destination. You can change the "near" 130 * distance, by setting <code>R.Engine.options.behaviors.seekNearDistance</code>. 131 * @return {Boolean} 132 */ 133 isArrived:function () { 134 return this.arrived; 135 }, 136 137 /** 138 * Determine if the first point is near the second point, within the 139 * set threshold. 140 * @param pt1 141 * @param pt2 142 * @param threshold 143 * @private 144 */ 145 nearPoint:function (pt1, pt2, threshold) { 146 if (pt1 && pt2) { 147 var p = R.math.Vector2D.create(pt1).sub(pt2), near = p.len() < threshold; 148 p.destroy(); 149 return near; 150 } 151 return false; 152 } 153 154 }, /** @scope R.components.logic.behaviors.Seek.prototype */{ 155 getClassName:function () { 156 return "R.components.logic.behaviors.Seek"; 157 } 158 }); 159 }; 160