0

Ball.java

public class Ball {
    int x = 500, y = 10, speed = 1;
    GameBoard board;
    boolean keepRunning = true;
    Thread thread;

    Ball(GameBoard board) {
        this.board = board;
        new Thread(r1).start();
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    Runnable r1 = new Runnable() {
        public void run() {
            try {
                while (true) {
                    if (board.ball.intersects(board.pPaddle)) {
                        speed = -speed;
                    } else {
                        System.out.println(board.ball + " z " + board.pPaddle);
                    }
                    x -= speed;
                    board.repaint();
                    Thread.sleep(10L);

                }
            } catch (InterruptedException iex) {
            }
        }

    };
}

游戏板.java

@SuppressWarnings("serial")
public class GameBoard extends Canvas {
    Image dbi;
    Graphics db;
    JFrame okno;
    Player p = new Player(this);
     Ball b = new Ball(this);
     Ai a = new Ai(this);
     Rectangle aiPaddle = new Rectangle(10, 590, 10, 50);
     Rectangle pPaddle = new Rectangle(10, 100, 10, 50);
     Rectangle ball = new Rectangle(500, 10, 10, 10);
    GameBoard() {
        okno = new JFrame();
        okno.setTitle("Pink Ponk");
        okno.setSize(600, 300);
        okno.getContentPane().setBackground(Color.black);
        okno.setResizable(false);
        okno.setVisible(true);
        okno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addKeyListener(p);
    }

    public static void main(String[] args) {
        GameBoard gra = new GameBoard();
        gra.okno.add(gra);
    }

    @Override
    public void update(Graphics g) {
        pPaddle.setBounds(p.getX(), p.getY(), 10, 50);
        aiPaddle.setBounds(a.getX(), a.getY(), 10, 50);
        ball.setBounds(b.getX(), b.getY(), 10, 10);
        dbi = createImage(10, 50);
        db = dbi.getGraphics();
        paint(db);
        g.clearRect(0, 0, 600, 300);
        g.drawRect(p.getX(), p.getY(), 10, 50);
        g.fillRect(p.getX(), p.getY(), 10, 50);
        g.drawOval(b.getX(), b.getY(), 10, 10);
        g.fillOval(b.getX(), b.getY(), 10, 10);
    }

    @Override
    public void paint(Graphics g) {
        pPaddle.setBounds(p.getX(), p.getY(), 10, 50);
        aiPaddle.setBounds(a.getX(), a.getY(), 10, 50);
        ball.setBounds(b.getX(), b.getY(), 10, 10);
        g.clearRect(0, 0, 600, 300);
        g.setColor(Color.white);
        g.drawRect(p.getX(), p.getY(), 10, 50);
        g.fillRect(p.getX(), p.getY(), 10, 50);
        g.drawOval(b.getX(), b.getY(), 10, 10);
        g.fillOval(b.getX(), b.getY(), 10, 10);
    }

}

它一直有效,直到我编写了这行代码(Ball.java 中的 24 行):

if (board.ball.intersects(board.pPaddle))

我收到错误:

线程“Thread-0”中的异常 java.lang.NullPointerException at Ball$1.run(Ball.java:24) at java.lang.Thread.run(Unknown Source)

我确定 GameBoard.java 中的矩形不是空的。我不知道该怎么办。

4

2 回答 2

1

据我所知,有两种可能性:

  • board,传递给 Ball 的构造函数的参数为​​ null
  • board,传递给 Ball 的构造函数的参数不为 null,但是因为您在构造函数中启动了一个线程,所以该线程可以看到 Ball 对象的部分构造(例如,可能尚未分配 ball.board)...

你应该做什么:

  1. 检查board不为空(例如使用打印语句)
  2. 无论如何,不​​要在构造函数中启动新线程

您可以在构造函数中创建线程并提供启动线程的另一种方法(例如 start 或 init)。


一旦你这样做了,你可能不会再得到你的 NPE。但是,请注意,该行Ball b = new Ball(this);之前已执行,Rectangle ball = new Rectangle(500, 10, 10, 10);因此如果您board.ball在 Ball 的构造函数中访问,您将看到它为 null。

通常,您应该避免this在构造函数或实例初始化程序中转义(即不要编写类似的东西ObjectXX o = new ObjectXX(this);),因为this可能没有完全构造。

于 2012-07-09T09:52:26.597 回答
0

球矩形很可能为空,您首先创建 b 启动一个线程,该线程将尝试访问board.ballball稍后在 GameBoard 构造函数中创建。

于 2012-07-09T09:54:35.353 回答