【问题标题】:Move image in a spiral fashion in java在java中以螺旋方式移动图像
【发布时间】:2015-02-19 23:39:06
【问题描述】:

我正在尝试制作一个简单的动画介绍。我有一个图像,我正试图以顺时针螺旋运动从屏幕的左下角移动到屏幕的中心。这是我现在使用的代码。它只是将图像向上移动到中心:

static ImageLoader il = new ImageLoader();
private static BufferedImage logo = il.load("/logoNew.png");
private static Image power = il.gif("http://i.stack.imgur.com/KSnus.gif");
static double y = 1024.0;

public static void render(Graphics g){
    if(y>(486/2)-128){
        y = y-0.25;
    }
    if(draw){   
    g.drawImage(logo,(864/2)-128,(int)y,null);
    g.setColor(Color.WHITE);
    g.drawImage(power,10,10,null);
    }
}

if(draw) 语句被其他东西激活。 我该如何移动图像。我只是在不同点以不同方式递增 x 和 y 吗?

** 编辑 ** 我没有在动议上说清楚。它从左下到左上到右上到右下到底部中心(中心)到屏幕的中心(中心)

【问题讨论】:

  • 编辑您的答案并添加其他代码行,以便我们查看上下文。
  • 所以看起来它正在付诸东流?还是像从左下角到中心的曲线一样?
  • @MadProgrammer 从左下角到左上角到右下角到左下角到底部中心(中心)到屏幕中心(中心)
  • 我不完全理解你,但使用以下方法。建立一个半径(例如:100)、xs = x start(例如:0)和 xf = x final(例如:50)。使用 for 循环,其中 x 是从 xs 到 xf 并且对于每个当前 x,使用 Pitagora 计算 y。然后使用xy 绘制该点。
  • @helpYou 我明白你的意思了。我会试试你说的,然后回复你。

标签: java


【解决方案1】:

动画是随着时间的推移运动的错觉。通常我会使用Timing Framework(或TridentUniversal Tween Engine)之类的东西作为动画的基础,它们为诸如缓入和缓出之类的东西提供了更好的支持。

下面的例子只是使用了一个简单的javax.swing.Timer。我使用它是因为它与 Swing 一起使用更安全,因为它允许我从事件调度线程的上下文中更新 UI 的状态,但不会阻止它(阻止它更新屏幕)。

以下示例使用时间线和关键帧的概念。也就是说,在某个时间点,必须发生一些事情。然后,时间线提供了在这些“关键”时间点之间进行混合的方法。

就我个人而言,我喜欢研究抽象概念,所以时间线只是以 0-1 的百分比来衡量,这让我可以提供可变的时间跨度。这使我无需更改任何内容即可调整动画的速度。

正如你(应该)看到的那样,最后两条腿只需要移动一半的距离,所以它们比其他三条腿慢,所以,从技术上讲,它们只需要一半的时间就可以完成......但我会留给你来计算数学;)

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test{

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        protected static final int PLAY_TIME = 6000;

        private Timeline timeline;
        private long startTime;

        private Point imgPoint;
        private BufferedImage img;

        public TestPane() {

            try {
                img = ImageIO.read(new File("C:/Neko.png"));

                imgPoint = new Point(0, 200 - img.getHeight());

                timeline = new Timeline();
                timeline.add(0f, imgPoint);
                timeline.add(0.2f, new Point(0, 0));
                timeline.add(0.4f, new Point(200 - img.getWidth(), 0));
                timeline.add(0.6f, new Point(200 - img.getWidth(), 200 - img.getHeight()));
                timeline.add(0.8f, new Point(100 - (img.getWidth() / 2), 200 - img.getHeight()));
                timeline.add(1f, new Point(100 - (img.getWidth() / 2), 100 - (img.getHeight() / 2)));

                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        long duration = System.currentTimeMillis() - startTime;
                        float progress = (float) duration / (float) PLAY_TIME;
                        if (progress > 1f) {
                            startTime = System.currentTimeMillis();
                            progress = 0;
                            ((Timer) (e.getSource())).stop();
                        }

                        System.out.println(progress);
                        imgPoint = timeline.getPointAt(progress);
                        repaint();

                    }
                });
                startTime = System.currentTimeMillis();
                timer.start();
            } catch (IOException exp) {
                exp.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null && imgPoint != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(img, imgPoint.x, imgPoint.y, this);
                g2d.dispose();
            }
        }

    }

    public static class Timeline {

        private Map<Float, KeyFrame> mapEvents;

        public Timeline() {
            mapEvents = new TreeMap<>();
        }

        public void add(float progress, Point p) {
            mapEvents.put(progress, new KeyFrame(progress, p));
        }

        public Point getPointAt(float progress) {

            if (progress < 0) {
                progress = 0;
            } else if (progress > 1) {
                progress = 1;
            }

            KeyFrame[] keyFrames = getKeyFramesBetween(progress);

            float max = keyFrames[1].progress - keyFrames[0].progress;
            float value = progress - keyFrames[0].progress;
            float weight = value / max;

            return blend(keyFrames[0].getPoint(), keyFrames[1].getPoint(), 1f - weight);

        }

        public KeyFrame[] getKeyFramesBetween(float progress) {

            KeyFrame[] frames = new KeyFrame[2];
            int startAt = 0;
            Float[] keyFrames = mapEvents.keySet().toArray(new Float[mapEvents.size()]);
            while (startAt < keyFrames.length && keyFrames[startAt] <= progress) {
                startAt++;
            }

            if (startAt >= keyFrames.length) {
                startAt = keyFrames.length - 1;
            }

            frames[0] = mapEvents.get(keyFrames[startAt - 1]);
            frames[1] = mapEvents.get(keyFrames[startAt]);

            return frames;

        }

        protected Point blend(Point start, Point end, float ratio) {
            Point blend = new Point();

            float ir = (float) 1.0 - ratio;

            blend.x = (int) (start.x * ratio + end.x * ir);
            blend.y = (int) (start.y * ratio + end.y * ir);

            return blend;
        }

        public class KeyFrame {

            private float progress;
            private Point point;

            public KeyFrame(float progress, Point point) {
                this.progress = progress;
                this.point = point;
            }

            public float getProgress() {
                return progress;
            }

            public Point getPoint() {
                return point;
            }

        }

    }
}

【讨论】:

  • 这是我想要的基本版本,但这会起作用。非常感谢你的帮助。 :)
猜你喜欢
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-21
  • 1970-01-01
相关资源
最近更新 更多