// ---------------------------------------------------------------------------- // evasion of another vehicle public Vector3 steerForEvasion(AbstractVehicle menace, float maxPredictionTime) { // offset from this to menace, that distance, unit vector toward menace Vector3 offset = menace.Position - Position; float distance = offset.magnitude; float roughTime = distance / menace.Speed(); float predictionTime = ((roughTime > maxPredictionTime) ? maxPredictionTime : roughTime); Vector3 target = menace.PredictFuturePosition(predictionTime); return(steerForFlee(target)); }
public Vector3 steerForPursuit(AbstractVehicle quarry, float maxPredictionTime) { // offset from this to quarry, that distance, unit vector toward quarry Vector3 offset = quarry.Position - Position; float distance = offset.magnitude; Vector3 unitOffset = offset / distance; // how parallel are the paths of "this" and the quarry // (1 means parallel, 0 is pependicular, -1 is anti-parallel) float parallelness = Vector3.Dot(Forward(), quarry.Forward()); // how "forward" is the direction to the quarry // (1 means dead ahead, 0 is directly to the side, -1 is straight back) float forwardness = Vector3.Dot(Forward(), unitOffset); float directTravelTime = distance / Speed(); int f = intervalComparison(forwardness, -0.707f, 0.707f); int p = intervalComparison(parallelness, -0.707f, 0.707f); float timeFactor = 0; // to be filled in below Vector3 color = OpenSteerColours.gBlack; // to be filled in below (xxx just for debugging) // Break the pursuit into nine cases, the cross product of the // quarry being [ahead, aside, or behind] us and heading // [parallel, perpendicular, or anti-parallel] to us. switch (f) { case +1: switch (p) { case +1: // ahead, parallel timeFactor = 4; color = OpenSteerColours.gBlack; break; case 0: // ahead, perpendicular timeFactor = 1.8f; color = OpenSteerColours.gGray50; break; case -1: // ahead, anti-parallel timeFactor = 0.85f; color = OpenSteerColours.gWhite; break; } break; case 0: switch (p) { case +1: // aside, parallel timeFactor = 1; color = OpenSteerColours.gRed; break; case 0: // aside, perpendicular timeFactor = 0.8f; color = OpenSteerColours.gYellow; break; case -1: // aside, anti-parallel timeFactor = 4; color = OpenSteerColours.gGreen; break; } break; case -1: switch (p) { case +1: // behind, parallel timeFactor = 0.5f; color = OpenSteerColours.gCyan; break; case 0: // behind, perpendicular timeFactor = 2; color = OpenSteerColours.gBlue; break; case -1: // behind, anti-parallel timeFactor = 2; color = OpenSteerColours.gMagenta; break; } break; } // estimated time until intercept of quarry float et = directTravelTime * timeFactor; // xxx experiment, if kept, this limit should be an argument float etl = (et > maxPredictionTime) ? maxPredictionTime : et; // estimated position of quarry at intercept Vector3 target = quarry.PredictFuturePosition(etl); // annotation annotationLine(Position, target, gaudyPursuitAnnotation ? color : OpenSteerColours.gGray40); return(steerForSeek(target)); }