// ---------------------- TimeToCoverDistance -----------------------------
  //
  // Given a force and a distance to cover given by two vectors, this
  // method calculates how long it will take the ball to travel between
  // the two points
  // ------------------------------------------------------------------------
  public double timeToCoverDistance(Vector2D A, Vector2D B, double force) {
    // this will be the velocity of the ball in the next time step *if*
    // the player was to make the pass.
    double speed = force / mass;

    // calculate the velocity at B using the equation
    //
    // v^2 = u^2 + 2as
    //
    // first calculate s (the distance between the two positions)
    double distanceToCover = vec2DDistance(A, B);

    double term = speed * speed + 2.0 * distanceToCover * Params.Instance().Friction;

    // if (u^2 + 2as) is negative it means the ball cannot reach point B.
    if (term <= 0.0) {
      return -1.0;
    }

    double v = Math.sqrt(term);

    // it IS possible for the ball to reach B and we know its speed when it
    // gets there, so now it's easy to calculate the time using the equation
    //
    // t = v-u
    // ---
    // a
    //
    return (v - speed) / Params.Instance().Friction;
  }
  // ----------------------------- Update -----------------------------------
  //
  // updates the ball physics, tests for any collisions and adjusts
  // the ball's velocity accordingly
  // ------------------------------------------------------------------------
  public void update(float tpf) {
    // keep a record of the old position so the goal::scored method
    // can utilize it for goal testing
    if (position != null) {
      oldPos.cloneVec(position);
    }
    // Test for collisions
    testCollisionWithWalls(pitchBoundary);

    // Simulate Params.Instance().Friction. Make sure the speed is positive
    // first though
    double friction = Params.Instance().Friction;
    // println (velocity)
    // println("LengthSq" + velocity.LengthSq() +" friction " + friction)
    if (velocity.LengthSq() > friction * friction) {
      velocity = velocity.plus(Vec2DNormalize(velocity).multiply(friction));
      // println (velocity)
      position = position.plus(velocity.multiply(tpf));
      // println (position)
      // update heading
      heading = Vec2DNormalize(velocity);
    }

    super.update(tpf);
  }
  // ----------------------------- AddNoiseToKick --------------------------------
  //
  // this can be used to vary the accuracy of a player's kick. Just call it
  // prior to kicking the ball using the ball's position and the ball target as
  // parameters.
  // -----------------------------------------------------------------------------
  public static Vector2D addNoiseToKick(Vector2D BallPos, Vector2D BallTarget) {
    double Pi = Utils.Pi;

    double displacement = (Pi - Pi * Params.Instance().PlayerKickingAccuracy) * RandomClamped();

    Vector2D toTarget = BallTarget.minus(BallPos);

    vec2DRotateAroundOrigin(toTarget, displacement);

    return toTarget.plus(BallPos);
  }
  // --------------------- FuturePosition -----------------------------------
  //
  // given a time this method returns the ball position at that time in the
  // future
  // ------------------------------------------------------------------------
  public Vector2D getFuturePosition(double time) {
    // using the equation s = ut + 1/2at^2, where s = distance, a = friction
    // u=start velocity

    // calculate the ut term, which is a vector
    Vector2D ut = velocity.multiply(time);

    // calculate the 1/2at^2 term, which is scalar
    double half_a_t_squared = 0.5 * Params.Instance().Friction * time * time;

    // turn the scalar quantity into a vector by multiplying the value with
    // the normalized velocity vector (because that gives the direction)
    Vector2D ScalarToVector = Vec2DNormalize(velocity).multiply(half_a_t_squared);

    // the predicted position is the balls position plus these two terms
    return getPos().plus(ut).plus(ScalarToVector);
  }