1 // Load all required engine components 2 R.Engine.define({ 3 "class":"R.components.logic.behaviors.UnalignedCollisionAvoidance", 4 "requires":[ 5 "R.components.logic.behaviors.BaseBehavior" 6 ] 7 }); 8 9 // Add behavior options 10 if (R.Engine.options.behaviors === undefined) { 11 R.Engine.options.behaviors = {}; 12 } 13 14 $.extend(R.Engine.options.behaviors, { 15 "unalignedAvoidanceCollisionRadius":150, 16 "unalignedAvoidanceFutureDistance":60 17 }); 18 19 /** 20 * @class The unaligned collision avoidance behavior component. This component will actively avoid other moving 21 * objects by examining their future position. 22 * @param vehicles {Array} The vehicle list to compare against 23 * @param [radius=150] {Number} The radius around each vehicle to use in collision detection 24 * @param [checkLength=60] {Number} The distance in front of the vehicle to perform checking 25 * @extends R.components.logic.behaviors.BaseBehavior 26 * @constructor 27 */ 28 R.components.logic.behaviors.UnalignedCollisionAvoidance = function () { 29 "use strict"; 30 return R.components.logic.behaviors.BaseBehavior.extend(/** @scope R.components.logic.behaviors.UnalignedCollisionAvoidance.prototype */{ 31 32 radius:0, 33 vehicles:null, 34 checkLength:0, 35 36 /** @private */ 37 constructor:function (vehicles, radius, checkLength) { 38 this.base("unalignedcollision"); 39 this.vehicles = vehicles; 40 this.radius = radius || R.Engine.options.behaviors.unalignedAvoidanceCollisionRadius; 41 this.checkLength = checkLength || R.Engine.options.behaviors.unalignedAvoidanceFutureDistance; 42 }, 43 44 /** 45 * This method is called by the game object to run the component, 46 * updating its state. 47 * 48 * @param renderContext {R.rendercontexts.AbstractRenderContext} The context the component will render within. 49 * @param time {Number} The global engine time 50 * @param dt {Number} The delta between the world time and the last time the world was updated 51 * in milliseconds. 52 */ 53 execute:function (time, dt) { 54 // No vehicles? nothing to do 55 if (!this.vehicles) { 56 return R.math.Vector2D.ZERO; 57 } 58 59 if (!this.getGameObject() || this.getGameObject().isDestroyed()) { 60 return R.math.Vector2D.ZERO; 61 } 62 63 var steering = R.math.Vector2D.create(0, 0), count = 0; 64 65 for (var i = 0; i < this.vehicles.length; i++) { 66 var other = this.vehicles[i]; 67 if (other === this.getGameObject()) { 68 // If this is our game object, skip it... 69 continue; 70 } 71 72 if (other.isDestroyed() || this.getGameObject().isDestroyed()) { 73 return R.math.Vector2D.ZERO; 74 } 75 76 var oMC = other.getComponentByClass("R.components.transform.BehaviorMover2D"), oPos = R.math.Vector2D.create(other.getPosition()).add(other.getOrigin()), 77 oVel = R.clone(oMC.getVelocity()), gO = this.getGameObject(), mC = this.getTransformComponent(), 78 gPos = R.clone(gO.getPosition()).add(gO.getOrigin()), 79 fwd = R.clone(mC.getVelocity()).normalize(), future = R.clone(oVel).normalize().mul(this.checkLength), 80 diff = R.clone(oPos).add(future).sub(gPos); 81 82 var dot = diff.dot(fwd); 83 if (dot > 0) { 84 // They may meet in the future 85 var ray = R.clone(fwd).mul(this.checkLength), proj = R.clone(fwd).mul(dot), 86 pC = R.clone(proj), dist = pC.sub(diff).len(); 87 88 if (dist > 0 && dist < this.radius && proj.len() < ray.len()) { 89 // They will merge 90 var force = R.clone(fwd).mul(mC.getMaxSpeed()), angle = force.getAngle(); 91 angle += R.math.Math2D.radToDeg(diff.getSign(mC.getVelocity()) * R.math.Math2D.PI / 4); 92 force.setAngle(angle); 93 steering.add(force); 94 force.destroy(); 95 } 96 97 ray.destroy(); 98 proj.destroy(); 99 pC.destroy(); 100 } 101 102 oPos.destroy(); 103 oVel.destroy(); 104 gPos.destroy(); 105 fwd.destroy(); 106 diff.destroy(); 107 future.destroy(); 108 } 109 110 if (count > 0) { 111 steering.div(count); 112 } 113 114 if (steering.len() > 0) { 115 steering.normalize().mul(mC.getMaxSpeed()).sub(mC.getVelocity()).truncate(mC.getMaxForce()); 116 } 117 118 return steering; 119 } 120 121 }, /** @scope R.components.logic.behaviors.UnalignedCollisionAvoidance.prototype */{ 122 getClassName:function () { 123 return "R.components.logic.behaviors.UnalignedCollisionAvoidance"; 124 } 125 }); 126 }; 127