1 /**
  2  * The Render Engine
  3  * FleeBehavior
  4  *
  5  * @fileoverview Flee behavior, based on Craig Reynolds "Autonomous Steering Behaviors" article.
  6  *               The flee behavior is the opposite of the seek behavior, where the vehicle will
  7  *               move away from the target object.
  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.Flee",
 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     "fleeMinimumDistance":350
 49 });
 50 
 51 /**
 52  * @class The flee behavior component.  This is essentially opposite of seeking.  Fleeing
 53  *        needs to be updated dynamically.  If the argument to {@link #fleeFrom} is an
 54  *        object, it must be a descendant of {@link R.objects.Object2D}.
 55  * @param target The target to flee from or a point to flee from.
 56  * @param [minDist=350] The minimum distance at which the vehicle will be triggered to
 57  *        flee.
 58  * @extends R.components.logic.behaviors.BaseBehavior
 59  * @constructor
 60  */
 61 R.components.logic.behaviors.Flee = function () {
 62     "use strict";
 63     return R.components.logic.behaviors.BaseBehavior.extend(/** @scope R.components.logic.behaviors.Flee.prototype */{
 64 
 65         minDist:0,
 66         target:null,
 67 
 68         /** @private */
 69         constructor:function (target, minDist) {
 70             this.base("flee");
 71             this.minDist = minDist || R.Engine.options.behaviors.fleeMinimumDistance;
 72             this.target = target;
 73         },
 74 
 75         /**
 76          * Update the object to flee from.
 77          * @param target The point or object to flee from
 78          */
 79         fleeFrom:function (target) {
 80             this.target = target;
 81         },
 82 
 83         /**
 84          * This method is called by the game object to run the component,
 85          * updating its state.
 86          *
 87          * @param renderContext {R.rendercontexts.AbstractRenderContext} The context the component will render within.
 88          * @param time {Number} The global engine time
 89          * @param dt {Number} The delta between the world time and the last time the world was updated
 90          *          in milliseconds.
 91          */
 92         execute:function (time, dt) {
 93 
 94             if (!this.target || this.target.isDestroyed()) {
 95                 return R.math.Vector2D.ZERO;
 96             }
 97 
 98             if (!this.getGameObject() || this.getGameObject().isDestroyed()) {
 99                 return R.math.Vector2D.ZERO;
100             }
101 
102             // Calculate the desired velocity to steer toward the destination
103             var flee;
104             if (this.target.__POINT2D) {
105                 flee = R.math.Vector2D.create(this.target);
106             } else {
107                 flee = R.math.Vector2D.create(this.target.getOriginPosition());
108             }
109 
110             var gO = this.getGameObject(), mC = this.getTransformComponent(), pt = R.clone(gO.getOriginPosition()),
111                 offs = R.clone(flee).sub(pt), distance = offs.len(), steering = R.math.Vector2D.create(0, 0);
112 
113             offs.normalize();
114             if (distance > 0 && distance < this.minDist) {
115                 offs.mul(mC.getMaxSpeed());
116                 steering.set(offs.sub(mC.getVelocity())).mul(distance / this.minDist);
117             }
118 
119             offs.destroy();
120             flee.destroy();
121             pt.destroy();
122             return steering.neg();
123         }
124 
125     }, /** @scope R.components.logic.behaviors.Flee.prototype */{
126         getClassName:function () {
127             return "R.components.logic.behaviors.Flee";
128         }
129     });
130 };
131