如何使用java.swing移动乒乓球拍?

时间:2020-03-01 04:50:41

标签: java swing graphics 2d-games

我正在尝试使用Java和Swing来制作Pong。但是,我有两个问题-一,屏幕上的矩形根本不动,二,即使代码仍在运行,NullPointerException仍在发生。这是我的两个文件:


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Pong extends JFrame implements KeyListener {

    private static final long serialVersionUID = -5782301423436L;

    JPanel panel;

    Paddle paddle1;

    public Pong() {
        super("Pong");

        panel = new JPanel();
        this.add(panel);

        super.setPreferredSize(new Dimension(800, 600));
        super.setVisible(true);
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.pack();
        addKeyListener(this);

        paddle1 = new Paddle(100, 300);
    }

    public static void main(String[] args) {
        @SuppressWarnings("unused")
        Pong game = new Pong();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 800, 600);

        g.setColor(Color.BLACK);
        this.paddle1.draw(g);
    }

    public void keyTyped(KeyEvent e) {}

    public void keyReleased(KeyEvent e) {}

    // I've tested this part and the w and s key presses
    // are still detected, but nothing happens. Why not?
    public void keyPressed(KeyEvent keyEvent) {
        int key = keyEvent.getKeyCode();
        if (key == KeyEvent.VK_ESCAPE) {
            this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
        } else if (key == KeyEvent.VK_W) {
            this.paddle1.up();
        } else if (key == KeyEvent.VK_S) {
            this.paddle1.down();
        }
    }

}

import java.awt.Graphics;

public class Paddle {

    // Position of the paddle's center
    int x;
    int y;

    public Paddle(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void draw(Graphics g) {
        g.fillRect(this.x - 10, this.y - 40, 20, 80);
    }

    // Up is negative because Java coordinates

    public void up() {
        this.y -= 30;
    }

    public void down() {
        this.y += 30;
    }

}

我已经测试了Pong文件中的keyPressed方法,实际上,当按下w和s键时,它确实会检测到它们(它将在控制台输出一行)。我是Java语言中的新手,这是我尝试创建的第一件事,并不是复制YouTube教程中的内容。我已经看了大约一个小时的代码,却找不到错误可能在哪里。任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:0)

我已经检查了代码,可以帮助您解决错误。

首先,您在这里使用JFrame Pong 的paint()方法显示了Paddle。您正在检测“ W”和“ S”键,并根据该键编写了更新Paddle类中y坐标的代码。

但是,这里的问题是,您只是在更新y坐标。您不会再次用新的坐标绘制桨叶。因此,在设置了新的y值之后,您应该再次绘制桨叶。 因此,在

之后,在keyPressed()方法中
this.paddle1.up();

this.paddle1.down();

您应该再次调用Paddle类的draw()方法,该方法将在修改后的位置绘制Paddle。

在此draw()方法中,您要传递一个Graphics对象,该对象是当前JFrame Pong的图形配置。因此,可以使用JFrame的getGraphics()方法获得此结果。

因此,在up()或down()之后添加的行将是

this.paddle1.draw(getGraphics());

由于我们正在处理图形,因此一旦更改了JFrame的图形,重新绘制JFrame也是正确的做法。如果您仅在keyPressed()方法中的up()和down()方法之后添加了以上行,您将看到Paddle并没有移动。其先前的图形将保持不变,并按按键,向上或向下绘制新的Paddle。因此,您将看到一个垂直条,而不是移动的桨。发生这种情况是因为我们正在修改图形,但没有再次绘制JFrame。因此,它将仅在JFrame中添加新矩形,保持原样。 因此,要摆脱这种情况,您应该使用JFrame的repaint()方法,使其仅绘制最新的屏幕。

因此,完整的keyPressed()方法将类似于:

@Override
public void keyPressed(KeyEvent keyEvent) {
    int key = keyEvent.getKeyCode();
    if (key == KeyEvent.VK_ESCAPE) {
        this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
    } else if (key == KeyEvent.VK_W) {
        this.paddle1.up();
        this.paddle1.draw(getGraphics());
        repaint();
    } else if (key == KeyEvent.VK_S) {
        this.paddle1.down();
        this.paddle1.draw(getGraphics());
        repaint();
    }
}

因此,现在,在检测到正确的键之后,它将再次绘制桨叶并 之后,它也将丢弃之前的代码,以便在您运行此代码的同时,您还可以根据所按的键看到操纵杆正在移动。

现在,关于NullPointerException。我试图运行此代码,但无法重现此类异常。因此,尝试使用建议的代码后,如果遇到NPE,则可以更新堆栈跟踪以解决它。

我已阅读评论,它们非常有用。请检查链接,该链接说明了侦听关键事件的更好方法。

谢谢。

相关问题