在Java Swing中实现sprite的波动效果

时间:2017-03-19 12:06:01

标签: java swing

Java swing中是否有一种方法可以为精灵提供像现场一样的效果?就像随机移动它的中心并产生波动效应一样?

我尝试了类似下面的内容(但结果太可怕了):

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

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;
    private int last = -1;

    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 = 58;
            y = 58;
            movementTimer = new Timer(12, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    moveImage();
                    repaint();
                }
            });
            movementTimer.start();
        }

        public void moveImage() {
            if (last < 0) {
                last = random();
                x += last;
                y += last;
            } else {
                x -= last;
                y -= last;
                last = -1;
            }
            if (x > W) {
                x = 0;
            }
            if (y > H) {
                y = 0;
            }
        }

        private int random() {

            Random r = new Random();
            int Low = 2;
            int High = 14;
            int Result = r.nextInt(High - Low) + Low;
            return Result;
        }

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

        }
    }
}

结果不顺利,你有什么建议吗?

1 个答案:

答案 0 :(得分:1)

简短回答是肯定的,可以做到。答案很长,您永远不会找到满足您确切需求的单个示例/解决方案,您需要剖析它们并删除您需要的元素。这是专业开发人员的标志,相信我,我花了90%的时间做我以前从未做过的事情(或者没有初步了解如何完成)。

当遇到问题/想法时,您需要退后一步并将其分解为可管理的组件

从我的角度来看,你有两个基本要求,即动画和转换。

动画

动画只是随时间变化的幻想。从表面上看,实现起来似乎很简单,实际上它变为very complex, very quickly

在Swing中,最简单的解决方案是使用Swing Timer生成定期更新,在事件调度线程的上下文中触发,从而可以安全地更新UI(Swing,就像大多数UI框架一样,一直不是线程安全的。)

由于它的工作方式,它不是很精确,这意味着你可能最终得到一个可变的帧速率。您可以使用time based animation方法克服此问题,其中移动基于持续时间,而不是计时器触发的次数。

另一种解决方案是使用线程,计算每个更新周期所花费的时间,并等待所需的剩余时间以维持FPS。当遇到线程问题(脏更新)时,这会更复杂,并且它没有考虑在UI上实际呈现图形所花费的时间(使用Swing的被动渲染引擎时) )

转化

转换图形(移动/旋转)最终将归结为&#34;什么&#34;你正在改造。

Graphics2D API可以旋转图片,for exampleexampleexampleexampleexample,{{3 }}

它还可以旋转Graphics上下文本身,这可能是凌乱的,或者旋转&#34;形状&#34;,这通常更容易管理。

您应该一般查看exampleWorking with Geometry以及Transforming Shapes, Text and Images

你也可以在点之间移动一个对象并改变它们的颜色,如2D Graphicshere所示,或者你可以使用here,然后对象遵循预先定义的移动路径甚至更复杂的东西,比如基于时间线的动画,path based animationfor exampleexample

所以,答案很长,取决于