我一直试图用纯粹的java制作一个简单的游戏,而且我在绘图时遇到了问题。我试图保持相对较高的帧速率,但却遇到JFrame.repaint()不能强制使用的问题。并且仅仅是在下一个可用机会重绘框架的请求。结果,下面代码的帧速率非常糟糕。然而,(这是一个奇怪的部分)当我的鼠标移动时似乎只是可怕。如果我的鼠标移动并且在窗口顶部,则帧速率快速且清晰。
我已经尝试了各种在线建议,甚至编写了如何执行此操作的示例,当鼠标不在窗口上移动时,它们似乎都有相同的问题,帧速率急剧下降。
(我使用Linux,如果重要的话)
非常感谢任何和所有帮助!
%ld
答案 0 :(得分:2)
经过太多研究,结果证明java在许多Linux系统上不会自动同步/刷新显示缓冲区。所有的重绘都是正确的,但显示缓冲区没有冲洗,因此产生了奇怪的滞后效应。
解决方案:
Toolkit toolkit = Toolkit.getDefaultToolkit(); /* get AWT toolkit */
/* initialize things */
...
while (your_loop) {
/* run your logic */
...
/* paint everything */
...
toolkit.sync(); /* force display buffer to flush */
}
感谢大家的投入
答案 1 :(得分:1)
问题并不简单。下面的代码尚未经过测试,只是为了给你一个想法......在下一行中,AWT是Swing的基础。
首先,你必须保持你的paintComponent()
非常快(确实!)。这是第一个要求。基本上,对于60 fps,您必须在不到15毫秒的时间内绘制。忘记transaparency和其他东西(在Windows上工作很糟糕,我不知道Linux)。尽可能尝试保存计算。
其次,在另一个线程中执行其他所有操作。这是我用于自己程序的方式。注意每次调用AWT(包括Swing,当然)必须封装在EventQueue.invokeLater()的调用中,以确保你在AWT线程中运行东西,因为设置标签绝不能在AWT线程之外完成。
当您从AWT收到需要时间的输入时,不要忘记创建一个线程!
第三,用timer之类的
替换你的循环new Timer("Drawer", true).scheduleAtFixedRate( new TimerTak(){
public void run(){
frame.repaint();
}
},
100, // Start in 100 ms
(int)(1000 / 60)); // 60 is the frame rate.
一切都应该顺利进行。对于帧计数k
,请使用以下内容:
// You should initialize just before you create the timer...!
static private long startedAt = System.currentTimeMillis();
@Override public void paintComponent(Graphics g) {
super.paintComponent(g);
// Microseconds since the game started.
long k = (System.currentTimeMillis() - startedAt);
// Increment only one by frame (60 fps)
k = (int)((double)k * 60 / 1000.0)
// Draw the game...!
}
这就是全部。请注意,如果计算机功能不够强大(或者需要CPU密集型,或垃圾收集器......),则可以删除某些帧。但是,如果可能,您的游戏将以最高60 fps的速度运行。
奖励:如果每次通过paintComponent()
时增加一个值,就可以找到自开始以来真正显示的丢帧数或平均每秒帧数游戏。