import acm.graphics.*;
import acm.program.*;
import acm.util.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.EventListener;
public class Breakout1 extends GraphicsProgram {
public static final int APPLICATION_WIDTH = 400;
public static final int APPLICATION_HEIGHT = 600;
private static final int WIDTH = APPLICATION_WIDTH;
private static final int HEIGHT = APPLICATION_HEIGHT;
private static final int PADDLE_WIDTH = 60;
private static final int PADDLE_HEIGHT = 10;
private static final int PADDLE_Y_OFFSET = 30;
/**Number of bricks per row */
private static final int NBRICKS_PER_ROW = 10;
/**
* Number of rows of bricks
*/
private static final int NBRICK_ROWS = 10;
/**
* Separation between bricks
*/
private static final int BRICK_SEP = 4;
/**
* Width of a brick
*/
private static final int BRICK_WIDTH =
(WIDTH - (NBRICKS_PER_ROW - 1) * BRICK_SEP) / NBRICKS_PER_ROW;
/**
* Height of a brick
*/
private static final int BRICK_HEIGHT = 8;
/**
* Radius of the ball in pixels
*/
private static final int BALL_RADIUS = 10;
/**
* Offset of the top brick row from the top
*/
private static final int BRICK_Y_OFFSET = 70;
/**
* Number of turns
*/
private static final int NTURNS = 3;
/* Method: init() */
/**
* Sets up the Breakout program.
*/
public void init() {
add (new GImage("C:\\Users\\Home\\Desktop\\beach.jpg"));
drawCanvas();
drawBrickWall();
drawPaddle();
drawBall();
addMouseListeners();
}
/* Method: run() */
/**
* Runs the Breakout program.
*/
public void run() {
}
private GRect brick;
private GOval ball;
private GRect paddle;
private void drawBrickWall() {
for (int i = 0; i < NBRICK_ROWS; i++)
for (int j = 0; j < NBRICKS_PER_ROW; j++)
drawBrick(i, j);
}
private void drawBrick(int row, int col) {
double x, y; // brick location
GRect brick = new GRect(BRICK_WIDTH, BRICK_HEIGHT);
x = computeXOffset() + col * (BRICK_WIDTH + BRICK_SEP);
y = BRICK_Y_OFFSET + row * (BRICK_HEIGHT + BRICK_SEP);
brick = new GRect(x, y, BRICK_WIDTH, BRICK_HEIGHT);
brick.setFilled(true);
add(brick, x, y);
if (row < 2) {
brick.setColor(Color.RED);
} else if (row == 2 || row == 3) {
brick.setColor(Color.ORANGE);
} else if (row == 4 || row == 5) {
brick.setColor(Color.YELLOW);
} else if (row == 6 || row == 7) {
brick.setColor(Color.GREEN);
} else if (row == 8 || row == 9) {
brick.setColor(Color.CYAN);
}
}
private double computeXOffset() {
return 0.5 * (WIDTH - (NBRICKS_PER_ROW - 1) * BRICK_SEP - BRICK_WIDTH * NBRICKS_PER_ROW);
}
private void drawPaddle() {
GRect paddle = new GRect(PADDLE_WIDTH, PADDLE_HEIGHT);
paddle.setFilled(true);
add(paddle, 0.5 * (WIDTH - PADDLE_WIDTH), HEIGHT - PADDLE_Y_OFFSET - PADDLE_HEIGHT);
addMouseListeners();
}
private boolean isMouseXInsideWindow(int x) {
return ((x > PADDLE_WIDTH / 2) && (x < (WIDTH - PADDLE_WIDTH / 2)));
}
public void mouseMoved(MouseEvent e) {
if (isMouseXInsideWindow(e.getX())) {
paddle.setLocation(paddle.getX() - PADDLE_WIDTH / 2, paddle.getY());
}
}
private void drawBall(){
GOval ball = new GOval(2*BALL_RADIUS, 2*BALL_RADIUS);
ball.setFilled(true);
add(ball, 0.5*WIDTH - BALL_RADIUS , 0.5*HEIGHT - BALL_RADIUS );
}
private void drawCanvas(){
GLabel myLabel= new GLabel ("Welcome to my Breakout Game!");
myLabel.setFont("Serif-bold-24");
myLabel.setColor(Color.CYAN);
add(myLabel,getXCenter(myLabel), getYCenter(myLabel));
}
private double getXCenter (GObject g){
return (getWidth()-g.getWidth())/2;
}
private double getYCenter (GObject g){
return (getHeight()-g.getHeight())/2;
}
}
它在我运行程序时一直给我错误NULLPOINTEXCEPTION,有人可以尝试检查mouseMoved(MouseEvent e)的错误,paddle不会移动并继续给我错误。但其余代码正在运行。
答案 0 :(得分:0)
您称为数据成员的Paddle
似乎并未实例化。您确实创建了Paddle
,但它尚未分配给成员变量,这是您在其余代码中使用的变量。
因此,在您的代码中drawPaddle()
内,您可以像这样创建Paddle
:
GRect paddle = new GRect(...)
。
但是,从未将其分配给类局部变量paddle
;因此,一旦调用drawPaddle()
,您对分配的变量的引用基本上就会丢失。当您来电话isMouseXInsideWindow(int)
时,您会尝试使用paddle.x
;但是这指的是属于类本身的成员变量paddle
,它已经未初始化。
所以,当你最初分配一个paddle时,需要将它分配给类&#39;成员变量而不是成为局部变量。这是一个非常简单的解决方案;在drawPaddle()
内,只需使用paddle = new GRect(...)
代替GRect paddle = new GRect(...)
;这确保我们分配对成员变量paddle
的引用,而不是创建一个本地的引用,我们在调用该方法后会忽略它。
为了避免将来出现这些问题,您应该尝试设计方法调用,以便将GRect
传递给它们。这使您可以更加具体地了解方法的工作方式,并强制您在管理引用时要小心。此外,如果将来你想添加第二个paddle
,或者第三个或第四个......,你会发现它会帮助你一大堆...
作为旁注,每当您与NullPointerExceptions
挣扎时,有助于缩小错误的确切来源。您已经知道问题必须放在mouseMoved(...)
方法的某个位置,因此您可以尝试将您使用的各种变量打印到控制台,以查看它们是否打印出有效的内容,打印null
或“不要”。甚至可以打印(这表示应用程序在您放置打印语句的位置之前的某个位置终止)。