Почему этот метод вращения AffineTransform работает? - PullRequest
2 голосов
/ 31 июля 2011

Я программировал игру, чтобы стать лучше в 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);

Это прекрасно работает, и у меня нет тех же проблем, которые у меня были раньше.Однако я не знаю почему.

Вот мой полный код.Код выше для тела метода рисования.

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 ]

1 голос
/ 31 июля 2011

Объект AffineTransform подключен к объекту Graphics2D через вызов setTransform.После подключения преобразование заставляет каждый объект, нарисованный с использованием объекта Graphics2D, рисовать с тем же преобразованием (в данном случае вращением), примененным к нему, пока новый AffineTransform не будет присвоен объекту Graphics2D посредством другого вызоваsetTransform.Пример кода, который вы нашли , сохранил старое преобразование (которое предположительно кодирует нормальное, не повернутое состояние) с помощью

AffineTransform oldTransform = g2.getTransform();

Затем код создал преобразование вращения и подключил его к Graphics2D (теперь все нарисованные объекты будут вращаться до тех пор, пока не будет назначено новое преобразование), затем рисуется один объект, который нужно было повернуть (для которого применено вновь созданное преобразование вращения), а затем восстанавливаетсяисходное невращающееся преобразование к объекту Graphics2D посредством:

g2.setTransform(oldTransform);

Таким образом, преобразование, которое будет применено к последующим объектам, будет исходным невращающимся преобразованием.

1 голос
/ 31 июля 2011

Это имеет смысл, поскольку, если вы не сбросите AffineTransform объекта Graphics обратно к его базовой линии, он будет использовать новое преобразование для рисования всего, включая все изображения. Однако я не понимаю, почему у вас есть вызов repaint() из вашего paint метода. Ты не должен этого делать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...