// ---------------------- 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); }