我在我的游戏中使用了 Swing 计时器,但是当游戏运行时,它似乎有时会运行平稳,有时会变慢。
为什么时间会波动?
我该如何解决?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main extends JFrame {
public Main() {
super("JFrame");
// you can set the content pane of the frame
// to your custom class.
setContentPane(new ImagePanel());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 400);
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new Main();
}
class ImagePanel extends JPanel {
Timer movementtimer;
int x, y;
public ImagePanel() {
x = 0;
y = 0;
movementtimer = new Timer(12, new ActionListener() {
public void actionPerformed(ActionEvent e) {
long timstarted = System.currentTimeMillis();
moveImage();
repaint();
long timefinished = System.currentTimeMillis() - timstarted;
System.out.println(timefinished + " to run");
};
});
movementtimer.start();
}
public void moveImage() {
x++;
y++;
if (x > 800) {
x = 0;
}
if (y > 400) {
y = 0;
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(0, 0, 800, 400);
g.setColor(Color.BLUE);
g.fillRect(x, y, 50, 50);
}
}
}
这是我的代码示例。在我的实际程序中,我正在绘制图像而不仅仅是一个矩形。还有很多碰撞检测和其他小计算。
另外,这里是游戏的 Jar 文件的链接,您可以运行它并(希望)明白我的意思。 http://dl.dropbox.com/u/8724803/Get%20To%20The%20Chopper%201.3.jar
谢谢
汤姆
最佳答案
因为渲染是微不足道的,我发现你的例子的这个变体非常流畅。渲染时间远低于半毫秒,因此 12 毫秒周期(~83 赫兹)充足 时间来完成一帧,通常占用不到一个内核的 10%。随着渲染时间的增长,计时器线程变得饱和,并且事件被合并。由于渲染与垃圾收集和外部处理需求竞争,这种效果在单核上被放大了。 Java 不是实时系统,并非所有的调度程序都是一样的。
您肯定希望按照建议分析您的实际代码 here ,以查看与波动性能的任何相关性。一种替代方法是延长周期(降低频率)以满足渲染截止日期,并在 moveImage()
中使用更大的增量以获得相同的速度。
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main extends JFrame {
private static final int W = 800;
private static final int H = 400;
public Main() {
super("JFrame");
this.add(new ImagePanel());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
setSize(W, H);
this.setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
}
class ImagePanel extends JPanel {
Timer movementTimer;
int x, y;
public ImagePanel() {
x = 0;
y = 0;
movementTimer = new Timer(12, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
moveImage();
repaint();
}
});
movementTimer.start();
}
public void moveImage() {
x++;
y++;
if (x > W) {
x = 0;
}
if (y > H) {
y = 0;
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
long start = System.nanoTime();
g.setColor(Color.RED);
g.fillRect(0, 0, W, H);
g.setColor(Color.BLUE);
g.fillRect(x, y, 50, 50);
double delta = (System.nanoTime() - start) / 1000000d;
g.drawString(String.format("%1$5.3f", delta), 5, 15);
}
}
}
关于java - Swing 计时器——时间波动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7747745/