2015-06-30 240 views
2

旋轉圖像我應該向鼠標的位置,這是我用下面的代碼進行旋轉坦克大炮層:爪哇 - 到位

double theta = Math.atan2(point.getY() - center.getY(), point.getX() - center.getX()); 

然後轉動圖形對象的相應轉變。這可以工作,但大炮圍繞大炮的中心旋轉。當旋轉發生時,我想讓大炮的基座保持在原位。我嘗試了許多不同的位置來旋轉,但我無法獲得一個能夠保持其基礎的位置。我認爲,我必須把旋轉到大炮的基礎應該是後圖形對象,但我不知道怎麼辦。我有兩層炮:enter image description here

正如你可以看到,基地(淺綠色部分)必須留在它的位置。我怎樣才能做到這一點?

+0

假設「坦克」和「大炮」是獨立的實體,您可以指定圍繞錨點圖像應該旋轉 – MadProgrammer

+0

不知道這是否會有所幫助,但你有沒有嘗試'Math.atan2(point.getY(),point.getX());' – Phoenix

回答

3

好吧,假設炮塔和基座是分開的圖像,並且炮塔與坦克尺寸不一樣(因爲它會變成複雜....更多然後它實際上是:P)

您可以使用AffineTransform和化合物轉變......

// 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(); 

而且因爲我去努力......

我資產...

BaseTurret

Tank

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

    } 

} 

看一看Transforming Shapes, Text, and Images更多細節

+0

哇,你在幾分鐘內寫了一個小遊戲wi第四個花哨的圖形。你真的是_mad_程序員:-) – chris

+0

@chris其實昨天做了這樣的事情,但有更多的層次:P – MadProgrammer

+0

謝謝,完美的作品! – MCMastery

1

公式只能說明你是如何計算的角度 - 你的問題似乎是「如何圍繞指定的點旋轉圖像」。爲此,我會建議使用AffineTransform s(矩陣數學)。開始的好點在這裏:http://docs.oracle.com/javase/tutorial/2d/advanced/transforming.html

一些示例代碼:

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 

如果你更深入AffineTransform.rotate(...)看到,起初翻譯而成,然後旋轉。第三個轉換是具有負x/y值的翻譯。

這是很好的舊代碼從太陽:

public void rotate(double theta, double anchorx, double anchory) { 
    // REMIND: Simple for now - optimize later 
    translate(anchorx, anchory); 
    rotate(theta); 
    translate(-anchorx, -anchory); 
} 

與矩陣的工作是非常強大的,你可以結合平移,旋轉,剪切,鏡子和諸如此類的東西。不僅在2D中,而且在3D中。也許你的坦克有一天會離開平坦的世界,併成爲一個容積模型...