【问题标题】:How to rotate a rectangle after reaching specified position?到达指定位置后如何旋转矩形?
【发布时间】:2015-11-30 06:14:52
【问题描述】:

我想旋转一个矩形,例如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);
}

【问题讨论】:

  • “如何在指定时间后旋转一个矩形?” 你能说得更具体点吗?我不知道您是在问两种提议的方法中哪一种更好,或者如何使渲染在一段时间后更新,或者.. ??
  • 您可以查看thisthis,它们提供了基于时间线的动画示例,例如具有旋转矩形的this。您可能还想对路径跟踪进行一些研究

标签: java swing rotation awt graphics2d


【解决方案1】:

您的问题缺少很多信息。

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

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

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

我们使用AffineTransform 来旋转玩家形状并将生成的Shape 转换为所需的位置。轻松

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

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多