我正在开发一款游戏。当尝试在“主”线程中使用游戏循环进行可视化时,仅很少调用
paintComponent
方法。我读过许多其他类似的问题,但似乎没有一个对我有帮助。可能是我仍然没有正确理解一切。
我知道这仍然是 EDT 的一个问题,因为当我移动鼠标或按下按键时,游戏会流畅地呈现。
谢谢!
这是我的缩短代码:
public class Game implements Runnable {
private GamePanel gamePanel;
private Thread gameThread;
private final int FPS_SET = 120;
public Game() {
gamePanel = new GamePanel();
gamePanel.requestFocus();
gameThread = new Thread(this);
gameThread.start();
}
@Override
public void run() {
double timePerFrame = 1000000000.0 / FPS_SET ;
long lastFrame = System.nanoTime();
long now = lastFrame;
while(true) {
now = System.nanoTime();
if (now - lastFrame >= timePerFrame) {
// Updates Scenery
_reDraw();
lastFrame = now;
}
}
}
private void _reDraw() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gamePanel.repaint();
}
});
}
}
public class GamePanel extends JPanel {
// ...
public void paintComponent(Graphics g) {
// draw
}
}
来自
repaint()
文档:
如果该组件是轻量级组件,则此方法会导致 尽快调用该组件的
方法。否则, 此方法会立即调用该组件的paint
update
方法可能。
尽快并不意味着每次你打电话repaint()
paint
都会被叫到。您拨打
repaint()
的速度可能比工具包能够回答您的请求的速度还要快。再次来自文档:
应用程序触发绘画和:在应用程序触发的绘画操作中,组件决定 它需要更新其内容,因为其内部状态已 改变了。 (例如,按钮检测到鼠标按钮已被按下 按下并确定需要绘制一个“按下”的按钮 视觉)。
绘画方法工具包会在绘制时调用此方法无论如何触发绘制请求,AWT 都会使用 绘画的“回调”机制,这个机制是一样的 重量级和轻量级组件。这意味着一个程序 应该将组件的渲染代码放在特定的 重写的方法,并且工具包将在它被覆盖时调用此方法 是时候画画了
.
是重要的部分。 和:
应用程序触发绘画
应用程序触发的绘画操作如下:
程序确定组件的一部分或全部需要 重新绘制以响应某些内部状态变化。
程序在组件上调用 repaint(),该组件注册了一个 该组件需要向 AWT 发出异步请求 重新粉刷了。
AWT 导致事件调度线程调用 update() 组件。
注意:如果在组件上多次调用 repaint() 初始重绘请求已处理,多个请求可能是 折叠成对 update() 的单个调用。算法为 确定何时应该折叠多个请求是 取决于实施。如果多个请求被折叠, 生成的更新矩形将等于 折叠请求中包含的矩形。真正的绘画不在你这边,而是在主机UI上 边。可能有很多事件不允许这幅画被拍摄 地点(你的窗户不可见,有更紧急的事情要做, 等)。
至少,我们知道对于
repaint
中将会有
paint
未来,但多个 repaint
可能会导致单个 paint
。