Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
173 views
in Technique[技术] by (71.8m points)

java - How to rotate a rectangle after reaching specified position?

I would like to rotate a rectangle when e.g. y position achieve specified position. I would like to behave a rectangle as a car on a junction - just turn e.g. right. I prefer just rotate and continue.

A draft code looks like that:

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);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There is a lot of information which is missing from your question.

In order to be able to rotate a shape, you need to know a few things, you need to know it's current position and it's next target position, then you can simply calculate the angle between these two points.

The question then becomes, how do you calculate these positions. There are plenty of ways you might achieve this, the following is a simple path following process.

First, we generate a path which we need to follow, we use the Shape API to calculate the points along the path. We use a simple time based animation (rather the looping through the points, we calculate the progress along the path by calculating amount of time the animation has been playing divided by the amount of time we want it to take) and picking the point which best matches our current progress.

We use a AffineTransform to rotate the player shape and the translate the resulting Shape to the required position. Ease

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

    }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...