摆动计时器 - 时间波动 [英] Swing timer - time fluctuating

查看:183
本文介绍了摆动计时器 - 时间波动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在游戏中使用的是Swing Timer,但是当游戏运行时,似乎有时候它会顺利运行,有时它会变慢。

I am using a Swing Timer in my game but when the game is running it appears to have moments when it runs smoothly and moments when it slows down.

为什么时间会波动?

我该如何解决?

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);

    }

}

}

以下是我的代码示例。在我的实际程序中,我正在绘制图像,而不仅仅是一个矩形。还有很多碰撞检测和其他小的计算发生。

Here is an example of my code. In my actual program I am drawing Images and not just a rectangle. There is also a lot of collision detection and other small calculations happening.

此外,这里有一个指向游戏的Jar文件的链接,所以你可以运行它(希望你好) ) 明白了吗。 http://dl.dropbox.com/u/8724803 /Get%20To%20The%20Chopper%201.3.jar

Also, here is a link to the Jar file for the game so you can run it and (hopefull) see what I mean. http://dl.dropbox.com/u/8724803/Get%20To%20The%20Chopper%201.3.jar

谢谢

Tom

推荐答案

因为渲染是微不足道的,所以我发现你的例子的这种变化非常平滑。渲染时间远低于半毫秒,因此12毫秒周期(~83 Hz)完成一帧时间 ,通常占用一个核心的10%。随着渲染时间的增长,计时器线程变得饱和,并且事件被合并。效果在单个核心上放大,因为渲染与垃圾收集和外部处理需求竞争。 Java不是一个实时系统,并不是所有的调度程序都是相同的。

Because the rendering is trivial, I find this variation of your example to be very smooth. The render time is well below a half millisecond, so the 12 millisecond period (~83 Hz) is plenty of time to finish a frame, typically taking less that 10% of one core. As the render time grows, the timer thread becomes saturated, and events are coalesced. The effect is magnified on a single core, as rendering competes with garbage collection and external processing demands. Java is not a real-time system, and not all schedulers are created equal.

你肯定想要描述你的实际代码,如建议here,查看与波动性能的任何相关性。另一种方法是延长周期(降低频率)以满足渲染截止期限,并在 moveImage()中使用更大的增量来获得相同的速度。

You'll certainly want to profile your actual code, as suggested here, to see any correlation with fluctuating performance. One alternative approach is to lengthen the period (decrease the frequency) to meet your rendering deadline and use a larger increment in moveImage() to get the same velocity.

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);
        }
    }
}

这篇关于摆动计时器 - 时间波动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆