How to animate from one x,y coordinate to another? (Java/Processing)

后端 未结 2 1436
天命终不由人
天命终不由人 2020-12-12 01:54

I am making a simple animation in Processing. I want to animate an image from its starting point to a defined x,y value on the screen.

I have 2 methods, update

相关标签:
2条回答
  • 2020-12-12 02:14

    If you are using Processing 2.0 this can be done via Ani library. To get same output like @MadProgrammer you just setup basic sketch with Ani.init(this) then in draw() function move box via translate() and rotate it via rotate() functions. Whole animation begins after first mouse click.

    import de.looksgood.ani.*;
    import de.looksgood.ani.easing.*;
    
    float posX = 25, posY = 25;
    float angleRotation = 0;
    
    void setup () {
     size (200, 200);
     background (99);  
     noFill ();
     stroke (0);
     Ani.init(this);
     frameRate (30);
     rectMode(CENTER); 
    }
    
    void draw () {
      background (225);  
      translate(posX, posY);
      rotate(radians(angleRotation));
      rect(0, 0, 50, 50);    
    }
    
    void mousePressed() {
      Ani.to(this, 5, "posX", 175, Ani.LINEAR);
      Ani.to(this, 5, "posY", 175, Ani.LINEAR);
      Ani.to(this, 5, "angleRotation", 360, Ani.LINEAR);
    }
    

    Manually you can get similar result just by increasing posX, posY and angleRotation within draw loop.

    0 讨论(0)
  • 2020-12-12 02:15

    This is a very basic example of time period based animation

    It will animate a Animatable object over a 5 second period. You could simply use a List and update/paint multiple objects simultaneously if you wanted to get fancy.

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.geom.AffineTransform;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class AnimationTest {
    
        public static void main(String[] args) {
            new AnimationTest();
        }
    
        public AnimationTest() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public interface Animatable {
    
            public void update(double progress);
            public void draw(Graphics2D g2d);
    
        }
    
        public static class FlyingSquiral implements Animatable {
    
            private final Point startPoint;
            private final Point targetPoint;
            private final double startAngel;
            private final double targetAngel;
    
            private Point location;
            private double angle;
    
            public FlyingSquiral(Point startPoint, Point targetPoint, double startAngel, double targetAngel) {
                this.startPoint = startPoint;
                this.targetPoint = targetPoint;
                this.startAngel = startAngel;
                this.targetAngel = targetAngel;
    
                location = new Point(startPoint);
                angle = startAngel;
            }
    
            @Override
            public void update(double progress) {
    
                location.x = (int)Math.round(startPoint.x + ((targetPoint.x - startPoint.x) * progress));
                location.y = (int)Math.round(startPoint.y + ((targetPoint.y - startPoint.y) * progress));
                angle = startAngel + ((targetAngel - startAngel) * progress);
    
            }
    
            @Override
            public void draw(Graphics2D g2d) {
    
                Graphics2D clone = (Graphics2D) g2d.create();
    
                clone.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                clone.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                clone.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                clone.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                clone.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                clone.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                clone.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                clone.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
                AffineTransform at = new AffineTransform();
                at.translate(location.x, location.y);
                at.rotate(Math.toRadians(angle), 25, 25);
                clone.setTransform(at);
                clone.draw(new Rectangle(0, 0, 50, 50));
                clone.dispose();
    
            }
    
        }
    
        public static class TestPane extends JPanel {
    
            public static final long DURATION = 5000;
            private long startTime;
            private boolean started = false;
    
            private FlyingSquiral squiral;
    
            public TestPane() {
                squiral = new FlyingSquiral(
                        new Point(0, 0), 
                        new Point(150, 150), 
                        0d, 360d);
                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (!started) {
                            startTime = System.currentTimeMillis();
                            started = true;
                        }
                        long time = System.currentTimeMillis();
                        long duration = time - startTime;
                        if (duration > DURATION) {
                            duration = DURATION;
                            ((Timer)e.getSource()).stop();
                        }
                        double progress = (double)duration / (double)DURATION;
                        squiral.update(progress);
                        repaint();
                    }
                });
                timer.start();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                squiral.draw(g2d);
                g2d.dispose();
            }
        }
    
    }
    

    Equally, you could use a constraint based animation, where by the object keeps moving until it meets it's required constraints (angel/position). Each has pros and cons.

    I prefer a time period based approach as it allows me to apply different transformations without needing to care about pre-calculating the delta. Try this, change the target angel from 360 to 720 and run it again.

    I also prefer to use an animation library, as they add additional features, like interpolation, allowing to change the speed of the animation at certain points in time without changing the duration, this would allow you to do things like slow in, slow out (ramp up/out) effects, making the animation more appealing.

    Take a look at...

    • Timing Framework
    • Trident
    • Unviersal Tween Engine
    0 讨论(0)
提交回复
热议问题