1

I have written code that should form the basis for a simple Pong game. It works, but I don't understand why. It should not work. I'm hoping somebody can give me the insight I'm missing as to why it does work.

I have the following concept in my canvas (which has (0,0) on the top left):

A ball always bounces in an angle between 0 and 180 degrees. I have taken the bottom of my canvas as the basis. Left is 0 degrees, right is 180 degrees. If it bounces on a wall the ball's angle (ball_angle) changes to 180 - ball_angle degrees. A ball's trajectory is defined by 2 more variables (x_traj and y_traj) indicating the direction on each axis.

The part I don't get is the ballHits() method. If the ball is hitting the cealing, coming from the right with a degree of e.g. 100, then it should bounce off at a degree of 80. The ball is coming from the right so the x_traj is negative. We are bouncing on the cealing so the ball drops instead of lifts, ergo we change the y_traj from negative (lifting) to positive (dropping). The ball will still be going to the right, so we leave that direction in tact.

Second scenario is when the ball hits the left wall. The ball is coming from the right again, so we know that traj_x is negative. We bounce off so the ball goes back to the right, ergo traj_x should be multiplied by -1 to make it positive again (move to the right). Wether we hit the wall coming from above or below, we are still going that same direction after bouncing of the wall. We don't change the traj_y variable.

However, below is the working code. I do not have to change any variable when I hit the left or right wall. Could somebody explain to me why?

If needed, the full compiling project can be found on GitHub.

Code to move the ball to new coordinates:

private void updateBall()
{
    // http://gamedev.stackexchange.com/questions/73593/calculating-ball-trajectory-in-pong
    // If the ball is not hitting anything, we simply move it.
    // http://en.wikipedia.org/wiki/Polar_coordinate_system
    if (ballHits())
    {
        // Bounce the ball off the wall.
        ball_angle = 180 - ball_angle;
    }
    // http://en.wikipedia.org/wiki/Polar_coordinate_system
    // Convert the angle to radians.
    double angle = (ball_angle * Math.PI) / 180;

    // Calculate the next point using polar coordinates.
    ball_x = ball_x + (int) (x_traj * BALL_STEPSIZE * Math.cos(angle));
    ball_y = ball_y + (int) (y_traj * BALL_STEPSIZE * Math.sin(angle));
    System.out.printf("Ball: (%d,%d) @ %d\n", ball_x, ball_y, ball_angle);
}

Code that determines if we have hit a wall:

private boolean ballHits()
{
    // If we came out of bounds just reset it.
    ball_y = Math.max(0,  ball_y);
    ball_x = Math.max(0,  ball_x);
    // Check to see if it hits any walls.
    // Top
    if(ball_y <= 0)
    {
        System.out.println("Collision on top");
        y_traj *= -1;
        x_traj *= -1;
        return true;
    }
    // Left
    if(ball_x <= 0)
    {
        System.out.println("Collision on left");
        //y_traj *= -1;
        //x_traj *= -1;
        return true;
    }
    // Right
    if(ball_x >= B_WIDTH)
    {
        System.out.println("Collision on right");
        //y_traj *= -1;
        //x_traj *= -1;
        return true;
    }
    // Bottom
    if(ball_y >= B_HEIGHT)
    {
        System.out.println("Collision on bottom");
        y_traj *= -1;
        x_traj *= -1;
        return true;
    }
    return false;
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Christophe De Troyer
  • 2,852
  • 3
  • 30
  • 47

1 Answers1

2

Well it's working in a tricky way because cosine goes negative when your angle is > 90°. Making him start with a different initial trajectory and angle should not work if the ball hits the bottom or top first.

Edit : I thought it would do that but doing it on paper proves me wrong, well it's a weird way to do it but it's working as intended. I'll investigate to find if there's a way it doesn't work.

Edit 2 : Does a start angle in range of [88-92] work ?

StairZ
  • 66
  • 5
  • Hmm, I have tried to make it bounce in angles > and < 90° on the top first and bottom first but it does seem to work fine. But I do understand that it comes from the cosine. However, I'll have reproduce some scenarios on paper. – Christophe De Troyer Aug 27 '14 at 09:45
  • I edited my answer, could you tell me if that works ? – StairZ Aug 27 '14 at 13:16
  • Yes, that works perfectly. Kind of odd. But, I'm wondering, what would be the idiomatic way to do it then? – Christophe De Troyer Aug 27 '14 at 15:49
  • 1
    Well you could go with only angles and get the trajectory changes with their signe but that would mean you have to rethink your range of angles [0-180] isn't enough and you need a range of [0-360], you can also keep your trajectories and put an abs() on cosine. For the angles you'd have to put an offset determined by the side the ball just hits, it might be, 90° for RIGHT, 180° for TOP, 270° for LEFT and 0 for BOTTOM, you won't have to bother with x_traj and y_traj anymore. – StairZ Aug 28 '14 at 11:54