java - 如何用java.Swing移动乒乓 Racket ?

标签 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 教程中复制粘贴的东西。我已经检查了我的代码大约一个小时,但找不到错误可能出在哪里。任何和所有的帮助将不胜感激。

最佳答案

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

首先,您在此处展示了使用 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 没有移动。其先前的绘制将保持原样,并且根据按下的键,新的桨将向上或向下绘制。因此,您将看到一条垂直条,而不是移动的桨。发生这种情况是因为我们正在修改图形,但没有再次绘制 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,可以更新堆栈跟踪来解决问题。

我已经阅读了这些评论,它们非常有用。请检查解释收听关键事件的更好方法的链接。

谢谢。

关于java - 如何用java.Swing移动乒乓 Racket ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60472083/

相关文章:

java - 如何将 xml 命名空间添加到 Java 中的非根元素?

java - JPanel 中的 TitledBorder 在使用 translate() 方法时移动

java - 如何使JScrollPane(在BorderLayout中,包含JPanel)平滑自动滚动

java - Swing组件的ActionMap中默认 Action 的名称是否标准化?

graphics - Slick-Util(在lwjgl中): Importing a texture and displaying it results in weird,在纹理附近创建的额外像素(以行为单位)

math - 带有行进立方体的隐式表面上的 CSG 操作

objective-c - 在drawRect中向UIView添加渐变

java - 更改 JFreeChart GanttChart 上的范围轴 - 非工作时间的 SegmentedTimeline

Java 8 流 - 如何正确制作 NPE 安全流

java - 尝试每 5 秒执行一次操作