Существует много информации, которая отсутствует из вашего вопроса.
Для того, чтобы повернуть фигуру, вам нужно знать несколько вещей, вам нужно знать, что это текущая позиция, и это следующая целевая позиция, тогда вы можете просто вычислить угол между этими двумя точками.
Вопрос тогда, как вы рассчитываете эти позиции. Существует множество способов достижения этого, следующий простой процесс, следующий за процессом.
Во-первых, мы генерируем путь, который нам нужно выполнить, мы используем API Shape
для вычисления точек вдоль пути. Мы используем простую анимацию, основанную на времени (а точнее, зацикливание по точкам, мы вычисляем прогресс по пути, вычисляя количество времени, в которое играли анимацию, деленное на количество времени, которое мы хотим принять) и выбираем точку, которая лучше всего соответствует нашему текущему прогрессу.
Мы используем AffineTransform
для поворота формы игрока и перевода полученного результата Shape
в нужное положение. Ease
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;
}
}
}
* "Как вращать прямоугольник после определенного времени?" * Можете ли вы быть более конкретным? Я не могу понять, если вы спрашиваете, какой из двух предложенных методов лучше, или как заставить рендеринг обновляться через определенное время или .. ?? –
Вы могли бы взглянуть на [это] (http://stackoverflow.com/questions/26898536/moving-jlabel-to-other-jlabels-gui/26899099#26899099) и [это] (http: // stackoverflow. com/questions/28619150/move-image-in-a-spiral-fashion-in-java/28619554 # 28619554), которые предоставляют примеры анимаций, основанных на временной шкале, например [this] (http://stackoverflow.com/questions/31958932/how-do-i-rotate-objects-images-independent-in-java/31959926 # 31959926), который имеет вращающиеся прямоугольники. Возможно, вам также захочется провести некоторое исследование пути – MadProgrammer