1 /**
  2  * The Render Engine
  3  * ObstacleAvoidanceBehavior
  4  *
  5  * @fileoverview Obstacle avoidance behavior, based on Craig Reynolds "Autonomous Steering Behaviors" article.
  6  *               This behavior will avoid the objects which are provided to it.  It will actively try to
  7  *               steer around the obstacles.
  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.ObstacleAvoidance",
 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     "obstacleAvoidanceRadius":60,
 49     "obstacleAvoidanceFutureDistance":40
 50 });
 51 
 52 /**
 53  * @class The obstacle avoidance behavior component.  This behavior will actively steer around
 54  *        the list of obstacles provided to it.
 55  * @param obstacles {Array} The obstacle list to compare against
 56  * @param [radius=150] {Number} The radius around each vehicle to use in collision detection
 57  * @param [futureDist=60] {Number} The distance in front of the vehicle to perform checking
 58  * @extends R.components.logic.behaviors.BaseBehavior
 59  * @constructor
 60  */
 61 R.components.logic.behaviors.ObstacleAvoidance = function () {
 62     "use strict";
 63     return R.components.logic.behaviors.BaseBehavior.extend(/** @scope R.components.logic.behaviors.ObstacleAvoidance.prototype */{
 64 
 65         radius:0,
 66         futureDist:0,
 67         vehicles:null,
 68 
 69         /** @private */
 70         constructor:function (obstacles, radius, futureDist) {
 71             this.base("obstacleavoid");
 72             this.vehicles = obstacles;
 73             this.radius = radius || R.Engine.options.behaviors.obstacleAvoidanceRadius;
 74             this.futureDist = futureDist || R.Engine.options.behaviors.obstacleAvoidanceFutureDistance;
 75         },
 76 
 77         /**
 78          * This method is called by the game object to run the component,
 79          * updating its state.
 80          *
 81          * @param renderContext {R.rendercontexts.AbstractRenderContext} The context the component will render within.
 82          * @param time {Number} The global engine time
 83          * @param dt {Number} The delta between the world time and the last time the world was updated
 84          *          in milliseconds.
 85          */
 86         execute:function (time, dt) {
 87             // No vehicles? nothing to do
 88             if (!this.vehicles) {
 89                 return R.math.Vector2D.ZERO;
 90             }
 91 
 92             if (!this.getGameObject() || this.getGameObject().isDestroyed()) {
 93                 return R.math.Vector2D.ZERO;
 94             }
 95 
 96             var steering = R.math.Vector2D.create(0, 0), count = 0;
 97 
 98             for (var i = 0; i < this.vehicles.length; i++) {
 99                 var other = this.vehicles[i];
100                 if (other === this.getGameObject()) {
101                     // If this is our game object, skip it...
102                     continue;
103                 }
104 
105                 if (other.isDestroyed() || this.getGameObject().isDestroyed()) {
106                     return R.math.Vector2D.ZERO;
107                 }
108 
109                 var oPos = R.math.Vector2D.create(other.getOriginPosition()),
110                     gO = this.getGameObject(), mC = this.getTransformComponent(),
111                     fwd = R.clone(mC.getVelocity()).normalize().mul(this.futureDist),
112                     gPos = R.math.Vector2D.create(gO.getOriginPosition()).add(fwd),
113                     diff = R.clone(gPos).sub(oPos), d = diff.len();
114 
115                 if (d > 0 && d < this.radius) {
116                     // They are close to each other
117                     diff.normalize(); //.div(d);
118                     steering.add(diff);
119                     count++
120                 }
121 
122                 oPos.destroy();
123                 gPos.destroy();
124                 fwd.destroy();
125                 diff.destroy();
126 
127             }
128 
129             if (count > 0) {
130                 steering.div(count);
131             }
132 
133             if (steering.len() > 0) {
134                 steering.normalize().mul(mC.getMaxSpeed()).sub(mC.getVelocity()).truncate(mC.getMaxForce());
135             }
136 
137             return steering;
138         }
139 
140     }, /** @scope R.components.logic.behaviors.ObstacleAvoidance.prototype */{
141         getClassName:function () {
142             return "R.components.logic.behaviors.ObstacleAvoidance";
143         }
144     });
145 };
146