在java中以螺旋方式移动图像 [英] Move image in a spiral fashion in java

查看:64
本文介绍了在java中以螺旋方式移动图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to make a simple animated intro. I have an image I am trying to move from the bottom left of the screen to the center of the screen in a clockwise spiral motion. This is the code that I am using for now. It just moves the image upward to the center:

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?

The if(draw) statement is activated by something else. How do I go about moving the image. Do I just increment the x and the y differently at different points?

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

** EDIT ** I didn't make it clear on the motion. Its going from the bottom left to the top left to the top right to the bottom right to the bottom center (centre) to the center (centre) of the screen

推荐答案

动画是随着时间的推移运动的错觉。通常我会使用像时间框架(或 Trident 通用Tween引擎)作为动画的基础,它们为轻松和缓出等内容提供了更好的支持。

Animation is the illusion of movement over time. Normally I would use something like the Timing Framework (or Trident or Universal Tween Engine) as the base of the animation, these provide better support for things like ease-in and ease-out.

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

The following example just makes uses of a simple javax.swing.Timer. I use this because it's safer to use with Swing, as it allows me to update the state of the UI from within the context of the Event Dispatching Thread, but doesn't block it (preventing it from updating the screen).

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

The following example uses a concept of a timeline and key frames. That is, at some point in time, something must happen. The timeline then provides the means for blending between those "key" points in time.

我个人喜欢在抽象概念中工作,所以时间线只是在从0到0的百分比,这允许我提供可变的时间跨度。这允许我调整动画的速度而无需改变任何东西。

I, personally, like to work in abstract concepts, so the timeline is simply measured in a percentage from 0-1, which allows me to provide a variable time span. This allows me to adjust the speed of the animation without the need to change anything.

正如你(应该)能够看到的那样,最后两条腿只需要移动一半距离,所以它们更慢比起其他三条腿,所以,从技术上讲,它们只需要一半的时间来完成......但是我会把它留给你来解决数学问题;)

As you (should) be able to see, the last two legs only need to move half the distance, so they are slower than the other three legs, so, technically, they only need half the time to complete...but I'll leave it up to you to nut out the maths for that ;)

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

        }

    }
}

这篇关于在java中以螺旋方式移动图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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