public Vector3 XXXSteerToEvadeAllDefenders() { // sum up weighted evasion Vector3 evade = Vector3.Zero; for (int i = 0; i < Globals.CtfEnemyCount; i++) { CtfEnemy e = Globals.CtfEnemies[i]; Vector3 eOffset = e.Position - Position; float eDistance = eOffset.Length(); // xxx maybe this should take into account e's heading? xxx float timeEstimate = 0.5f * eDistance / e.Speed; //xxx Vector3 eFuture = e.PredictFuturePosition(timeEstimate); // annotation annotation.CircleXZ(e.Radius, eFuture, Globals.EvadeColor, 20); // steering to flee from eFuture (enemy's future position) Vector3 flee = xxxSteerForFlee(eFuture); float eForwardDistance = Vector3.Dot(Forward, eOffset); float behindThreshold = Radius * -2; float distanceWeight = 4 / eDistance; float forwardWeight = ((eForwardDistance > behindThreshold) ? 1.0f : 0.5f); Vector3 adjustedFlee = flee * distanceWeight * forwardWeight; evade += adjustedFlee; } return(evade); }
public Vector3 SteerToEvadeAllDefenders() { Vector3 evade = Vector3.Zero; float goalDistance = Vector3.Distance(Globals.HomeBaseCenter, Position); // sum up weighted evasion for (int i = 0; i < Globals.CtfEnemyCount; i++) { CtfEnemy e = Globals.CtfEnemies[i]; Vector3 eOffset = e.Position - Position; float eDistance = eOffset.Length(); float eForwardDistance = Vector3.Dot(Forward, eOffset); float behindThreshold = Radius * 2; bool behind = eForwardDistance < behindThreshold; if ((!behind) || (eDistance < 5)) { if (eDistance < (goalDistance * 1.2)) //xxx { // const float timeEstimate = 0.5f * eDistance / e.speed;//xxx float timeEstimate = 0.15f * eDistance / e.Speed; //xxx Vector3 future = e.PredictFuturePosition(timeEstimate); annotation.CircleXZ(e.Radius, future, Globals.EvadeColor, 20); // xxx Vector3 offset = future - Position; Vector3 lateral = Vector3Helpers.PerpendicularComponent(offset, Forward); float d = lateral.Length(); float weight = -1000 / (d * d); evade += (lateral / d) * weight; } } } return(evade); }
// is there a clear path to the goal? public bool IsPathToGoalClear() { float sideThreshold = Radius * 8.0f; float behindThreshold = Radius * 2.0f; Vector3 goalOffset = Globals.HomeBaseCenter - Position; float goalDistance = goalOffset.Length(); Vector3 goalDirection = goalOffset / goalDistance; bool goalIsAside = IsAside(Globals.HomeBaseCenter, 0.5f); // for annotation: loop over all and save result, instead of early return bool xxxReturn = true; // loop over enemies for (int i = 0; i < Globals.CtfEnemyCount; i++) { // short name for this enemy CtfEnemy e = Globals.CtfEnemies[i]; float eDistance = Vector3.Distance(Position, e.Position); float timeEstimate = 0.3f * eDistance / e.Speed; //xxx Vector3 eFuture = e.PredictFuturePosition(timeEstimate); Vector3 eOffset = eFuture - Position; float alongCorridor = Vector3.Dot(goalDirection, eOffset); bool inCorridor = ((alongCorridor > -behindThreshold) && (alongCorridor < goalDistance)); float eForwardDistance = Vector3.Dot(Forward, eOffset); // xxx temp move this up before the conditionals annotation.CircleXZ(e.Radius, eFuture, Globals.ClearPathColor, 20); //xxx // consider as potential blocker if within the corridor if (inCorridor) { Vector3 perp = eOffset - (goalDirection * alongCorridor); float acrossCorridor = perp.Length(); if (acrossCorridor < sideThreshold) { // not a blocker if behind us and we are perp to corridor float eFront = eForwardDistance + e.Radius; //annotation.annotationLine (position, forward*eFront, gGreen); // xxx //annotation.annotationLine (e.position, forward*eFront, gGreen); // xxx // xxx // std::ostringstream message; // message << "eFront = " << std::setprecision(2) // << std::setiosflags(std::ios::fixed) << eFront << std::ends; // draw2dTextAt3dLocation (*message.str(), eFuture, gWhite); bool eIsBehind = eFront < -behindThreshold; bool eIsWayBehind = eFront < (-2 * behindThreshold); bool safeToTurnTowardsGoal = ((eIsBehind && goalIsAside) || eIsWayBehind); if (!safeToTurnTowardsGoal) { // this enemy blocks the path to the goal, so return false annotation.Line(Position, e.Position, Globals.ClearPathColor); // return false; xxxReturn = false; } } } } // no enemies found along path, return true to indicate path is clear // clearPathAnnotation (sideThreshold, behindThreshold, goalDirection); // return true; //if (xxxReturn) ClearPathAnnotation(sideThreshold, behindThreshold, goalDirection); return(xxxReturn); }