changeset 22:4fce5596d1f6

ai work
author zzzzrrr <mason.green@gmail.com>
date Thu, 26 Mar 2009 16:56:30 -0400
parents cad384ad349e
children e79347dd38a3
files ai/ai.d ai/steer.d melee/melee.d openmelee.geany render/render.d ships/asteroids.d ships/orz.d ships/planet.d ships/ship.d ships/urQuan.d
diffstat 10 files changed, 251 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/ai/ai.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/ai/ai.d	Thu Mar 26 16:56:30 2009 -0400
@@ -48,6 +48,8 @@
     bzWorld m_world;
 	bzVec2 st;
     
+    bool avoidTurn;
+    
 	this(Ship ship, bzWorld world) {
         m_world = world;
 		this.ship = ship;
@@ -59,18 +61,15 @@
         // Elementary steering AI 
 	    steer.update();
         //st = steer.steerToAvoidObstacles(0.25, m_world.bodyList);
-        st = steer.avoid(maxPredictionTime, m_world.bodyList);
+        st = steer.avoid(1.0, m_world.bodyList);
         
         if(st == bzVec2.zeroVect) {
-            st = steer.steerForPursuit(enemy.state, maxPredictionTime);
-            chase(enemy);
+            avoidTurn = false;
+            //st = steer.steerForPursuit(enemy.state, maxPredictionTime);
+            //chase(enemy);
         } else {
-            Stdout(st.x)(",")(st.y).newline;
             avoid();
         }
-        
-        st = bzVec2.zeroVect;
-        
     }
     
     void chase(Ship enemy) {
@@ -111,15 +110,16 @@
         st = -bzVec2(y,-x);
         float angle = atan2(st.x, st.y);
         
-        if(st.x >= 0) {
-            ship.turnRight();
-        } else {
-            ship.turnLeft();
+        if(!avoidTurn) {
+            if(st.x <= 0) {
+                ship.turnRight();
+            } else {
+                ship.turnLeft();
+            }
+            avoidTurn = true;
         }
-    
-        //if(abs(angle) < PI/4) {
-			ship.thrust();
-		//}
+                
+        ship.thrust();
     }
 
 }
--- a/ai/steer.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/ai/steer.d	Thu Mar 26 16:56:30 2009 -0400
@@ -49,14 +49,6 @@
     {
         m_ship = ship;
         m_body = ship.rBody;
-        m_radius = 0.0f;
-        
-        // Find radius of body
-        for (bzShape s = m_body.shapeList; s; s = s.next) {
-            if(s.sweepRadius > m_radius) {
-                m_radius = s.sweepRadius;
-            }
-        }
     }
     
 	struct PathIntersection
@@ -81,6 +73,7 @@
         m_speed = m_ship.state.speed;
         m_maxForce = m_ship.state.maxForce;
         m_forward = m_ship.state.forward;
+        m_radius = m_ship.state.radius;
     }
 
     // -------------------------------------------------- steering behaviors
@@ -147,7 +140,7 @@
 
         bzVec2 avoidance;
         PathIntersection nearest, next;
-        float minDistanceToCollision = minTimeToCollision * m_speed;
+        float minDistanceToCollision = 10; //minTimeToCollision * m_speed;
         
         next.intersect = false;
         nearest.intersect = false;
@@ -159,7 +152,7 @@
             if(o is m_body) continue;
             
             // This code which presumes the obstacle is spherical
-            findNextIntersectionWithSphere(o, next, minDistanceToCollision);
+            findNextIntersectionWithSphere(o, next);
 
             if (!nearest.intersect || (next.intersect && next.distance < nearest.distance)) {
 					nearest = next;
@@ -168,7 +161,6 @@
         
         // when a nearest intersection was found
         if (nearest.intersect && (nearest.distance < minDistanceToCollision)) {
-            Stdout("Distance: ")(nearest.distance).newline;
             // compute avoidance steering force: take offset from obstacle to me,
             // take the component of that which is lateral (perpendicular to my
             // forward direction), set length to maxForce, add a bit of forward
@@ -176,10 +168,13 @@
             bzVec2 offset = m_position - nearest.obstacle.position;
             avoidance = perpendicularComponent(offset, m_forward);
             avoidance.normalize;
-            //avoidance *= m_maxForce;
+            avoidance = m_body.localPoint(avoidance);
+            ///avoidance *= m_maxForce;
             //avoidance += m_forward * m_maxForce * 0.75f;
         }
 
+        auto state = cast(State) m_body.userData;
+        state.avoid = avoidance;
         return avoidance;
     }
     
@@ -201,15 +196,13 @@
                 bzVec2 characterToObstacle = o.position - m_position;
 
                 real distanceSquared = bzDot(characterToObstacle, movementNormal);
-                distanceSquared = characterToObstacle.length - 
-                    distanceSquared*distanceSquared;
+                distanceSquared = characterToObstacle.lengthSquared - distanceSquared*distanceSquared;
 
                 // Check for collision
-                // Find radius of obstacle
                 float oRad = 0;
-                for (bzShape shape = o.shapeList; shape; shape = shape.next) {
-                    if(shape.sweepRadius > oRad) {
-                        oRad = shape.sweepRadius;
+                for (bzShape s = o.shapeList; s; s = s.next) {
+                    if(s.sweepRadius > oRad) {
+                        oRad = s.sweepRadius;
                     }
                 }
                 
@@ -223,31 +216,34 @@
                     if (distanceToClosest > 0 && distanceToClosest < maxLookahead)
                     {
                         // Find the closest point
-                        bzVec2 closestPoint = 
-                            o.position + movementNormal*distanceToClosest;
+                        bzVec2 closestPoint =  o.position + movementNormal * distanceToClosest;
 
                         // Find the point of avoidance
-                        bzVec2 target = 
-                            o.position +
-                            (closestPoint - o.position).length *
-                            (oRad + avoidMargin);
+                        bzVec2 target = o.position + (closestPoint - o.position).length * radius;
 
+                        auto state = cast(State) m_body.userData;
+                        state.avoid = target;
+                        
                         return target;
                     }
                 }
             }
 		}
+        
+        auto state = cast(State) m_body.userData;
+        state.avoid = bzVec2.zeroVect;
+                            
         return bzVec2.zeroVect;
 
     }
 
 		void findNextIntersectionWithSphere(bzBody obs, 
-                                            inout PathIntersection intersection, float mdc) {
+                                            inout PathIntersection intersection) {
                                                 
 			// This routine is based on the Paul Bourke's derivation in:
 			//   Intersection of a Line and a Sphere (or circle)
-			//   http://www.swin.edu.au/astronomy/pbourke/geometry/sphereline/
-
+			//   http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/raysphere.c
+            
 			float b, c, d, p, q, s;
 			bzVec2 lc;
 
@@ -255,7 +251,7 @@
 			intersection.intersect = false;
 			intersection.obstacle = obs;
 
-			// find "local center" (lc) of sphere in boid's coordinate space
+			// find "local center" (lc) of sphere in coordinate space
 			lc = m_body.localPoint(obs.position);
 
 			// computer line-sphere intersection parameters
@@ -269,7 +265,7 @@
                 }
             }
         
-			c = square(lc.x) + square(lc.y) - square(obsRadius + m_radius+mdc);
+			c = square(lc.x) + square(lc.y) - square(obsRadius + m_radius);
 			d = (b * b) - (4 * c);
             
 			// when the path does not intersect the sphere
--- a/melee/melee.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/melee/melee.d	Thu Mar 26 16:56:30 2009 -0400
@@ -48,11 +48,12 @@
 import openmelee.melee.boundaryListener;
 import openmelee.melee.contactListener;
 import openmelee.render.render;
-import openmelee.ai.ai;
-import openmelee.ai.human;
-import openmelee.ships.urQuan;
-import openmelee.ships.orz;
-import openmelee.ships.planet;
+import openmelee.ai.ai : AI;
+import openmelee.ai.human : Human;
+import openmelee.ships.urQuan : UrQuan;
+import openmelee.ships.orz : Orz;
+import openmelee.ships.planet : Planet;
+import openmelee.ships.asteroids : Asteroid;
 
 const ITERS_PER_SECOND = 100;
 const k_maxContactPoints = 100;
@@ -101,6 +102,7 @@
     Human human;
     Ship ship1;
 	Ship ship2;
+    Planet planet;
     
     bool running;
     
@@ -129,7 +131,7 @@
         
         draw = new Render(world, ship1, ship2, settings);
         human = new Human(ship1);
-        ai = new AI(ship2, world);
+        ai = new AI(ship1, world);
     
         gui.begin(cfg).retained;
         gui.push(`main`);
@@ -151,7 +153,7 @@
 
         jobHub.addPreFrameJob( {
             // Update AI
-            ai.move(ship1);
+            ai.move(ship2);
         });
 
         jobHub.addPostFrameJob( {
@@ -188,15 +190,16 @@
 
     void initWorld() {
 	    // Define world boundaries
-		worldAABB.lowerBound.set(-400.0f, -250.0f);
-		worldAABB.upperBound.set(400.0f, 250.0f);
+		worldAABB.lowerBound.set(-100.0f, -150.0f);
+		worldAABB.upperBound.set(100.0f, 150.0f);
 		world = new bzWorld(worldAABB, gravity, allowSleep);
 		world.boundaryListener = m_boundaryListener;
 		world.contactListener = m_contactListener;
 		ship1 = new UrQuan(world);
 		ship2 = new Orz(world);
         ship2.rBody.angle = 3.14159265/4;
-        auto planet = new Planet(world);
+        planet = new Planet(world);
+        //auto asteroids = new Asteroid(world);
 	}
     
     void boundaryViolated(bzBody rBody)
--- a/openmelee.geany	Thu Mar 26 07:02:56 2009 -0400
+++ b/openmelee.geany	Thu Mar 26 16:56:30 2009 -0400
@@ -14,13 +14,13 @@
 run_cmd=
 
 [files]
-current_page=5
+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=2415;D;0;16;0;1;1;C:\\workspace\\openmelee\\ai\\ai.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=7818;D;0;16;0;1;1;C:\\workspace\\openmelee\\ai\\steer.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
--- a/render/render.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/render/render.d	Thu Mar 26 16:56:30 2009 -0400
@@ -49,7 +49,7 @@
 import blaze.common.bzMath : bzXForm, bzVec2, bzMul, bzClamp;
 import blaze.common.bzConstants : k_toiSlop,k_maxProxies;
 
-import openmelee.ships.ship : Ship;
+import openmelee.ships.ship : Ship, State;
 import openmelee.melee.melee : Settings;
 
 // Cursor scale factor
@@ -386,6 +386,17 @@
         // Draw dynamic bodies
         if (settings.drawShapes) {
             for (bzBody b = world.bodyList; b; b = b.next) {
+                
+                if(b.userData) {
+                    bzVec2 center = b.position;
+                    auto state = cast(State) b.userData;
+                    vec2 avoid = vec2.from(state.avoid);
+                    gl.drawCircle(vec2.from(center), state.radius);
+                    if(avoid != vec2(0,0)) {
+                        gl.drawSegment(vec2.from(b.position), avoid, Color(0, 1, 0));
+                    }
+                }
+                
                 for (bzShape shape = b.shapeList; shape; shape = shape.next) {
 
                     bzShape s = shape;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ships/asteroids.d	Thu Mar 26 16:56:30 2009 -0400
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (c) 2009 Blaze Contributors http://www.dsource.org/projects/blaze
+ *  Maintained by Mason Green (zzzzrrr)
+ *
+ *   This software is provided 'as-is', without any express or implied
+ *   warranty. In no event will the authors be held liable for any damages
+ *   arising from the use of this software.
+ *
+ *   Permission is granted to anyone to use this software for any purpose,
+ *   including commercial applications, and to alter it and redistribute it
+ *   freely, subject to the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software
+ *   in a product, an acknowledgment in the product documentation would be
+ *   appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must not be
+ *   misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any source
+ *   distribution.
+ */
+module openmelee.ships.asteroids;
+
+import blaze.dynamics.bzBody : bzBody;
+import blaze.bzWorld: bzWorld;
+import blaze.dynamics.bzBodyDef;
+import blaze.collision.shapes.bzCircle : bzCircleDef;
+import blaze.collision.shapes.bzPolygon : bzPolyDef;
+import blaze.collision.shapes.bzShape : bzShapeDef;
+import blaze.common.bzMath: bzVec2, bzMul, bzXForm;
+import blaze.dynamics.forces.bzAttractor: bzAttractor;
+
+
+import openmelee.ai.utilities;
+
+const PI = 3.141593;
+
+class Asteroid
+{
+
+    bzBodyDef bd;
+    bzBody rBody;
+    bzShapeDef sd;
+
+    bzWorld world;
+
+    this(bzWorld world) {
+        this.world = world;
+        init();
+    }
+
+    void init() {
+        
+        float minRadius = 0.1;
+        float maxRadius = 10;
+        float strength = 0.5f;
+        bzVec2 center = bzVec2(0,0);
+
+		{
+		    float radius = 0.5f;
+            float density = 5.0f;
+			auto sd1 = new bzCircleDef(density, radius);
+			sd1.localPosition.set(-0.5f, 0.5f);
+
+            density = 0.0f;
+			auto sd2 = new bzCircleDef(density, radius);
+			sd2.localPosition.set(0.5f, 0.5f);
+
+			for (int i = 0; i < 5; ++i)
+			{
+				float x = randomRange(-100f, 100f);
+                float y = randomRange(-100f, 100f);
+				bzVec2 position = bzVec2(x , y);
+				float angle = randomRange(-PI, PI);
+				bd = new bzBodyDef(position, angle);
+				rBody = world.createBody(bd);
+				rBody.createShape(sd1);
+				rBody.createShape(sd2);
+				rBody.setMassFromShapes();
+                auto attractor = new bzAttractor(rBody, center, strength, minRadius, maxRadius);
+                world.addForce(attractor);
+                rBody.linearVelocity = bzVec2(x*20, y*20);
+			}
+		}
+
+		{
+			auto sd1 = new bzPolyDef();
+			sd1.setAsBox(0.25f, 0.5f);
+			sd1.density = 5.0f;
+
+			auto sd2 = new bzPolyDef();
+			sd2.setAsBox(0.25f, 0.5f, bzVec2(0.0f, -0.5f), 0.5f * PI);
+			sd2.density = 5.0f;
+
+			for (int i = 0; i < 5; ++i)
+			{
+				float x = randomRange(-100f, 100f);
+                float y = randomRange(-100f, 100f);
+				bzVec2 position = bzVec2(x , y);
+				float angle = randomRange(-PI, PI);
+				bd = new bzBodyDef(position, angle);
+				rBody = world.createBody(bd);
+				rBody.createShape(sd1);
+				rBody.createShape(sd2);
+				rBody.setMassFromShapes();
+                auto attractor = new bzAttractor(rBody, center, strength, minRadius, maxRadius);
+                world.addForce(attractor);
+                rBody.linearVelocity = bzVec2(x*20, y*20);
+			}
+		}
+
+		{
+			bzXForm xf1;
+			xf1.R.set(0.3524f * PI);
+			xf1.position = bzMul(xf1.R, bzVec2(1.0f, 0.0f));
+
+			auto sd1 = new bzPolyDef();
+			sd1.vertices.length = 3;
+			sd1.vertices[0] = bzMul(xf1, bzVec2(-1.0f, 0.0f));
+			sd1.vertices[1] = bzMul(xf1, bzVec2(1.0f, 0.0f));
+			sd1.vertices[2] = bzMul(xf1, bzVec2(0.0f, 0.5f));
+			sd1.density = 5.0f;
+
+			bzXForm xf2;
+			xf2.R.set(-0.3524f * PI);
+			xf2.position = bzMul(xf2.R, bzVec2(-1.0f, 0.0f));
+
+			auto sd2 = new bzPolyDef();
+			sd2.vertices.length = 3;
+			sd2.vertices[0] = bzMul(xf2, bzVec2(-1.0f, 0.0f));
+			sd2.vertices[1] = bzMul(xf2, bzVec2(1.0f, 0.0f));
+			sd2.vertices[2] = bzMul(xf2, bzVec2(0.0f, 0.5f));
+			sd2.density = 5.0f;
+
+			for (int i = 0; i < 5; ++i)
+			{
+				float x = randomRange(-100f, 100f);
+                float y = randomRange(-100f, 100f);
+				bzVec2 position = bzVec2(x , y);
+				float angle = 0.0f;
+				bd = new bzBodyDef(position, angle);
+				rBody = world.createBody(bd);
+				rBody.createShape(sd1);
+				rBody.createShape(sd2);
+				rBody.setMassFromShapes();
+                auto attractor = new bzAttractor(rBody, center, strength, minRadius, maxRadius);
+                world.addForce(attractor);
+                rBody.linearVelocity = bzVec2(x, y);
+			}
+		}
+	}
+}
--- a/ships/orz.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/ships/orz.d	Thu Mar 26 16:56:30 2009 -0400
@@ -91,6 +91,7 @@
         shapes.add(rBody.createShape(bWing));
 
         rBody.setMassFromShapes();
-        setPlanetGravity();
+        //setPlanetGravity();
+        calcRadius();
       }
 }
--- a/ships/planet.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/ships/planet.d	Thu Mar 26 16:56:30 2009 -0400
@@ -36,14 +36,20 @@
 import blaze.collision.shapes.bzCircle : bzCircleDef;
 import blaze.common.bzMath: bzVec2;
 
+import openmelee.ships.ship: State;
+
+
 class Planet 
 {
-    
     bzWorld world;
+    bzBody rBody;
     
     this(bzWorld world) {
         this.world = world;
         init();
+        auto state = new State;
+        state.radius = rBody.shapeList.sweepRadius;
+        rBody.userData = state;
     }
     
     void init() {
@@ -51,7 +57,7 @@
         bzVec2 position = bzVec2.zeroVect;
         float angle = 0.0f;
         auto bd = new bzBodyDef(position, angle);
-        auto rBody = world.createBody(bd);
+        rBody = world.createBody(bd);
         float radius = 7.0f;
         float density = 7.5f;
         auto sd = new bzCircleDef(density, radius);
--- a/ships/ship.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/ships/ship.d	Thu Mar 26 16:56:30 2009 -0400
@@ -41,7 +41,7 @@
 
 alias LinkedList!(bzShape) ShapeList;
 
-struct State 
+class State 
 {
 	bzVec2 position;
     bzVec2 velocity;
@@ -52,8 +52,10 @@
 	float speed = 0;
 	float maxForce = 0;
 	bool turn;
-	
-	float enemyAngle;
+    
+    float radius = 0.0f;
+	float enemyAngle = 0.0f;
+    bzVec2 avoid;
 	
 	bzVec2 predictFuturePosition(float dt) {
 	    return (position + velocity * dt);
@@ -71,16 +73,16 @@
     bzVec2 rightTurnPoint;
 	State state;
 	
-    float battery;
-    float crew;
+    float battery = 0.0f;
+    float crew = 0.0f;
     
     float maxLinVel = 50;
     float maxAngVel = 2;
     
     this(bzWorld world) {
-        
         this.world = world;
         shapes = new ShapeList;
+        state = new State;
     }
 
     void thrust() {
@@ -124,4 +126,13 @@
     	state.forward = engineForce.rotate(rBody.angle);
     }
     
+    void calcRadius() {
+        rBody.userData = state;
+        for (bzShape s = rBody.shapeList; s; s = s.next) {
+            if(s.sweepRadius > state.radius) {
+                state.radius = s.sweepRadius;
+            }
+        }
+    }
+    
 }
--- a/ships/urQuan.d	Thu Mar 26 07:02:56 2009 -0400
+++ b/ships/urQuan.d	Thu Mar 26 16:56:30 2009 -0400
@@ -118,6 +118,7 @@
         shapes.add(rBody.createShape(bWing));
 
         rBody.setMassFromShapes();
-        setPlanetGravity();
+        //setPlanetGravity();
+        calcRadius();
     }
 }