changeset 23:e79347dd38a3

steering
author zzzzrrr <mason.green@gmail.com>
date Thu, 26 Mar 2009 20:35:58 -0400
parents 4fce5596d1f6
children 441eb7672404
files ai/ai.d ai/steer.d melee/melee.d openmelee.geany
diffstat 4 files changed, 98 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/ai/ai.d	Thu Mar 26 16:56:30 2009 -0400
+++ b/ai/ai.d	Thu Mar 26 20:35:58 2009 -0400
@@ -58,15 +58,18 @@
 	
 	void move(Ship enemy) {
 	    
+        st = bzVec2.zeroVect;
+        
         // Elementary steering AI 
 	    steer.update();
         //st = steer.steerToAvoidObstacles(0.25, m_world.bodyList);
-        st = steer.avoid(1.0, m_world.bodyList);
+        //st = steer.avoid(10.0, m_world.bodyList);
+        //st = steer.getSteering(m_world.bodyList);
         
         if(st == bzVec2.zeroVect) {
             avoidTurn = false;
-            //st = steer.steerForPursuit(enemy.state, maxPredictionTime);
-            //chase(enemy);
+            st = steer.steerForPursuit(enemy.state, maxPredictionTime);
+            chase(enemy);
         } else {
             avoid();
         }
@@ -111,7 +114,7 @@
         float angle = atan2(st.x, st.y);
         
         if(!avoidTurn) {
-            if(st.x <= 0) {
+            if(st.x >= 0) {
                 ship.turnRight();
             } else {
                 ship.turnLeft();
--- a/ai/steer.d	Thu Mar 26 16:56:30 2009 -0400
+++ b/ai/steer.d	Thu Mar 26 20:35:58 2009 -0400
@@ -178,10 +178,93 @@
         return avoidance;
     }
     
-    bzVec2 avoid(float minTimeToCollision, bzBody obstacles) {
+    bzVec2 getSteering(bzBody obstacles) {
+
+        // 1. Find the target that’s closest to collision
+
+        float radius = m_radius;
+        float rad;
+        // Store the first collision time
+        float shortestTime = 0.5;
+
+        // Store the target that collides then, and other data
+        // that we will need and can avoid recalculating
+        bzBody firstTarget = null;
+        float firstMinSeparation = 0;
+        float firstDistance = 0;
+        bzVec2 firstRelativePos;
+        bzVec2 firstRelativeVel;
+        bzVec2 relativePos;
+        
+        // Loop through each target
+        for (bzBody target = obstacles; target; target = target.next) {
+
+            if(target is m_body) continue;
+            
+            // Calculate the time to collision
+            relativePos = m_body.localPoint(target.position); // - m_position;
+            bzVec2 relativeVel = target.linearVelocity - m_velocity;
+            float relativeSpeed = relativeVel.length;
+            float timeToCollision = bzDot(relativePos, relativeVel) /
+                                    (relativeSpeed * relativeSpeed);
+
+            // Check if it is going to be a collision at all
+            float distance = relativePos.length;
+            float minSeparation = distance - relativeSpeed * shortestTime;
+            
+            float eRad;
+            for (bzShape s = target.shapeList; s; s = s.next) {
+                if(s.sweepRadius > eRad) {
+                    eRad = s.sweepRadius;
+                }
+            }
+                
+            if (minSeparation > radius + eRad) continue;
+
+            // Check if it is the shortest
+            if (timeToCollision > 0 && timeToCollision < shortestTime) {
+                
+                // Store the time, target and other data
+                shortestTime = timeToCollision;
+                firstTarget = target;
+                firstMinSeparation = minSeparation;
+                firstDistance = distance;
+                firstRelativePos = relativePos;
+                firstRelativeVel = relativeVel;
+                rad = eRad;
+            }
+        }
+        
+        // 2. Calculate the steering
+
+        // If we have no target, then exit
+        if(!firstTarget) return bzVec2.zeroVect;
+
+        Stdout(shortestTime).newline;
+        
+        // If we’re going to hit exactly, or if we’re already
+        // colliding, then do the steering based on current
+        // position.
+        if(firstMinSeparation <= 0 || firstDistance < radius + rad) {
+            relativePos = firstTarget.position - m_position;
+        } else {
+            // Otherwise calculate the future relative position:
+            relativePos = firstRelativePos + 
+                          firstRelativeVel * shortestTime;
+        }
+
+        // Avoid the target
+        bzVec2 steering = relativePos;
+        steering.normalize();
+        //steering.linear = relativePos * maxAcceleration
+
+        return steering;
+    }
+
+    bzVec2 avoid(float maxLookAhead, bzBody obstacles) {
         
         float avoidMargin = 1.0f;
-        float maxLookahead = minTimeToCollision * m_speed;
+        float maxLookahead = maxLookAhead * m_speed;
         
         // Make sure we're moving
 		if (m_velocity.length > 0)
@@ -221,9 +304,11 @@
                         // Find the point of avoidance
                         bzVec2 target = o.position + (closestPoint - o.position).length * radius;
 
+                        target -= m_position;
+                        
                         auto state = cast(State) m_body.userData;
-                        state.avoid = target;
-                        
+                        state.avoid = m_body.localPoint(target);
+
                         return target;
                     }
                 }
--- a/melee/melee.d	Thu Mar 26 16:56:30 2009 -0400
+++ b/melee/melee.d	Thu Mar 26 20:35:58 2009 -0400
@@ -131,7 +131,7 @@
         
         draw = new Render(world, ship1, ship2, settings);
         human = new Human(ship1);
-        ai = new AI(ship1, world);
+        ai = new AI(ship2, world);
     
         gui.begin(cfg).retained;
         gui.push(`main`);
@@ -153,7 +153,7 @@
 
         jobHub.addPreFrameJob( {
             // Update AI
-            ai.move(ship2);
+            ai.move(ship1);
         });
 
         jobHub.addPostFrameJob( {
--- a/openmelee.geany	Thu Mar 26 16:56:30 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-
-[indentation]
-indent_width=4
-indent_type=0
-indent_hard_tab_width=8
-detect_indent=false
-indent_mode=2
-
-[project]
-name=openmelee
-base_path=C:\\workspace\\openmelee
-make_in_base_path=false
-description=
-run_cmd=
-
-[files]
-current_page=3
-FILE_NAME_0=0;D;0;16;0;1;1;C:\\workspace\\openmelee\\openmelee.d;0
-FILE_NAME_1=1787;D;0;16;0;1;1;C:\\workspace\\openmelee\\game.d;0
-FILE_NAME_2=3831;D;0;16;0;1;1;C:\\workspace\\openmelee\\melee\\melee.d;0
-FILE_NAME_3=1970;D;0;16;0;1;1;C:\\workspace\\openmelee\\ai\\ai.d;0
-FILE_NAME_4=0;D;0;16;0;1;1;C:\\workspace\\openmelee\\ai\\human.d;0
-FILE_NAME_5=8104;D;0;16;0;1;1;C:\\workspace\\openmelee\\ai\\steer.d;0
-FILE_NAME_6=2371;D;0;16;0;1;1;C:\\workspace\\openmelee\\ai\\utilities.d;0
-FILE_NAME_7=12531;D;0;16;0;1;1;C:\\workspace\\openmelee\\render\\render.d;0
-FILE_NAME_8=0;D;0;16;0;1;1;C:\\workspace\\openmelee\\ships\\models.d;0
-FILE_NAME_9=1907;D;0;16;0;1;1;C:\\workspace\\openmelee\\ships\\orz.d;0
-FILE_NAME_10=1673;D;0;16;0;1;1;C:\\workspace\\openmelee\\ships\\planet.d;0
-FILE_NAME_11=2220;D;0;16;0;1;1;C:\\workspace\\openmelee\\ships\\ship.d;0
-FILE_NAME_12=1679;D;0;16;0;1;1;C:\\workspace\\openmelee\\ships\\urQuan.d;0
-FILE_NAME_13=16183;D;0;16;0;1;1;C:\\workspace\\blaze\\blaze\\bzWorld.d;0