为什么这个AffineTransform旋转方法有效?

时间:2011-07-31 02:35:47

标签: java affinetransform

我一直在编写游戏,以便在java上变得更好。让玩家轮换正常工作我遇到了很多麻烦。我的第一种方法使用了这个

g2.setTransform(AffineTransform.getRotateInstance(radAngle,x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));

然而,这导致所有图像随播放器旋转,从而使拍摄和瞄准完全失效。 我正在研究并看到有人使用此代码让他们成为播放器旋转。

    Graphics2D g2 = (Graphics2D)g;
           AffineTransform oldTransform = g2.getTransform();
    AffineTransform newOne = (AffineTransform)(oldTransform.clone());
    newOne.rotate(radAngle,x_pos + (img.getWidth() / 2),y_pos+ (img.getHeight()  / 2));
    g2.setTransform(newOne);
    g2.drawImage(img, x_pos,y_pos,this);
    repaint();
    g2.setTransform(oldTransform);

这很有效,我没有遇到过同样的问题。但是我不知道为什么。

继承我的完整代码。上面的代码用于paint方法的主体。

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.lang.Math.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;

public class Game extends Applet implements Runnable, KeyListener, MouseMotionListener, MouseListener
{
//pos variables keep track of the current position of the player
int x_pos = 250;
int y_pos = 250;
//speed variables keep track of the speed/how many pixels will be added to position during this iteration of the thread
float x_speed = 0;
float y_speed = 0;
int radius = 25;
//denotes the boundries of the applet
int appletsize_x = 800;
int appletsize_y = 600;
//the x and y variables mark whether a movement key is being pressed thats telling the object to move on
//on of those axes's
int x = 0;
int y = 0;
//variables that will indicate whether one of those keys are being depressed
int up = 0;
int down= 0;
int left = 0;
int right= 0;

int mouse_x;
int mouse_y;
int tracking_angle;
//getting some images.
private BufferedImage dbImage;
private BufferedImage test;
private Graphics dbg;
private  Image curser;
BufferedImage img = null;
BufferedImage round = null;
   double x_dist;
    double y_dist;



//i dont use this AffineTransform, although ill leave it here just incase i decide to use it if i continue working
//on this independently.
AffineTransform at = new AffineTransform();
//the angle of the mouse to the player object.
double radAngle;
public void init()
{


        try {
           URL url = new URL(getCodeBase(), "UFO.png");
           img = ImageIO.read(url);
        } catch (IOException e) {System.out.println("Cant find player image");
    }
                    try {
                       URL url = new URL(getCodeBase(), "round.png");
                       round = ImageIO.read(url);}
         catch (IOException e) {System.out.println("round not loading");}

    setBackground (Color.black);
    setFocusable(true);
    addKeyListener( this );
    curser = getImage(getDocumentBase(), "mouse.png");
    addMouseMotionListener(this);
    addMouseListener(this);
    try
    //changing the curser to the  crosshair image
            {
                Toolkit tk = Toolkit.getDefaultToolkit();
                Cursor c = tk.createCustomCursor( curser,new Point( 5, 5 ), "Cross_Hair" );
                setCursor( c );
            }
            catch( IndexOutOfBoundsException x )
            {System.out.println("Cross_hair");}
}

public class Shot {
    final double angle = radAngle;
    double x_loc;
    double  y_loc;
    double X;
    double Y;

    public Shot(){
        x_loc += x_pos;
        y_loc += y_pos;
        X=Math.cos(radAngle)*5;
        Y=Math.sin(radAngle)*5;
    }

    public void move(){

    x_loc += X;
    y_loc += Y;}
            }
//start the thread
public void start ()
{

    Thread th = new Thread (this);

    th.start ();

}

public void stop()
{

}

public void destroy()
{

}
//cathces the mouseEvent when the mosue is moved.
public void mouseClicked(MouseEvent e){}
public void mousePressed(MouseEvent e){
Shot shoot = new Shot();
shots.add(shoot);}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseMoved(MouseEvent e){
    //get position of mouse
    mouse_x = e.getX();
    mouse_y = e.getY();
    //get the distence from the player to the

    //i calculate the actual angle of the mosue from the player object in radians




    //this exists more just for debugging purposes since radians make no sense to me
    tracking_angle = 90;

    }
public void mouseDragged(MouseEvent e){
    mouse_x = e.getX();
    mouse_y = e.getY();
    Shot shoot = new Shot();
    shots.add(shoot);}

//this method sets the key variables to zero when the keys are released
public void keyReleased(KeyEvent r)
{
    //Right
    if (r.getKeyCode()  == 68 ){
        x = 0;
        left = 0;

        }
    //Left
    if (r.getKeyCode() == 65){
        x = 0;
        right = 0;
        }
    //Up
    if (r.getKeyCode() == 87 ) {
        //y_speed = 0;
        down = 0;}
    //Down
    if (r.getKeyCode() == 83 ) {
        //y_speed = 0;
        up = 0;}
        //move();
}
public void keyTyped(KeyEvent t){}
//changes the variables when a key is pressed so that the player object will move
public void keyPressed(KeyEvent r){


    //right
    if (r.getKeyCode()  == 68 ){
        left = 1;
        }
    //left
    if (r.getKeyCode() == 65){
        right = 1;}
    //Down
    if (r.getKeyCode() == 87 ) {
        down = 1;}
    //Up
    if (r.getKeyCode() == 83) {
        up = 1;}
        //move();
}

//sorta like the body of the thread i think
public void run ()
{


    Thread.currentThread().setPriority(Thread.MIN_PRIORITY);


    while (true)
    {
        System.out.println(Math.tan(radAngle)/1);
        x_dist = mouse_x - x_pos;
        y_dist = mouse_y - y_pos;

        radAngle = Math.atan2(y_dist , x_dist);
        //if(tracking_angle < 0){
            //tracking_angle = absT
        if (left  == 1 && x_speed < 11){
            x = 0;
            x_speed += 1;
            }
        //Right
        if (right == 1 && x_speed > -11){
            x = 0;
             x_speed -= 1;
            }
        //Down
        if (down == 1  && y_speed > -11) {
            y_speed -= 1;}
        //Up
        if (up == 1  && y_speed < 11) {
        y_speed += 1;}
    if( x == 0 && x_speed > 0){
        x_speed -=.2;}
    if( x == 0 && x_speed < 0){
        x_speed +=.2;}
    if( y == 0 && y_speed > 0){
        y_speed -=.2;}
    if( y == 0 && y_speed < 0){
        y_speed +=.2;}



        if (x_pos > appletsize_x - radius && x_speed > 0)
        {

            x_pos = radius;
        }

        else if (x_pos < radius && x_speed < 0)
        {

            x_pos = appletsize_x + radius ;
        }

        if (y_pos > appletsize_y - radius && y_speed > 0){
            y_speed = 0;}
        else if ( y_pos < radius && y_speed < 0  ){
                y_speed = 0;}

        x_pos += (int)x_speed;
        y_pos += (int)y_speed;


        repaint();

        try
        {

            //tells the thread to wait 15 milliseconds util it executes again.
            Thread.sleep (15);


        }
        catch (InterruptedException ex)
        {

        }


        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    }
}


public void update (Graphics g)
{

    if (dbImage == null)
    {
        dbImage = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_RGB);
        dbg = dbImage.getGraphics ();
    }


    dbg.setColor (getBackground ());
    dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);


    dbg.setColor (getForeground());
    paint (dbg);
    shot_draw(dbg);


    g.drawImage (dbImage, 0, 0, this);



}

ArrayList<Shot> shots = new ArrayList<Shot>();
double last_angle = 1000;

public void paint (Graphics g){

    Graphics2D g2 = (Graphics2D)g;
    AffineTransform oldTransform = g2.getTransform();
    AffineTransform newOne = (AffineTransform)(oldTransform.clone());
    newOne.rotate(radAngle,x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2));
    g2.setTransform(newOne);
    g2.drawImage(img, x_pos,y_pos,this);
    repaint();
    g2.setTransform(oldTransform);
   // g2.setTransform(AffineTransform.getRotateInstance(radAngle,x_pos +   (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));
    //g2.getTransform().setToIdentity();


}
public void shot_draw(Graphics g){

    Graphics2D g2 = (Graphics2D)g;
//        Shot shoot = new Shot();
//        shots.add(shoot);
    for(Shot i: shots){
        g2.drawImage(round,(int)i.x_loc+40,(int)i.y_loc+40,this);
        i.move();}


        }}

以下是我正在使用的图片:http://img813.imageshack.us/img813/2466/ufoq.png

2 个答案:

答案 0 :(得分:1)

这是有道理的,因为如果你没有将Graphics对象的AffineTransform重置回其基线,它将使用新的变换来绘制包括所有图像在内的所有内容。我不明白为什么你在repaint()方法中打电话给paint。你不应该这样做。

答案 1 :(得分:1)

AffineTransform对象通过调用Graphics2D连接到setTransform对象。连接后,变换会导致使用Graphics2D对象绘制的每个对象都应用相同的变换(在本例中为旋转),直到将新的AffineTransform分配给Graphics2D为止。通过另一个setTransform调用对象。您找到的示例代码已保存旧转换(可能编码正常的非旋转状态)

AffineTransform oldTransform = g2.getTransform();

然后代码创建了旋转变换并将其连接到Graphics2D(现在绘制的所有对象都将旋转,直到分配新的变换),然后画出需要旋转的一个对象(因此将新创建的旋转变换应用于它),然后通过以下方式将原始的非旋转变换恢复为Graphics2D对象

g2.setTransform(oldTransform);

这样,将应用于后续对象的变换将是原始的非旋转变换。