private void ComputeHorizontalMovement(ref VelocityCurve velocityCurve,
                                                   ref SideScrollingCharacterController sideScrollingCharacterController,
                                                   [ReadOnly] ref SolidAgent solidAgent)
            {
                //Check for hitting a wall you're moving towards
                if (((velocityCurve.X.CurrentVelocity < 0.0f) &&
                     (solidAgent.IsLeftWallCollided))

                    ||

                    ((velocityCurve.X.CurrentVelocity > 0.0f) &&
                     (solidAgent.IsRightWallCollided)))
                {
                    //We hit a wall.
                    //Reduce our current X velocity to zero
                    velocityCurve.X.CurrentVelocity = 0.0f;
                }

                //Move based on the movement input
                if (MovementInput.x == 0.0f)
                {
                    //The player isn't holding any direction.
                    //In the air, do nothing.
                    //On the ground, skid to a halt
                    if (solidAgent.IsGroundCollided)
                    {
                        velocityCurve.X = VelocityCurveAxis.Quadratic(velocityCurve.X.CurrentVelocity,
                                                                      velocityCurve.X.CurrentVelocity < 0.0f,
                                                                      sideScrollingCharacterController.WalkingAbsoluteDeceleration,
                                                                      0.0f);
                    }
                }
                else
                {
                    //Moving left and right
                    //Check if we're moving with the momentum or against it
                    if (((MovementInput.x > 0.0f) &&
                         (velocityCurve.X.CurrentVelocity < 0.0f))

                        ||

                        ((MovementInput.x < 0.0f) &&
                         (velocityCurve.X.CurrentVelocity > 0.0f)))
                    {
                        //The player is skidding back towards zero velocity
                        velocityCurve.X = VelocityCurveAxis.Quadratic(velocityCurve.X.CurrentVelocity,
                                                                      MovementInput.x > 0.0f,
                                                                      sideScrollingCharacterController.SkiddingAbsoluteDeceleration,
                                                                      0.0f);
                    }
                    else
                    {
                        //The player is accelerating towards maximum velocity
                        velocityCurve.X = VelocityCurveAxis.Quadratic(velocityCurve.X.CurrentVelocity,
                                                                      MovementInput.x > 0.0f,
                                                                      sideScrollingCharacterController.WalkingAbsoluteAcceleration,
                                                                      sideScrollingCharacterController.WalkingAbsoluteMaximumVelocity);
                    }
                }
            }
            public void Execute(ref VelocityCurve velocityCurve, ref WindController windController)
            {
                //The wind never blows on the Z axis
                velocityCurve.Z = VelocityCurveAxis.Zero();

                //Turn the wind on and off
                windController.ElapsedTime += DeltaTime;

                if (windController.IsBlowing &&
                    (windController.ElapsedTime > windController.OnTime))
                {
                    //Turn the wind off.
                    windController.IsBlowing   = false;
                    windController.ElapsedTime = 0.0f;

                    velocityCurve.X = VelocityCurveAxis.Quadratic(velocityCurve.X.CurrentVelocity,
                                                                  windController.WindDirection.x < 0.0f,
                                                                  windController.WindAbsoluteDeceleration * math.abs(windController.WindDirection.x),
                                                                  0.0f);

                    velocityCurve.Y = VelocityCurveAxis.Quadratic(velocityCurve.Y.CurrentVelocity,
                                                                  windController.WindDirection.y < 0.0f,
                                                                  windController.WindAbsoluteDeceleration * math.abs(windController.WindDirection.y),
                                                                  0.0f);
                }
                else if (!windController.IsBlowing &&
                         (windController.ElapsedTime > windController.OffTime))
                {
                    //Turn the wind on.
                    windController.IsBlowing   = true;
                    windController.ElapsedTime = 0.0f;

                    velocityCurve.X = VelocityCurveAxis.Quadratic(velocityCurve.X.CurrentVelocity,
                                                                  windController.WindDirection.x > 0.0f,
                                                                  windController.WindAbsoluteDeceleration * math.abs(windController.WindDirection.x),
                                                                  windController.WindAbsoluteMaximumVelocity * math.abs(windController.WindDirection.x));

                    velocityCurve.Y = VelocityCurveAxis.Quadratic(velocityCurve.Y.CurrentVelocity,
                                                                  windController.WindDirection.y > 0.0f,
                                                                  windController.WindAbsoluteDeceleration * math.abs(windController.WindDirection.y),
                                                                  windController.WindAbsoluteMaximumVelocity * math.abs(windController.WindDirection.y));
                }
            }
            private void ComputeVerticalMovement(ref VelocityCurve velocityCurve,
                                                 ref SideScrollingCharacterController sideScrollingCharacterController,
                                                 [ReadOnly] ref SolidAgent solidAgent)
            {
                //Check if we're grounded
                if (solidAgent.IsGroundCollided)
                {
                    //We're grounded.
                    //Reset jumping and falling flags
                    sideScrollingCharacterController.IsJumping  = false;
                    sideScrollingCharacterController.IsFalling  = false;
                    sideScrollingCharacterController.IsJumpHeld = false;

                    //Check if we want to jump
                    if (IsJumpPressedThisFrame)
                    {
                        sideScrollingCharacterController.IsJumping  = true;
                        sideScrollingCharacterController.IsJumpHeld = true;

                        velocityCurve.Y = VelocityCurveAxis.Quadratic(sideScrollingCharacterController.JumpAbsoluteVelocity,
                                                                      false,
                                                                      sideScrollingCharacterController.JumpAbsoluteDeceleration,
                                                                      sideScrollingCharacterController.TerminalVelocity);
                    }
                    else
                    {
                        //While grounded, continue to push down on the ground an amount
                        //equal to a single step off acceleration
                        velocityCurve.Y = VelocityCurveAxis.Linear(false,
                                                                   sideScrollingCharacterController.FallingAbsoluteAcceleration * DeltaTime);
                    }
                }
                else
                {
                    //Check for hitting your head on the ceiling
                    if ((velocityCurve.Y.CurrentVelocity > 0.0f) &&
                        (solidAgent.IsCeilingCollided))
                    {
                        //Cancel the jump and reduce velocity to zero
                        velocityCurve.Y.CurrentVelocity             = 0.0f;
                        sideScrollingCharacterController.IsJumpHeld = false;
                    }

                    //Differentiate between jumping and falling
                    if (!IsJumpPressedThisFrame)
                    {
                        sideScrollingCharacterController.IsJumpHeld = false;
                    }

                    //Did the player let go of jump?
                    if (sideScrollingCharacterController.IsJumping && !sideScrollingCharacterController.IsJumpHeld)
                    {
                        sideScrollingCharacterController.IsJumping = false;
                    }

                    //Check if we should start falling
                    if (!sideScrollingCharacterController.IsJumping && !sideScrollingCharacterController.IsFalling)
                    {
                        //Start Falling
                        sideScrollingCharacterController.IsFalling = true;

                        velocityCurve.Y = VelocityCurveAxis.Quadratic(velocityCurve.Y.CurrentVelocity,
                                                                      false,
                                                                      sideScrollingCharacterController.FallingAbsoluteAcceleration,
                                                                      sideScrollingCharacterController.TerminalVelocity);
                    }
                }
            }