我是更动态的 java swing 编程新手。当然,我之前也使用过常规的 swing 组件,包括 Buttons
、Panels
等。
所以我尝试使用 Swing
和 Graphics2D
制作一个非常基本的乒乓球游戏。我之前做了一个绘画程序,我成功了。
我的问题是程序运行时图形严重卡顿。到目前为止,我只实现了球,它只是选择一个随机方向并开始在面板中弹跳。这有效。但是,只有当我一直不断调整框架大小时,我才能看到球,否则它会严重卡顿,看起来是空白的。在第一秒左右,您实际上可以看到球在移动,但严重卡顿,然后面板开始显得空白。
相关代码和结构:
程序的主要部分是Controller
和Frame
类。其中 Controller
实现了 runnable 并包含一个执行游戏更新的 run 方法。
Frame 类扩展了 JFrame
并包含一个私有(private)实例变量 JPanel
gamePanel,所有图形都在其中绘制。 JFrame
还有一个重写的 paint()
;方法
当Controller
更新程序时,它会调用Frame
中名为updateGraphics()
的类,该类之前调用paint(getGraphics( ))
;
public class Frame extends JFrame {
private JPanel gamePanel;
....
public void paint(Graphics g) {
super.paint(g);
label.setText(Integer.toString(ball.getPos().x) + ", " + Integer.toString(ball.getPos().y));
Graphics2D g2 = (Graphics2D) gamePanel.getGraphics();
g2.setStroke(new BasicStroke(2));
//g2.drawRect(0, 0, gamePanel.getWidth(), gamePanel.getHeight());
try{
//Draws the ball
g2.fillOval(ball.getPos().x, ball.getPos().y, 10, 10);
//Draws the player1(left) shield
g2.setStroke(new BasicStroke(2));
g2.drawLine(playerShield.getNorthX(), playerShield.getNorthY(), playerShield.getSouthX(), playerShield.getSouthY());
g2.drawLine(playerShield.getNorthX(), playerShield.getNorthY(), playerShield.getSouthX(), playerShield.getSouthY());
//Draws the computer/Player2(right) Shield
g2.drawLine(computerShield.getNorthX(), computerShield.getNorthY(), computerShield.getSouthX(), computerShield.getSouthY());
g2.drawLine(computerShield.getNorthX(), computerShield.getNorthY(), computerShield.getSouthX(), computerShield.getSouthY());
} catch(Exception e) {
System.out.println(e);
}
}
...
public void updateGraphics() {
paint(getGraphics());
}
//Another version of the updateGraphics i have tried to use with as little success
public void updateGrapgics() {
gamePanel.validate();
gamePanel.repaint();
}
}
在搜索时,我发现有人说我应该和不应该使用paint或repaint方法。
有人可以向我解释为什么它会口吃以及我应该如何做才能使其不口吃吗?
最佳答案
无需实现双缓冲或其他技巧。只需执行以下操作:
public class SomeVisualObject extends JComponent {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
// paint things
}
}
...
final SomeVisualObject obj = new SomeVisualObject()
frame.add(obj);
...
final Timer repaintTimer = new Timer(20, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// do some stuff here, for example calculate game physics.
// repaint actually does not repaint anything, but enqueues repaint request
obj.repaint();
}
});
repaintTimer.start();
并且它将顺利运行和绘制,没有任何故障。
只是不要弄乱循环。 Swing 运行它自己的事件循环,这对于重绘和其他内容至关重要。
在此处查看 2d 游戏对象(弹跳球)的完整且有效的示例:https://gist.github.com/akhikhl/8199472
关于Java 图形更新严重卡顿(简单的乒乓球游戏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20858817/