# HG changeset patch # User zzzzrrr # Date 1238114158 14400 # Node ID e79347dd38a394acfba92c2eb78a937abadc8081 # Parent 4fce5596d1f6b838abf53a09f12769b81f812354 steering diff -r 4fce5596d1f6 -r e79347dd38a3 ai/ai.d --- 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(); diff -r 4fce5596d1f6 -r e79347dd38a3 ai/steer.d --- 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; } } diff -r 4fce5596d1f6 -r e79347dd38a3 melee/melee.d --- 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( { diff -r 4fce5596d1f6 -r e79347dd38a3 openmelee.geany --- 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