为什么我的碰撞检测不能正常工作?
Why is my collision detection not working properly?
我正在开发广为人知的游戏 Pong,我 运行 遇到了一些碰撞检测问题:球拍和球大部分时间会发生碰撞,但有时也会发生碰撞出现一个奇怪的问题:未检测到碰撞,因此,球落在球拍后面并且没有改变方向。我无法弄清楚问题隐藏在哪里。我们将不胜感激。
注意: 根据评论进行了编辑。
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));
}
}
在您的 checkCollision 方法中,您必须将 xVelocity 设置回正数。试试这个:
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);
}
}
}
这样想,如果球向左移动并击中球员,您希望它回到右侧。当它们向右移动时,X 坐标会上升,因此将 xvelocity 设置为负数会导致它继续穿过桨板,就好像它没有碰到它一样。
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);
}
}
}
你的问题就出在这里。在 Pong 中,您(玩家)只能将球击向另一侧;如果你在左边,你就会向右击球,反之亦然。因此,在任何碰撞之后,无论传入球的 y 速度如何,球的 x 速度应始终保持相同方向。但是,由于您根据球的 y 速度将 x 速度设置为不同的值,因此其中一种情况会导致球穿过球拍。
我正在开发广为人知的游戏 Pong,我 运行 遇到了一些碰撞检测问题:球拍和球大部分时间会发生碰撞,但有时也会发生碰撞出现一个奇怪的问题:未检测到碰撞,因此,球落在球拍后面并且没有改变方向。我无法弄清楚问题隐藏在哪里。我们将不胜感激。
注意: 根据评论进行了编辑。
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));
}
}
在您的 checkCollision 方法中,您必须将 xVelocity 设置回正数。试试这个:
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);
}
}
}
这样想,如果球向左移动并击中球员,您希望它回到右侧。当它们向右移动时,X 坐标会上升,因此将 xvelocity 设置为负数会导致它继续穿过桨板,就好像它没有碰到它一样。
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);
}
}
}
你的问题就出在这里。在 Pong 中,您(玩家)只能将球击向另一侧;如果你在左边,你就会向右击球,反之亦然。因此,在任何碰撞之后,无论传入球的 y 速度如何,球的 x 速度应始终保持相同方向。但是,由于您根据球的 y 速度将 x 速度设置为不同的值,因此其中一种情况会导致球穿过球拍。