围绕其中心旋转移动的形状

我正在用Java制作2D游戏,玩家通过障碍物引导多边形。 多边形上下移动,游戏世界左右滚动。 我需要多边形围绕其中心旋转,但由于它经常被平移,所以它围绕移动旋转。 尝试将其转换回原始中心,旋转它并将其翻译回来并不起作用。 如何获得形状的中心?

以下是我在2ms计时器上的运动计算:

@Override public void actionPerformed(ActionEvent e) { double theta = angleRad+90; if (up == true) { if (accelerating == false) { time2 = 0; moveX0 = moveX; moveY0 = moveY; accelerating = true; } time1++; double t = time1/500; if (accCount % 10 == 0) { DronePilot.velocity++; } moveX = moveX0 + velX*Math.cos(theta)*t; moveY = moveY0 + velY*Math.sin(theta)*t-(1/2d)*g*Math.pow(t, 2); velX = (DronePilot.velocity)*Math.cos(theta); velY = (DronePilot.velocity)*Math.sin(theta)-g*(t); accCount++; } else if (up == false){ if (accelerating == true) { time1 = 0; moveX0 = moveX; moveY0 = moveY; accelerating = false; } time2++; double t = time2/500; moveX = moveX0 + velX*Math.cos(theta)*t; moveY = moveY0 + velY*Math.sin(theta)*t-(1/2d)*g*Math.pow(t, 2); accCount = 0; } if (left == true) { angleCount++; if (angleCount % 2 == 0) { angleDeg++; } angleRad = Math.toRadians(angleDeg); } else if (right == true) { angleCount--; if (angleCount % 2 == 0) { angleDeg--; } angleRad = Math.toRadians(angleDeg); } repaint(); } } 

这是我的paintComponent方法:

 @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2D = (Graphics2D)g; Graphics g2 = g.create(); Graphics2D copy = (Graphics2D)g2; copy.rotate(-angleRad, xPos, yPos); copy.translate(0, -moveY); g2D.translate(-moveX, 0); copy.draw(player.shape); for (Rectangle2D.Double r: DronePilot.rocksFloorArray) { g2D.draw(r); } for (Rectangle2D.Double r: DronePilot.rocksCeilArray) { g2D.draw(r); } for (Rectangle2D.Double r: DronePilot.roomsArray) { g2D.draw(r); } } 

其中(xPos,yPos)是屏幕的中心。

转换(通常)复合

 public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2D = (Graphics2D)g; Graphics g2 = g.create(); Graphics2D copy = (Graphics2D)g2; copy.rotate(-angleRad, xPos, yPos); copy.translate(0, -moveY); g2D.translate(-moveX, 0); copy.draw(player.shape); for (Rectangle2D.Double r: DronePilot.rocksFloorArray) { g2D.draw(r); } for (Rectangle2D.Double r: DronePilot.rocksCeilArray) { g2D.draw(r); } for (Rectangle2D.Double r: DronePilot.roomsArray) { g2D.draw(r); } } 

在上面的代码中,您将翻译原始Graphics上下文和copy 。 在这种情况下, copy不会受到原件的影响,原件也不会受到copy影响。但是,原始上下文是共享资源,因为您没有重置翻译,您将继续获得每次翻译的上下文(复合)。

作为一般经验法则,在副本上进行所有转换并在完成后处理它。

例如…

 Graphics2D g2d = (Graphics2D)g.create(); AffineTransform at = AffineTransform.getTranslateInstance(playerPoint.x, playerPoint.y); at.rotate(Math.toRadians(angle), player.getBounds2D().getCenterX(), player.getBounds2D().getCenterY()); g2d.setTransform(at); g2d.setColor(Color.RED); g2d.fill(player); g2d.setColor(Color.BLACK); g2d.draw(player); g2d.dispose(); 

这基本上将对象的位置转换为玩家的位置,然后围绕对象的中心旋转对象

您也可以应用一个转换,创建该上下文的副本并应用另一个转换,这将变得复杂(因此您可以translate一个上下文,复制它,然后rotate副本,第一个转换仍将应用于副本)

这个令人难以置信的简单例子演示了两个基

  1. 使用Graphics上下文和AffineTransform来转换和旋转玩家对象(关于它的中心点)
  2. 使用Path2D生成变换后的形状(此示例生成两个对象,但您可以使用单个AffineTransform平移和旋转并应用一次)。

在这两种情况下,它们都不会影响原始形状

 import java.awt.Color; 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.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.awt.geom.Rectangle2D; import java.util.Random; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame(); 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 player; private Point playerPoint; private float angle; private float deltaZ = 1.0f; private int deltaX, deltaY; public TestPane() { player = new Rectangle(0, 0, 20, 20); playerPoint = new Point(80, 80); Random rnd = new Random(); deltaX = 1; deltaY = -1; Timer timer = new Timer(5, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { playerPoint.x += deltaX; playerPoint.y += deltaY; Shape rotatedPlayer = rotatedAndTranslatedPlayer(); Rectangle2D bounds = rotatedPlayer.getBounds2D(); if (bounds.getX() < 0.0) { playerPoint.x = (int)(bounds.getX() * -1); deltaX *= -1; } else if (bounds.getX() + bounds.getWidth() >= getWidth()) { playerPoint.x = getWidth() - (int)bounds.getWidth(); deltaX *= -1; } if (bounds.getY() < 0) { playerPoint.y = 0; deltaY *= -1; } else if (bounds.getY() + bounds.getHeight() > getHeight()) { playerPoint.y = getHeight() - (int)bounds.getHeight(); deltaY *= -1; } angle += deltaZ; repaint(); } }); timer.start(); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } protected Shape rotatedAndTranslatedPlayer() { Path2D.Double rotated = new Path2D.Double(player, AffineTransform.getRotateInstance( Math.toRadians(angle), player.getBounds2D().getCenterX(), player.getBounds2D().getCenterY())); return new Path2D.Double(rotated, AffineTransform.getTranslateInstance(playerPoint.x, playerPoint.y)); } // Simply paints the "area" that the player takes up when it's rotated and // translated protected void paintAutoTranslatedShape(Graphics2D g2d) { g2d.setColor(Color.DARK_GRAY); g2d.fill(rotatedAndTranslatedPlayer().getBounds2D()); } // Uses a AffineTransform to translate and rotate the player protected void paintPlayer(Graphics2D g2d) { AffineTransform at = AffineTransform.getTranslateInstance(playerPoint.x, playerPoint.y); at.rotate(Math.toRadians(angle), player.getBounds2D().getCenterX(), player.getBounds2D().getCenterY()); g2d.setTransform(at); g2d.setColor(Color.RED); g2d.fill(player); g2d.setColor(Color.BLACK); g2d.draw(player); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); paintAutoTranslatedShape(g2d); g2d.dispose(); g2d = (Graphics2D) g.create(); paintPlayer(g2d); g2d.dispose(); } } } 

在openGL中,我们使用pushMatrix()popMatrix()保存转换状态。 这里他们的等价物是Graphics.create()Graphics.dispose()

 Graphics g1 = g.create(); //do transformations g1.dispose(); Graphics g2 = g.create(); //do other stuff g2.dispose();