当前位置: 首页 > 面试题库 >

围绕其中心旋转运动形状

曾新立
2023-03-14
问题内容

我正在用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. 使用a 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();
        }

    }
}


 类似资料:
  • 如题所述,我想知道如何围绕中心旋转绘制的矩形。 我目前正在使用以下代码: 现在,旋转发生在2D空间中,但我似乎无法集中矩形的旋转。相反,矩形一直围绕全局点0,0旋转。 我想我的旋转和平移设置不正确或顺序不正确。 我不想是什么阻止此代码产生所需的输出。任何建议和答案将不胜感激。 谢谢

  • 我在下面有一个类,我将其附加到一个对象上,以使其围绕其轴旋转。我把雪碧的枢轴通过检查员送来了。 这正是我想要的效果,但是我遇到的问题是,每当我触摸并拖动它,然后再次触摸并拖动它,它就会捕捉到一个新的位置。 我想让它做的是,当它旋转,然后再次旋转时,精灵保持其相同的旋转,而不是捕捉到一个新的位置,我想精灵的角度重置为0。接下来,我想让角度持续旋转。所以如果我朝正方向旋转,角度应该在正方向上不断增加,

  • 我有两个矩形,其中一个是另一个的剪裁。现在我想围绕剪切矩形的中心旋转较大的矩形并调整x / y值。 如何计算旋转后的新x/y值? 我只想绕着小盒子的中心旋转大盒子的x/y。因此,较大盒子的x/y点相对于较小盒子的顶部/左侧点。我有小盒子的宽度和高度,所以我可以计算大盒子相对于小盒子中心的x/y点。旋转的角度以度为单位。旋转可以是任何角度,例如10度。

  • 问题内容: 有没有一种简单的方法可以围绕图片中心旋转图片?我首先使用了AffineTransformOp。看起来很简单,而且需要,并且在一个整洁的Google会话中为矩阵找到正确的参数。所以我认为… 我的结果是这样的: 如果您忽略旋转90度的倍数的情况,这非常简单(sin()和cos()无法正确处理)。该解决方案的问题在于,它围绕图片左上角的(0,0)坐标点进行变换,而不是围绕图片中心进行正常的变

  • 我试着绕着它的中心旋转一个矩形。使用GraphicsContext ie gc将旋转绘制到画布上。这是我的绘图代码。 这会将矩形移动到其中心,然后围绕其左上角点旋转矩形。我试着把两边的长度和宽度减半,但那只会让它飞得到处都是。我数学不好也许这里有更好的人能告诉我我做错了什么。 如果需要的话,我还存储了矩形的所有四个点(角)。 谢了乔

  • 我刚开始使用JavaFX,有一个问题。在我的项目中,我想使用旋转矩形。但矩形只围绕其中心旋转,我希望它围绕其左上角旋转。 就像这张照片(从这里开始): 下面是我的项目中的一些代码: 在这种情况下,如果按下箭头键,矩形会旋转。