Java 摆动计时器-时间波动
我在游戏中使用了一个摆动计时器,但当游戏运行时,它似乎有平稳运行和减速的时刻 为什么时间在波动 我该如何修复它Java 摆动计时器-时间波动,java,swing,time,timer,Java,Swing,Time,Timer,我在游戏中使用了一个摆动计时器,但当游戏运行时,它似乎有平稳运行和减速的时刻 为什么时间在波动 我该如何修复它 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.swin
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文件的链接,您可以运行它,并(希望)了解我的意思
谢谢
汤姆秋千
计时器
因其不准确而臭名昭著。用别的东西代替
在提示下,我决定取消删除此帖子。OTOH大多数值得恢复的额外信息来自垃圾神,所以我只引用/解释他们的评论 我认为它相当准确,但很容易饱和 垃圾神接着在另一条评论中补充说: (一) 可以引用
javax.swing.Timer
不是很精确,但它在现代平台上非常精确
在面板中,请执行以下操作:
setBackground(Color.RED);
然后您不需要擦除背景,因为您正在调用super.paintComponent
通常,根据实际经过的时间(System.nanoTime())计算位置,并且不依赖计时器帧。有几个游戏框架,所以也许值得一看他们的解决方案。我喜欢这个示例。因为渲染非常简单,我发现您示例的这个变体非常平滑。渲染时间远低于半毫秒,因此12毫秒周期(~83 Hz)是完成一帧所需的大量时间,通常不到一个核心的10%。随着渲染时间的增长,计时器线程将饱和,事件将合并。这种效果在单个内核上被放大,因为渲染与垃圾收集和外部处理需求竞争。Java不是一个实时系统,并非所有调度程序都是平等创建的 正如建议的那样,您肯定希望分析实际代码,以查看与性能波动的任何相关性。另一种方法是延长周期(降低频率)以满足渲染截止时间,并在
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);
}
}
}
顺便说一句,我无法理解你计时计算的逻辑。使
长时间启动代码>ActionListener类的一个属性,你可能会看到我所看到的-一致的12s和13s。好主意,但这似乎更适合移动的组件。我不能这样做,因为在我的实际程序中,背景一直在移动。@Andrew Thompson我同意你删除的帖子(垃圾神+1)@mKorbel从某种意义上讲,它是准确的,因为如果你每秒运行一个计时器,持续86400次迭代,它将“漂移”,而不是24小时。但是我认为垃圾神发现了这个不稳定的动画的真正问题——核心饱和。@Andrew:如果你恢复你删除的帖子(+1,顺便说一句),你可能会引用javax.swing.Timer
不是很精确,但它在现代平台上非常精确。