1
votes

I'm creating the widly-known game Pong and I ran into some collision detection problems: the paddle and the ball collide most of the times but sometimes an odd issue occurs: the collision isn't detected and because of that, the ball gets behind the paddle and not change direction. I can't figure out where's the problem hiding. Any and all help would be appreciated.

Note: edited due to a comment.

GamePanel.java

public class GamePanel extends JPanel implements ActionListener, KeyListener {

    Ball ball = new Ball();
    Player player = new Player();

    private void update() {
        checkCollision();
    }

    @Override
    public void actionPerformed(ActionEvent a) {
        update();
    }

    public void checkCollision() {
        Rectangle playerRect = player.bounds();
        Rectangle ballRect = ball.bounds();
        if (playerRect.intersects(ballRect)) {
            if (ball.getyVelocity() < 0) {
                ball.setxVelocity(5);
                ball.setyVelocity(-5);
            } else if (ball.getyVelocity() > 0) {
                ball.setxVelocity(-5);
                ball.setyVelocity(5);
            }
        }
    }

}

Ball.java

public class Ball {

    private final int RADIUS = 15;
    private final int DIAMETER = RADIUS * 2;

    private int x_pos = 250;
    private int y_pos = 250;

    private int xVelocity = -5;
    private int yVelocity = -5;

    public void update() {
        x_pos += xVelocity;
        y_pos += yVelocity;

        if (x_pos <= 0 + RADIUS) {
            xVelocity = 5;
        } else if (x_pos >= Pong.WINDOW_WIDTH - (5 + RADIUS)) {
            xVelocity = -5;
        }

        if (y_pos <= 0 + RADIUS) {
            yVelocity = 5;
        } else if (y_pos >= Pong.WINDOW_HEIGHT - (15 + DIAMETER)) {
            yVelocity = -5;
        }
    }

    public void paint(Graphics g) {
        g.setColor(Color.white);
        g.fillOval(x_pos - RADIUS, y_pos - RADIUS, DIAMETER, DIAMETER);
    }

    public Rectangle bounds() {
        return (new Rectangle(x_pos - RADIUS, y_pos - RADIUS, DIAMETER, DIAMETER));
    }

    public int getxVelocity() {
        return xVelocity;
    }

    public int getyVelocity() {
        return yVelocity;
    }

    public void setxVelocity(int xVelocity) {
        this.xVelocity = xVelocity;
    }

    public void setyVelocity(int yVelocity) {
        this.yVelocity = yVelocity;
    }

}

Player.java

public class Player {

    private final int WIDTH = 15;
    private final int HEIGHT = 150;

    private final int X_POS = 5 + WIDTH / 2;

    private int y_pos = Pong.WINDOW_HEIGHT / 2 - HEIGHT / 2;

    private int yVelocity = 0;

    public void update() {
        y_pos += yVelocity;

        if (y_pos < 0 + HEIGHT / 2) {
            y_pos = 0 + HEIGHT / 2;
        } else if (y_pos > Pong.WINDOW_HEIGHT - 25 - HEIGHT / 2) {
            y_pos = Pong.WINDOW_HEIGHT - 25 - HEIGHT / 2;
        }
    }

    public void paint(Graphics g) {
        g.setColor(Color.white);
        g.fillRect(X_POS, y_pos - HEIGHT / 2, WIDTH, HEIGHT);
    }

    public int getyVelocity() {
        return yVelocity;
    }

    public void setyVelocity(int yVelocity) {
        this.yVelocity = yVelocity;
    }

    public int getY_pos() {
        return y_pos;
    }

    public void setY_pos(int y_pos) {
        this.y_pos = y_pos;
    }

    public int getX_POS() {
        return X_POS;
    }

    public int getWIDTH() {
        return WIDTH;
    }

    public int getHEIGHT() {
        return HEIGHT;
    }

    public Rectangle bounds() {
        return (new Rectangle(X_POS, y_pos - HEIGHT / 2, WIDTH, HEIGHT));
    }

}
2
Ugh. So much code to go through. Can you not just post the relevant code? - RaminS
@Gendarme As you wish. - user6258402

2 Answers

2
votes

In your checkCollision method, you have to set the xVelocity back to a positive number. Try this:

public void checkCollision() {
      Rectangle playerRect = player.bounds();
      Rectangle ballRect = ball.bounds();
      if (playerRect.intersects(ballRect)) {
          if (ball.getyVelocity() < 0) {
            ball.setxVelocity(5);
            ball.setyVelocity(-5);
        } else if (ball.getyVelocity() > 0) {
            ball.setxVelocity(5);
            ball.setyVelocity(5);
        }
    }
}

Think about it this way, if the ball is going left and hits the player, you want it to go back to the right. X coordinates go up as they go to the right, so setting the xvelocity to a negative number results in it keep moving through the paddle as if it is not touching it.

0
votes
public void checkCollision() {
    Rectangle playerRect = player.bounds();
    Rectangle ballRect = ball.bounds();
    if (playerRect.intersects(ballRect)) {
        if (ball.getyVelocity() < 0) {
            ball.setxVelocity(5); <-- these should be the same value
            ball.setyVelocity(-5);
        } else if (ball.getyVelocity() > 0) {
            ball.setxVelocity(-5); <-- these should be the same value
            ball.setyVelocity(5);
        }
    }
}

Your problem lies here. In Pong, you (the player) only ever hit the ball away towards the opposite side; if you're on the left, you hit towards the right, and vice versa. So therefore, after any collision, the x velocity of the ball should always be in the same direction, regardless of the y velocity of the incoming ball. However, since you are setting the x velocity to different values based on the ball's y velocity, one of these cases will cause the ball to pass through the paddle instead.