Swing timer - time fluctuating

前端 未结 3 611
陌清茗
陌清茗 2021-01-14 04:52

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.

Why is the time fl

3条回答
  •  北海茫月
    2021-01-14 05:15

    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.

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

提交回复
热议问题