/// <summary>
        /// Passes the ball to the cursor by rolling it around the ground
        /// The ball's velocity at arrival is given by Constants.ShortPassDesiredVelocityAtArrival.
        /// </summary>
        private void KickShortPass()
        {
            // NOTE: Works, but isn't optimized. Fix as necessary.

            // Take cursor location and obtain the vector pointing toward (relative to the position of the ball).
            Coords   clicked       = PixelUnderMousecursor();
            Vector3d clickedVector = new Vector3d(clicked.X, clicked.Y, 0);
            Vector2d test0         = new Vector2d(clicked.X - _ball.Position3d.X, clicked.Y - _ball.Position3d.Y);

            // Proximity check.
            if (test0.Length() < Constants.TargetCheckTolerance)
            {
                // target too close. just nudge the ball.
                _ball.Kick(new Vector3d(test0.X, test0.Y, 0), Constants.ShortPassDefaultSpin, null);
            }

            // Scale velocity vector
            test0.ScaleToLength(1);

            // NOTE:
            // The calibration works as follows:
            // We start with a velocity vector of magnitude 1 aimed in the correct direction.
            // We obtain the magnitude of the ball's velocity at arrival at the target (0 = didn't arrive).
            // We scale the velocity vector as necessary. The scaling is linear, defined by Constants.ShortPassCalibrationSensitivity.
            // If the target is too far, we use the Constants.ShortPassMaxVelocity loop stopping condition.
            // WARMING: This algo assumes the ShortPassDefaultSpin is 0. With spin, once has to alter the algo
            // in a way similar to the alteration for the Lob calibration.

            // Definet he calibrator ball and its helper variables, and do the first cycle of the loop
            BallCalibrator calibrator = new BallCalibrator(_ball);

            calibrator.Kick(new Vector3d(test0.X, test0.Y, 0), Constants.ShortPassDefaultSpin);
            double testResult = calibrator.VelocityMagnitudeAtTarget(clickedVector);
            double difference = this._shotPower - testResult;
            double length     = test0.Length();

            // Loop until the desired velocity has been found.
            while (difference > Constants.ShortPassDesiredVelocityAtArrivalTolerance &&
                   length < Constants.ShortPassMaxVelocity)
            {
                calibrator.SpawnAt(new Vector2d(_ball.Position3d.X, _ball.Position3d.Y));
                length = test0.Length();
                test0.ScaleToLength(test0.Length() + Constants.ShortPassCalibrationSensitivity);
                calibrator.Kick(new Vector3d(test0.X, test0.Y, 0), Constants.ShortPassDefaultSpin);
                testResult = calibrator.VelocityMagnitudeAtTarget(clickedVector);
                difference = this._shotPower - testResult;
            }

            // Kick ball.
            _ball.Kick(new Vector3d(test0.X, test0.Y, 0), Constants.ShortPassDefaultSpin, null);
        }
        /// <summary>
        /// Projects the ball's travel path until stopping.
        /// </summary>
        private void ConstructProjection()
        {
            // clear old projection
            _projection.Clear();

            BallCalibrator calibrator = new BallCalibrator(this);

            calibrator.Kick(this._velocity, new Vector3d(0, 0, 0));
            calibrator.Spin3d = _spin3d; // to bypass the spin realignment. do this more cleverly later.

            int j = 0;

            while (calibrator.Velocity.Length() > 0 && j < Constants.ProjectionMaxLength)
            {
                calibrator.UpdateMotion3D();

                _projection.Add(calibrator.Position3d);
                ++j;
            }

            _projection.Reverse();
        }
Example #3
0
        /// <summary>
        /// Lobs the ball so it bounces at the cursor. Spin is defined by Constants.LobDefaultSpin.
        /// </summary>
        private void KickLob(Ball ball, Vector3d target, Vector3d spinner)
        {
            Vector3d spin = new Vector3d(0, spinner.Y, spinner.Z);
            //Vector3d spin = Constants.LobDefaultSpin;

            Vector3d clickedVector    = new Vector3d(target.X, target.Y, 0);
            Vector2d test0            = new Vector2d(target.X - ball.Position3d.X, target.Y - ball.Position3d.Y);
            double   distanceToTarget = test0.Length();

            // Proximity check.
            if (distanceToTarget < Constants.TargetCheckTolerance)
            {
                // target too close. just nudge the ball.
                ball.Kick(new Vector3d(test0.X, test0.Y, Constants.LobLiftCoefficient * test0.Length()), spin, _owner);
            }

            // Scale velocity vector
            test0.ScaleToLength(1);

            // NOTE:
            // The calibration works as follows:
            // We start with a velocity vector of magnitude 1 aimed toward the goal.
            // We obtain the position where the ball bounces.
            // We compare the distance to bounce with the distance to target.
            // We scale the velocity vector as necessary. The scaling is linear, defined by Constants.ShortPassCalibrationSensitivity.
            // If the target is too far, we use the Constants.ShortPassMaxVelocity loop stopping condition.
            // After we have the desired kick strength, we rotate the kick vector to align the bounce position with the target.

            // Definet he calibrator ball and its helper variables, and do the first cycle of the loop
            BallCalibrator calibrator = new BallCalibrator(ball);

            calibrator.Kick(new Vector3d(test0.X, test0.Y, Constants.LobLiftCoefficient * test0.Length()), spin);
            Vector3d landing           = calibrator.BallPositionAtBounce();
            Vector3d vectorToLanding   = landing - ball.Position3d;
            double   distanceMagnitude = vectorToLanding.Length();

            double difference = distanceMagnitude - distanceToTarget;

            // Loop until the desired velocity has been found.
            while (Math.Abs(difference) > Constants.LobTargetCheckTolerance &&
                   test0.Length() < Constants.LobMaxVelocity)
            {
                calibrator.SpawnAt(new Vector2d(ball.Position3d.X, ball.Position3d.Y));
                //length = difference.Length();
                test0.ScaleToLength(test0.Length() + Constants.LobCalibrationSensitivity);
                calibrator.Kick(new Vector3d(test0.X, test0.Y, Constants.LobLiftCoefficient * test0.Length()), spin);
                landing           = calibrator.BallPositionAtBounce();
                vectorToLanding   = landing - ball.Position3d;
                distanceMagnitude = vectorToLanding.Length();
                difference        = distanceMagnitude - distanceToTarget;
            }

            // If necessary, rotate to align with target.
            if (spin.Z != 0)
            {
                double angleOfRotation = (new Vector2d(landing.X - ball.Position3d.X, landing.Y - ball.Position3d.Y)).
                                         AngleBetween(new Vector2d(clickedVector.X - ball.Position3d.X, clickedVector.Y - ball.Position3d.Y));
                test0 = test0.Rotate(angleOfRotation);
            }

            // Kick the ball.
            _owner.KickBall(new Vector3d(test0.X, test0.Y, Constants.LobLiftCoefficient * test0.Length()), spin);
        }