Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
 /// <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&lt;string, (Vector3, Vector3)&gt;
 /// {
 ///     {"goal", (opponentLeftPost, opponentRightPost)},
 ///     {"anywhereButMyNet", (myRightPost, myLeftPost)}
 /// }
 /// var hits = FindHits(agent, targets);
 /// hits == Dictionary&lt;string, List&lt;IRoutine&gt;&gt;
 /// {
 ///     { "goal", List&lt;IRoutine&gt; { a ton of jump and aerial routines, in order from soonest to latest } },
 ///     { "anywhereButMyNet", List&lt;IRoutine&gt; { more routines and stuff } }
 /// }
 /// </code>
 /// </example>
 public static Dictionary <string, List <IRoutine> > FindHits(
     GoslingAgent agent,
     Dictionary <string, (Vector3, Vector3)> targets