我正在尝试使用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教程中的内容。我已经看了大约一个小时的代码,却找不到错误可能在哪里。任何帮助都将不胜感激。
答案 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,则可以更新堆栈跟踪以解决它。
我已阅读评论,它们非常有用。请检查链接,该链接说明了侦听关键事件的更好方法。
谢谢。