Java 编程、突破游戏球物理未按预期运行
Java programming, breakout game ball physics not behaving as expected
我正在学习 java 本书 "The Art and Science of Java: An Introduction to Computer Science"。练习程序之一是创建 Breakout 游戏的简单克隆。
我目前可以加载游戏,但球的物理特性存在问题。我正在使用最简单的物理学,但看不出为什么它不起作用。
当球撞到墙上时,它会正常反弹,但当它撞到球拍或砖块时,它不会反弹。我在碰撞检测中使用相同的代码来改变我在墙壁上使用的方向。检测到碰撞,我添加了一个 println 并观察了控制台,因为它经历了碰撞事件,但没有发生方向变化。
package chapter10;
/*
* This program creates a clone of the classic Breakout Game,
* where a player bounces a ball with a paddle to "break" bricks
* along the top of the screen.
*
* Controls: Left: left button, Right: right button
*/
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.RepaintManager;
import javax.swing.Timer;
import acm.program.*;
import acm.graphics.*;
public class BreakoutClone extends GraphicsProgram {
/* components */
private GRect paddle;
private GRect brick;
private GOval ball;
/* static variables */
private static final double PADDLE_HEIGHT = 5;
private static final double BALL_SPEED = 2;
private static final double PADDLE_SPEED = 2;
private static final double ROWS_BRICKS = 6;
private static final double COLUMNS_BRICKS = 10;
private static final double TOP_GAP = 50;
/* variables */
private int numTurns = 3;
private double paddleWidth = 50;
private int dx = 2;
private int dy = 2;
public void init() {
setSize(700, 600);
paddle = new GRect(0, getHeight() - 30, paddleWidth, PADDLE_HEIGHT);
paddle.setFilled(true);
add(paddle);
addBricks();
ball = new GOval(getWidth() / 2, 175, 5, 5);
ball.setFilled(true);
add(ball);
}
public void run() {
animateBall();
// TODO animate paddle
}
public void addBricks() {
double gap = 20;
double brickWidth = getWidth() / COLUMNS_BRICKS;
for (int r = 0; r < ROWS_BRICKS; r++) {
for (int b = 0; b < COLUMNS_BRICKS; b++) {
brick = new GRect(b * brickWidth, gap * r + TOP_GAP,
brickWidth, 10);
brick.setFilled(true);
add(brick);
}
}
}
public void endGame() {
// TODO write end game method
}
public void animateBall() {
while (numTurns > 0) {
ball.move(dx, dy);
pause(15);
/* Look for Object Collision */
GObject topRightObject = getElementAt(ball.getX() + 5, ball.getY());
GObject topLeftObject = getElementAt(ball.getX(), ball.getY());
GObject botRightObject = getElementAt(ball.getX() + 5,
ball.getY() + 5);
GObject botLeftObject = getElementAt(ball.getX(), ball.getY() + 5);
/* Bounce off walls */
if ((ball.getX() >= getWidth() - 5) || ball.getX() <= 0) {
dx = -dx;
}
if (ball.getY() <= 0) {
dy = -dy;
}
if ((ball.getY() >= getHeight() - 5)) {
dy = -dy;
// numTurns--;
// if (numTurns == 0) {
// endGame();
// } else {
// run();
// }
}
/* Bounce off objects, remove bricks */
if (topRightObject != null) {
dy = -dy;
hasCollided(topRightObject);
}
if (topLeftObject != null) {
dy = -dy;
hasCollided(topLeftObject);
}
if (botRightObject != null) {
dy = -dy;
hasCollided(botRightObject);
}
if (botLeftObject != null) {
dy = -dy;
hasCollided(botLeftObject);
}
}
}
private void hasCollided(GObject obj) {
if (obj.equals(paddle)) {
System.out.println("detecting paddle");
} else {
System.out.println("detecting brick");
remove(obj);
}
}
}
在球击中球拍时反转方向的部分周围添加一个 if(dy<0)
(假设负数 dy 表示球朝向球拍)。这消除了你的方向被改变的可能性,但每次碰撞不止一次
我正在学习 java 本书 "The Art and Science of Java: An Introduction to Computer Science"。练习程序之一是创建 Breakout 游戏的简单克隆。
我目前可以加载游戏,但球的物理特性存在问题。我正在使用最简单的物理学,但看不出为什么它不起作用。
当球撞到墙上时,它会正常反弹,但当它撞到球拍或砖块时,它不会反弹。我在碰撞检测中使用相同的代码来改变我在墙壁上使用的方向。检测到碰撞,我添加了一个 println 并观察了控制台,因为它经历了碰撞事件,但没有发生方向变化。
package chapter10;
/*
* This program creates a clone of the classic Breakout Game,
* where a player bounces a ball with a paddle to "break" bricks
* along the top of the screen.
*
* Controls: Left: left button, Right: right button
*/
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.RepaintManager;
import javax.swing.Timer;
import acm.program.*;
import acm.graphics.*;
public class BreakoutClone extends GraphicsProgram {
/* components */
private GRect paddle;
private GRect brick;
private GOval ball;
/* static variables */
private static final double PADDLE_HEIGHT = 5;
private static final double BALL_SPEED = 2;
private static final double PADDLE_SPEED = 2;
private static final double ROWS_BRICKS = 6;
private static final double COLUMNS_BRICKS = 10;
private static final double TOP_GAP = 50;
/* variables */
private int numTurns = 3;
private double paddleWidth = 50;
private int dx = 2;
private int dy = 2;
public void init() {
setSize(700, 600);
paddle = new GRect(0, getHeight() - 30, paddleWidth, PADDLE_HEIGHT);
paddle.setFilled(true);
add(paddle);
addBricks();
ball = new GOval(getWidth() / 2, 175, 5, 5);
ball.setFilled(true);
add(ball);
}
public void run() {
animateBall();
// TODO animate paddle
}
public void addBricks() {
double gap = 20;
double brickWidth = getWidth() / COLUMNS_BRICKS;
for (int r = 0; r < ROWS_BRICKS; r++) {
for (int b = 0; b < COLUMNS_BRICKS; b++) {
brick = new GRect(b * brickWidth, gap * r + TOP_GAP,
brickWidth, 10);
brick.setFilled(true);
add(brick);
}
}
}
public void endGame() {
// TODO write end game method
}
public void animateBall() {
while (numTurns > 0) {
ball.move(dx, dy);
pause(15);
/* Look for Object Collision */
GObject topRightObject = getElementAt(ball.getX() + 5, ball.getY());
GObject topLeftObject = getElementAt(ball.getX(), ball.getY());
GObject botRightObject = getElementAt(ball.getX() + 5,
ball.getY() + 5);
GObject botLeftObject = getElementAt(ball.getX(), ball.getY() + 5);
/* Bounce off walls */
if ((ball.getX() >= getWidth() - 5) || ball.getX() <= 0) {
dx = -dx;
}
if (ball.getY() <= 0) {
dy = -dy;
}
if ((ball.getY() >= getHeight() - 5)) {
dy = -dy;
// numTurns--;
// if (numTurns == 0) {
// endGame();
// } else {
// run();
// }
}
/* Bounce off objects, remove bricks */
if (topRightObject != null) {
dy = -dy;
hasCollided(topRightObject);
}
if (topLeftObject != null) {
dy = -dy;
hasCollided(topLeftObject);
}
if (botRightObject != null) {
dy = -dy;
hasCollided(botRightObject);
}
if (botLeftObject != null) {
dy = -dy;
hasCollided(botLeftObject);
}
}
}
private void hasCollided(GObject obj) {
if (obj.equals(paddle)) {
System.out.println("detecting paddle");
} else {
System.out.println("detecting brick");
remove(obj);
}
}
}
在球击中球拍时反转方向的部分周围添加一个 if(dy<0)
(假设负数 dy 表示球朝向球拍)。这消除了你的方向被改变的可能性,但每次碰撞不止一次