到达指定位置后如何旋转矩形?

时间:2015-09-04 07:08:49

标签: java swing rotation awt graphics2d

我想在例如旋转矩形时y位置达到指定位置。我想在一个交叉点上表现为一个长方形的汽车 - 只需转动,例如对。我更喜欢旋转并继续。

草案代码如下:

Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(new Color(150, 150, 0));

//1. when rectangle achieve 500 on y dimension just rotate left/right
if(y==500) {
    _rotate = true;
    g2d.rotate(Math.toRadians(90.));
}
if(_rotate) { //if rotate, continue way on x dimension
    ++x ;
    g2d.fillRect(x, y, 20, 40);
} else { //else go to the north
    --y;
    g2d.fillRect(x, y, 20, 40);
}

1 个答案:

答案 0 :(得分:3)

您的问题中缺少很多信息。

为了能够旋转形状,你需要知道一些事情,你需要知道它的当前位置和它的下一个目标位置,然后你可以简单地计算这两个点之间的角度。

那么问题就变成了,你如何计算这些位置。有很多方法可以实现这一点,以下是一个简单的路径跟踪过程。

首先,我们生成一个我们需要遵循的路径,我们使用Shape API来计算路径上的点。我们使用简单的基于时间的动画(而不是通过点循环,我们通过计算动画播放的时间量除以我们想要的时间来计算沿路径的进度)并选择最佳点符合我们目前的进展。

我们使用AffineTransform来旋转玩家形状,并将结果Shape转换为所需位置。缓解

FollowMe

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class PathFollow {

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

    public PathFollow() {
        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 {

        private Shape pathShape;
        private List<Point2D> points;
        private Shape car;

        private double angle;
        private Point2D pos;
        private int index;

        protected static final double PLAY_TIME = 5000; // 5 seconds...

        private Long startTime;

        public TestPane() {

            Path2D path = new Path2D.Double();
            path.moveTo(0, 200);
            path.curveTo(100, 200, 0, 100, 100, 100);
            path.curveTo(200, 100, 0, 0, 200, 0);

            pathShape = path;

            car = new Rectangle(0, 0, 10, 10);

            points = new ArrayList<>(25);
            PathIterator pi = pathShape.getPathIterator(null, 0.01);
            while (!pi.isDone()) {
                double[] coords = new double[6];
                switch (pi.currentSegment(coords)) {
                    case PathIterator.SEG_MOVETO:
                    case PathIterator.SEG_LINETO:
                        points.add(new Point2D.Double(coords[0], coords[1]));
                        break;
                }
                pi.next();
            }

//          System.out.println(points.size());
//          pos = points.get(0);
//          index = 1;
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {

                    if (startTime == null) {
                        startTime = System.currentTimeMillis();
                    }
                    long playTime = System.currentTimeMillis() - startTime;
                    double progress = playTime / PLAY_TIME;
                    if (progress >= 1.0) {
                        progress = 1d;
                        ((Timer) e.getSource()).stop();
                    }

                    int index = Math.min(Math.max(0, (int) (points.size() * progress)), points.size() - 1);

                    pos = points.get(index);
                    if (index < points.size() - 1) {
                        angle = angleTo(pos, points.get(index + 1));
                    }
                    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();
            g2d.draw(pathShape);

            AffineTransform at = new AffineTransform();

            if (pos != null) {

                Rectangle bounds = car.getBounds();
                at.rotate(angle, (bounds.width / 2), (bounds.width / 2));

                Path2D player = new Path2D.Double(car, at);

                g2d.translate(pos.getX() - (bounds.width / 2), pos.getY() - (bounds.height / 2));
                g2d.draw(player);

            }

            g2d.dispose();
        }

        // In radians...
        protected double angleTo(Point2D from, Point2D to) {
            double angle = Math.atan2(to.getY() - from.getY(), to.getX() - from.getX());
            return angle;
        }

    }

}