/// <summary> /// Returns true if the ball is still where the shot anticipates it to be. /// First finds the two closest slices in the ball prediction to shot's intercept_time /// threshold controls the tolerance we allow the ball to be off by. /// </summary> public static bool ShotValid(GoslingAgent agent, IShotRoutine shot, float threshold = 45) { var slices = agent.GetBallPrediction().Slices; int soonest = 0; int latest = slices.Length - 1; // Porting note: the original code reads `while len(slices[soonest:latest+1]) > 2`. This seems to be a // contrived and less efficient way of just checking `while latest + 1 - soonest > 2`. while (latest + 1 - soonest > 2) { int midpoint = (soonest + latest) / 2; if (slices[midpoint].GameSeconds > shot.InterceptTime) { latest = midpoint; } else { soonest = midpoint; } } // Preparing to interpolate between the selected slices var dt = slices[latest].GameSeconds - slices[soonest].GameSeconds; var timeFromSoonest = shot.InterceptTime - slices[soonest].GameSeconds; var slopes = (slices[latest].Physics.Location - slices[soonest].Physics.Location) * (1 / dt); // Determining exactly where the ball will be at the given shot's intercept_time var predictedBallLocation = slices[soonest].Physics.Location + (slopes * timeFromSoonest); // Comparing predicted location with where the shot expects the ball to be return((shot.BallLocation - predictedBallLocation).Length() < threshold); }
public static float DefaultThrottle(GoslingAgent agent, float targetSpeed, float direction = 1) { var carSpeed = agent.Me.Local(agent.Me.Velocity).X; var t = targetSpeed * direction - carSpeed; agent.Controller.Throttle = Cap((float)Math.Pow(t, 2) * Sign(t) / 1000, -1, 1); agent.Controller.Boost = t > 150 && carSpeed < 2275 && agent.Controller.Throttle == 1; return(carSpeed); }
/// <summary> /// Points the car towards a given local target. /// Direction can be changed to allow the car to steer towards a target while driving backwards. /// </summary> public static (float, float, float) DefaultPd(GoslingAgent agent, Vector3 localTarget, float direction = 1) { localTarget *= direction; var up = agent.Me.Local(Vector3.UnitZ); (float, float, float)targetAngles = ( (float)Math.Atan2(localTarget.Z, localTarget.X), // angle required to pitch towards target (float)Math.Atan2(localTarget.Y, localTarget.X), // angle required to yaw towards target (float)Math.Atan2(up.Y, up.Z) // angle required to roll upright ); // Once we have the angles we need to rotate, we feed them into PD loops to determine the controller inputs. agent.Controller.Steer = SteerPd(targetAngles.Item2, 0) * direction; agent.Controller.Pitch = SteerPd(targetAngles.Item1, agent.Me.AngularVelocity.Y / 4); agent.Controller.Yaw = SteerPd(targetAngles.Item2, -agent.Me.AngularVelocity.Z / 4); agent.Controller.Roll = SteerPd(targetAngles.Item3, agent.Me.AngularVelocity.X / 2); // Returns the angles, which can be useful for other purposes return(targetAngles); }
/// <summary> /// FindHits takes a dict of (left, right) target pairs and finds routines that could hit the ball between those /// target pairs.<br/> /// FindHits is only meant for routines that require a defined intercept time/place in the future.<br/> /// FindHits should not be called more than once in a given tick, as it has the potential to use an entire tick /// to calculate.<br/> /// </summary> /// <remarks> /// Porting note: The above note that this method shouldn't be called frequently probably does not apply to C# /// as it's much faster than Python. /// </remarks> /// <example> /// Example usage: /// <code> /// var targets = new Dictionary<string, (Vector3, Vector3)> /// { /// {"goal", (opponentLeftPost, opponentRightPost)}, /// {"anywhereButMyNet", (myRightPost, myLeftPost)} /// } /// var hits = FindHits(agent, targets); /// hits == Dictionary<string, List<IRoutine>> /// { /// { "goal", List<IRoutine> { a ton of jump and aerial routines, in order from soonest to latest } }, /// { "anywhereButMyNet", List<IRoutine> { more routines and stuff } } /// } /// </code> /// </example> public static Dictionary <string, List <IRoutine> > FindHits( GoslingAgent agent, Dictionary <string, (Vector3, Vector3)> targets