Java-原地旋转图像

Java-原地旋转图像,java,rotation,image-rotation,Java,Rotation,Image Rotation,我有一个坦克加农炮层,它应该朝着鼠标位置旋转,我已经用下面的代码完成了: double theta = Math.atan2(point.getY() - center.getY(), point.getX() - center.getX()); 然后我相应地旋转图形对象的变换。这是可行的,但大炮会绕着大炮的中心旋转。当旋转发生时,我希望加农炮的底座保持在原位。我尝试了很多不同的位置来旋转,但我没有一个可以保持它的底部位置。我想我必须在旋转后将图形对象转换到加农炮的底部,但我不知道如何转换。我

我有一个坦克加农炮层,它应该朝着鼠标位置旋转,我已经用下面的代码完成了:

double theta = Math.atan2(point.getY() - center.getY(), point.getX() - center.getX());
然后我相应地旋转图形对象的变换。这是可行的,但大炮会绕着大炮的中心旋转。当旋转发生时,我希望加农炮的底座保持在原位。我尝试了很多不同的位置来旋转,但我没有一个可以保持它的底部位置。我想我必须在旋转后将图形对象转换到加农炮的底部,但我不知道如何转换。我的两层加农炮:


如您所见,底座(浅绿色部分)必须保持在原来的位置。如何实现这一点?

您的公式只显示了如何计算角度-您的问题似乎是“如何围绕指定点旋转图像”。为此,我建议使用
AffineTransform
s(矩阵数学)。一个好的起点是:

一些示例代码:

Graphics2D g; //<- you should have this in your code somewhere
AffineTransform at = new AffineTransform(); 
at.rotate(theta, centerX, centerY); //<- your question: rotate around specified point
g.setTransform(at); //<- tell the graphics to transform before painting
g.drawImage(...); //<- draws transformed image

使用矩阵功能非常强大,因为您可以将平移、旋转、剪切、镜像等功能结合起来。不仅在二维,而且在三维。也许有一天你的坦克会离开这个平坦的世界,成为一个体积模型…

好吧,假设炮塔和基地是分开的图像,炮塔的大小与坦克的大小不一样(因为这样它就变得复杂了……实际上更复杂了:p)

您可以使用
仿射变换
并合成变换

    // This is the x/y position of the top, at the top/left point,
    // I've placed it at the center of my screen, but you get the idea
    double x = (getWidth() - base.getWidth()) / 2d;
    double y = (getHeight() - base.getHeight()) / 2d;

    // Translate the location to the x/y, this makes the top/left 0x0...
    // much easier to deal with...
    AffineTransform at = AffineTransform.getTranslateInstance(x, y);
    g2d.setTransform(at);
    // Draw the base...
    g2d.drawImage(base, 0, 0, this);

    // Offset the turret, in my testing, this was 8x8 from the bases
    // top/left
    at.translate(8, 8);
    if (targetPoint != null) {
        // Calculate the delta between the mouse and the center point
        // of the turret, this is in screen coordinates and not
        // translated coordinates
        double deltaX = (x + 8) - targetPoint.x;
        double deltaY = (y + 8) - targetPoint.y;

        // Calculate the rotation required to point at the mouse
        // Had to apply an offset to allow for the default orientation
        // of the tank...
        double rotation = Math.atan2(deltaY, deltaX) + Math.toRadians(180d);
        // Rotate around the anchor point of the turret
        // Remember, we've translated so the top/left (0x0) is now the
        // turrets default position
        at.rotate(rotation, 4, 4);
    }
    // Transform the Graphics context
    g2d.setTransform(at);
    // Paint the turret
    g2d.drawImage(turret, 0, 0, this);
}
g2d.dispose();
因为我去努力

我的资产

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.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FollowMe {

    public static void main(String[] args) {
        new FollowMe();
    }

    public FollowMe() {
        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 Point targetPoint;
        private BufferedImage turret;
        private BufferedImage base;

        public TestPane() {
            addMouseMotionListener(new MouseAdapter() {

                @Override
                public void mouseMoved(MouseEvent e) {
                    targetPoint = e.getPoint();
                    repaint();
                }

            });
            try {
                base = ImageIO.read(getClass().getResource("/Base.png"));
                turret = ImageIO.read(getClass().getResource("/Turret.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
            g.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
            if (base != null) {
                double x = (getWidth() - base.getWidth()) / 2d;
                double y = (getHeight() - base.getHeight()) / 2d;
                // Test line from center of tank to mouse poisition
                if (targetPoint != null) {
                    g2d.draw(new Line2D.Double((x + 12), (y + 12), targetPoint.x, targetPoint.y));
                }
                AffineTransform at = AffineTransform.getTranslateInstance(x, y);
                g2d.setTransform(at);
                g2d.drawImage(base, 0, 0, this);
                at.translate(8, 8);
                if (targetPoint != null) {
                    double deltaX = (x + 8) - targetPoint.x;
                    double deltaY = (y + 8) - targetPoint.y;

                    double rotation = Math.atan2(deltaY, deltaX) + Math.toRadians(180d);
                    at.rotate(rotation, 4, 4);
                }
                g2d.setTransform(at);
                g2d.drawImage(turret, 0, 0, this);
            }
            g2d.dispose();
        }

    }

}


查看更多详细信息

假设“坦克”和“加农炮”是独立的实体,您可以指定图像应围绕其旋转的定位点不确定这是否有帮助,但您是否尝试过
Math.atan2(point.getY(),point.getX())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.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FollowMe {

    public static void main(String[] args) {
        new FollowMe();
    }

    public FollowMe() {
        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 Point targetPoint;
        private BufferedImage turret;
        private BufferedImage base;

        public TestPane() {
            addMouseMotionListener(new MouseAdapter() {

                @Override
                public void mouseMoved(MouseEvent e) {
                    targetPoint = e.getPoint();
                    repaint();
                }

            });
            try {
                base = ImageIO.read(getClass().getResource("/Base.png"));
                turret = ImageIO.read(getClass().getResource("/Turret.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
            g.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
            if (base != null) {
                double x = (getWidth() - base.getWidth()) / 2d;
                double y = (getHeight() - base.getHeight()) / 2d;
                // Test line from center of tank to mouse poisition
                if (targetPoint != null) {
                    g2d.draw(new Line2D.Double((x + 12), (y + 12), targetPoint.x, targetPoint.y));
                }
                AffineTransform at = AffineTransform.getTranslateInstance(x, y);
                g2d.setTransform(at);
                g2d.drawImage(base, 0, 0, this);
                at.translate(8, 8);
                if (targetPoint != null) {
                    double deltaX = (x + 8) - targetPoint.x;
                    double deltaY = (y + 8) - targetPoint.y;

                    double rotation = Math.atan2(deltaY, deltaX) + Math.toRadians(180d);
                    at.rotate(rotation, 4, 4);
                }
                g2d.setTransform(at);
                g2d.drawImage(turret, 0, 0, this);
            }
            g2d.dispose();
        }

    }

}