# HG changeset patch # User zzzzrrr # Date 1238100990 14400 # Node ID 4fce5596d1f6b838abf53a09f12769b81f812354 # Parent cad384ad349eea09eb0b3d6e3544b3c176286d9c ai work diff -r cad384ad349e -r 4fce5596d1f6 ai/ai.d --- 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(); } } diff -r cad384ad349e -r 4fce5596d1f6 ai/steer.d --- 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 diff -r cad384ad349e -r 4fce5596d1f6 melee/melee.d --- 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) diff -r cad384ad349e -r 4fce5596d1f6 openmelee.geany --- 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 diff -r cad384ad349e -r 4fce5596d1f6 render/render.d --- 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; diff -r cad384ad349e -r 4fce5596d1f6 ships/asteroids.d --- /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); + } + } + } +} diff -r cad384ad349e -r 4fce5596d1f6 ships/orz.d --- 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(); } } diff -r cad384ad349e -r 4fce5596d1f6 ships/planet.d --- 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); diff -r cad384ad349e -r 4fce5596d1f6 ships/ship.d --- 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; + } + } + } + } diff -r cad384ad349e -r 4fce5596d1f6 ships/urQuan.d --- 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(); } }