在 JPanel 中绘制一组对象
Painting a group of objects in a JPanel
我对 Java 和 GUI 世界还很陌生。现在我正在尝试创建一个非常基本的 space 射击游戏。为了创建它,我开始创建一个 JFrame
,稍后我在其中放置了一个名为 GamePanel
的 JPanel
的个人扩展,我现在正在尝试在其上显示我的所有组件.到这里为止一切都很清楚,现在问题来了:我有我的 GamePanel
显示我的播放器,在 KeyEvent
按下 S 播放器应该射击子弹。我将项目符号管理为一个名为 Shooter[]
的数组,由 Bullet
个对象组成,由我自己以这种方式创建:
public class Bullet implements ActionListener{
Timer Time = new Timer(20, this);
private int BulletY = 430;
public int PlayerX;
public Rectangle Bound = new Rectangle();
public Bullet(int playerx) {
this.PlayerX = playerx;
Time.start();
}
public void draw(Graphics g){
g.setColor(Color.RED);
g.fillRect(PlayerX + 2, BulletY, 3, 10);
g.dispose();
}
@Override
public void actionPerformed(ActionEvent e) {
if (Time.isRunning()) {
BulletY = BulletY - 5;
Bound = new Rectangle (PlayerX + 2, BulletY, 3, 10);
}
}
}
我认为在 GamePanel
的 paint()
方法中调用 draw 方法可以让我同时显示所有发射的子弹和玩家。实际发生的是,一开始它似乎还好,但是当我按下 S 时,播放器消失了,只发射了一颗子弹。你能解释一下为什么吗?这就是我的 paint()
方法的样子:
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
for(int i = 0; i < BulletsCounter; i++) {
Shooter[i].draw(g);
}
g.setColor(Color.RED);
g.fillRect(PlayerX, PlayerY, 20, 20);
//System.out.println("Here I should have painted the player...");
g.dispose();
}
BulletsCounter
是我创建的一个计数器,以避免在绘制整个阵列时出现任何 NullPointerException
s,当按下 S 时它会增加,因此阵列的另一个子弹被初始化并发射。
感谢您的耐心等待,我是该网站的新手,如有任何错误请警告我。
你有几个严重的问题,首先给出最大的问题:
- 您正在处置 JVM 提供给您的 Graphics 对象。永远不要这样做,因为这会破坏绘画链。相反,只处理您自己创建的 Graphics 对象。
- 你在画图内绘图,这有几个原因并不好,但对动画尤其不利,因为你没有图像的自动双缓冲
- 您没有在覆盖中调用超级绘画方法,因此不允许 JPanel 进行内务绘画。
建议:
- 不要处理 Graphics 对象,除非您自己创建它,例如,如果您从 BufferedImage 中提取一个对象。
- 覆盖 JPanel 的 paintComponent 方法,而不是其 paint 方法,以提供双缓冲和更流畅的动画效果。
- 然后在覆盖中首先调用
super.paintComponent(g)
以允许内务处理绘画
我对 Java 和 GUI 世界还很陌生。现在我正在尝试创建一个非常基本的 space 射击游戏。为了创建它,我开始创建一个 JFrame
,稍后我在其中放置了一个名为 GamePanel
的 JPanel
的个人扩展,我现在正在尝试在其上显示我的所有组件.到这里为止一切都很清楚,现在问题来了:我有我的 GamePanel
显示我的播放器,在 KeyEvent
按下 S 播放器应该射击子弹。我将项目符号管理为一个名为 Shooter[]
的数组,由 Bullet
个对象组成,由我自己以这种方式创建:
public class Bullet implements ActionListener{
Timer Time = new Timer(20, this);
private int BulletY = 430;
public int PlayerX;
public Rectangle Bound = new Rectangle();
public Bullet(int playerx) {
this.PlayerX = playerx;
Time.start();
}
public void draw(Graphics g){
g.setColor(Color.RED);
g.fillRect(PlayerX + 2, BulletY, 3, 10);
g.dispose();
}
@Override
public void actionPerformed(ActionEvent e) {
if (Time.isRunning()) {
BulletY = BulletY - 5;
Bound = new Rectangle (PlayerX + 2, BulletY, 3, 10);
}
}
}
我认为在 GamePanel
的 paint()
方法中调用 draw 方法可以让我同时显示所有发射的子弹和玩家。实际发生的是,一开始它似乎还好,但是当我按下 S 时,播放器消失了,只发射了一颗子弹。你能解释一下为什么吗?这就是我的 paint()
方法的样子:
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
for(int i = 0; i < BulletsCounter; i++) {
Shooter[i].draw(g);
}
g.setColor(Color.RED);
g.fillRect(PlayerX, PlayerY, 20, 20);
//System.out.println("Here I should have painted the player...");
g.dispose();
}
BulletsCounter
是我创建的一个计数器,以避免在绘制整个阵列时出现任何 NullPointerException
s,当按下 S 时它会增加,因此阵列的另一个子弹被初始化并发射。
感谢您的耐心等待,我是该网站的新手,如有任何错误请警告我。
你有几个严重的问题,首先给出最大的问题:
- 您正在处置 JVM 提供给您的 Graphics 对象。永远不要这样做,因为这会破坏绘画链。相反,只处理您自己创建的 Graphics 对象。
- 你在画图内绘图,这有几个原因并不好,但对动画尤其不利,因为你没有图像的自动双缓冲
- 您没有在覆盖中调用超级绘画方法,因此不允许 JPanel 进行内务绘画。
建议:
- 不要处理 Graphics 对象,除非您自己创建它,例如,如果您从 BufferedImage 中提取一个对象。
- 覆盖 JPanel 的 paintComponent 方法,而不是其 paint 方法,以提供双缓冲和更流畅的动画效果。
- 然后在覆盖中首先调用
super.paintComponent(g)
以允许内务处理绘画