/// <summary> /// Calculates the required acceleration to arrive at a location in a given amount of time. /// </summary> /// <param name="car">The car to use in the calculation.</param> /// <param name="target">The target location for the aerial.</param> /// <param name="time">The time allowed to complete the aerial.</param> /// <returns></returns> public static Vector3 CalculateCourse(Car car, Vector3 target, float time) { Vector3 z = Vector3.UnitZ; Vector3 P = target; Vector3 x0 = car.Position; Vector3 v0 = car.Velocity; float delta_t = time; if (car.HasWheelContact) { v0 += car.Up * jump_dv; x0 += car.Up * jump_dx; } float g = -650.0f; float a = 9.0f; Vector3 A = P - x0 - v0 * delta_t - 0.5f * g * delta_t * delta_t * z; Vector3 dir = Vector3.Normalize(A); // estimate the time required to turn float phi = MathUtility.Angle(car.Rotation, MathUtility.LookAt(dir, car.Up)); float T = (float)(0.7 * (2.0 * Math.Sqrt(phi / a))); // see if the boost acceleration needed to reach the target is achievable return(dir * 2.0f * A.Length() / ((delta_t - T) * (delta_t - T))); }
public Controller Step(Ball ball, float dt, float currentTime) { float delta_t = ArrivalTime - currentTime; Vector3 A = CalculateCourse(Car, Target, delta_t); Controller c = new Controller(); Vector3 dir = Vector3.Normalize(A); if (doubleJump != null && !doubleJump.Finished) { c = doubleJump.Step(); } else { Quaternion t; Vector3 predicted = Car.Position + Car.Velocity * delta_t + 0.5f * -650f * delta_t * delta_t * Vector3.UnitZ; if ((predicted - Target).Length() > 50) { t = MathUtility.LookAt(dir, Car.Up); } else { Vector3 d = ball.Position - Car.Position; Vector3 r = new Vector3(d.Y, -d.X, 0); t = MathUtility.LookAt(Vector3.Normalize(Vector3.Cross(d, r)), -Vector3.Normalize(d)); } Vector3 inputs = RotationController.GetInputs(Car, t, dt); c.Roll = inputs.X; c.Pitch = inputs.Y; c.Yaw = inputs.Z; if (MathUtility.Angle(Car.Rotation, MathUtility.LookAt(dir, Car.Up)) < 0.4f) { c.Boost = true; } if (Car.CanDodge) { Finished = true; } } if (currentTime > ArrivalTime) { Finished = true; } return(c); }
public Controller Step(Ball ball, float dt, float currentTime) { Vector3 A = CalculateCourse(Car, Target, ArrivalTime - currentTime); Controller c = new Controller(); Vector3 dir = Vector3.Normalize(A); if (doubleJump != null && !doubleJump.Finished) { c = doubleJump.Step(); } else { Quaternion t; Car test = new Car(Car); for (int i = 0; i < (int)((ArrivalTime - currentTime) / 0.016667f); i++) { test.Simulate(new Controller(), 0.016667f); } if ((Target - test.Position).Length() > 120) { t = MathUtility.LookAt(dir, Car.Up); } else { t = MathUtility.LookAt(Vector3.Normalize(ball.Position - Car.Position), Car.Up); } Vector3 inputs = RotationController.GetInputs(Car, t, dt); c.Roll = inputs.X; c.Pitch = inputs.Y; c.Yaw = inputs.Z; if (MathUtility.Angle(Car.Rotation, MathUtility.LookAt(dir, Car.Up)) < 0.4f) { c.Boost = true; } } if (currentTime > ArrivalTime || A.Length() > 1050) { Finished = true; } return(c); }