摇摆动画优化 [英] Swing animation optimization

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

问题描述

我一直在 JComponent 上使用 Timer 制作简单的动画。但是,当观看动画时,我会遇到难以置信的震荡运动。我应该采取什么步骤来优化此代码?

I have been working on a simple animation using a Timer on a JComponent. However, I experience incredibly choppy motion when I view the animation. What steps should I take to optimize this code?

import javax.swing.*;

public class MyAnimationFrame extends JFrame {
    public MyAnimationFrame() {
        super("My animation frame!");
        setSize(300,300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(new AnimationComponent(0,0,50,50));
        setVisible(true);
    }

    public static void main(String[] args) {
        MyAnimationFrame f = new MyAnimationFrame();
    }
}



AnimationComponent



AnimationComponent

import javax.swing.*;
import java.awt.*;

public class AnimationComponent extends JComponent implements ActionListener {
    private Timer animTimer;
    private int x;
    private int y;
    private int xVel;
    private int yVel;
    private int width;
    private int height;
    private int oldX;
    private int oldY;

    public AnimationComponent(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;

        animTimer = new Timer(25, this);
        xVel = 5;
        yVel = 5;

        animTimer.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        g.fillOval(x,y,width,height);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        oldX = x;
        oldY = y;

        if(x + width > getParent().getWidth() || x < 0) {
             xVel *= -1;
        }

        if(y + height > getParent().getHeight() || y < 0) {
            yVel *= -1;
        }

        x += xVel;
        y += yVel;

        repaint();
    }
}

不确定这是否重要,但我使用的是OpenJDK版本1.8.0_121。

Not sure if this matters, but I am using OpenJDK version 1.8.0_121.

不胜感激。

推荐答案

在与Yago进行了精彩的讨论之后,我发现问题围绕多个领域展开,很大程度上归因于Java将更新与操作系统和硬件同步的能力,有些可以控制,有些则不能。

After a wonderful discussion with Yago it occurred to me that the issue revolves around number of areas, alot comes down to the ability for Java to sync the updates with the OS and the hardware, some things you can control, some you can't.

受Yago的示例和我对Timing Framework的记忆的启发,我通过提高帧速率(至5毫秒,〜= 200fps)并降低帧速率来测试代码更改增量,其结果与使用Timing Framework的结果相同,但为您提供了原始设计的灵活性。

Inspired by Yago's example and my "memory" of how the Timing Framework works, I tested you code by increasing the framerate (to 5 milliseconds, ~= 200fps) and decreasing the change delta, which gave the same results as using the Timing Framework, but which leaves you with the flexibility of your original design.

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Test");
                frame.add(new AnimationComponent(0, 0, 50, 50));
                frame.setSize(300, 300);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class AnimationComponent extends JComponent implements ActionListener {

        private Timer animTimer;
        private int x;
        private int y;
        private int xVel;
        private int yVel;
        private int width;
        private int height;
        private int oldX;
        private int oldY;

        public AnimationComponent(int x, int y, int width, int height) {
            this.x = x;
            this.y = y;
            this.height = height;
            this.width = width;

            animTimer = new Timer(5, this);
            xVel = 1;
            yVel = 1;

            animTimer.start();
        }

        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g.create();
            RenderingHints hints = new RenderingHints(
                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
            );
            g2d.setRenderingHints(hints);
            g2d.fillOval(x, y, width, height);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            oldX = x;
            oldY = y;

            if (x + width > getParent().getWidth() || x < 0) {
                xVel *= -1;
            }

            if (y + height > getParent().getHeight() || y < 0) {
                yVel *= -1;
            }

            x += xVel;
            y += yVel;

            repaint();
        }
    }
}

如果需要放慢速度增加速度,然后减少变化增量,这意味着您必须使用 double s,这将导致 Shape 支持双精度值的API

If you need to slow down the speed more, then decrease the change delta more, this will mean you have to use doubles instead, which will lead into the Shape's API which supports double values

您应该使用哪个?随你(由你决定。时序框架确实非常适合在一段时间内进行线性动画处理,您知道要从一种状态进入另一种状态。对于游戏之类的东西来说,状态不是很好,因为对象的状态可能会从我的周期更改为另一个周期。我确定您可以做到,但是使用简单的主循环概念-IMHO

Which should you use? That's up to you. The Timing Framework is really great for linear animations over a period of time, where you know you want to go from one state to another. It's not so good for things like games, where the state of the object can change from my cycle to another. I'm sure you could do it, but it'd be a lot easier with a simple "main loop" concept - IMHO

这篇关于摇摆动画优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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