简体   繁体   English

在Java中以螺旋方式移动图像

[英]Move image in a spiral fashion in 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);
    }
}

The if(draw) statement is activated by something else. if(draw)语句被其他东西激活。 How do I go about moving the image. 我该如何移动图像。 Do I just increment the x and the y differently at different points? 我只是在不同点以不同的方式增加x和y吗?

** 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 它从左下角到左上角,右上角,右下角到屏幕底部中心(中心)到屏幕中心(中心)

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. 通常,我会使用诸如Timing Framework (或TridentUniversal Tween Engine )之类的动画作为基础,这些动画为缓入和缓出提供了更好的支持。

The following example just makes uses of a simple javax.swing.Timer . 以下示例仅使用一个简单的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). 我之所以使用它,是因为它与Swing一起使用更安全,因为它允许我从事件调度线程的上下文中更新UI的状态,但不会阻止它(防止它更新屏幕)。

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. 然后,时间轴提供了在这些“关键”时间点之间进行融合的方法。

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. 我个人比较喜欢抽象概念,因此时间线只是以0-1的百分比来衡量,这使我可以提供可变的时间跨度。 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;
            }

        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM