Reputation: 21
Ive been programming a game just to become better at java. I had been having alot of trouble with getting the player rotation to work correctly. My first method used this
g2.setTransform(AffineTransform.getRotateInstance(radAngle,x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));
However this caused all images to rotate with the player thus making shooting and aiming completely disfunctional. i was researching and saw someone use this code to make they're player rotate.
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);
This works great and i dont have the same problems i had before. However i dont know why.
Heres my full code. The code above is for the body of the paint method.
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();}
}}
Here are the images I'm using:
Upvotes: 2
Views: 2847
Reputation: 2744
The AffineTransform
object is connected to the Graphics2D
object via the call to setTransform
. Once connected, the transform causes every object drawn using the Graphics2D
object to be drawn with that same transform (in this case, rotation) applied to it until a new AffineTransform
is assigned to the Graphics2D
object via another call to setTransform
. The sample code you found saved the old transform (which presumably encodes a normal, non-rotated state) via
AffineTransform oldTransform = g2.getTransform();
The code then created the rotation transform and connected it to the Graphics2D
(now all objects drawn would be rotated until a new transform be assigned), then drew the one object that needed to be drawn rotated (which therefore had the newly-created rotation transform applied to it), and then restored the original, non-rotating transform to the Graphics2D object via:
g2.setTransform(oldTransform);
That way, the transform that would be applied to subsequent objects would be the original, non-rotating transform.
Upvotes: 1
Reputation: 285415
This makes sense since if you don't reset the Graphics object's AffineTransform back to its baseline, it will use the new transform to draw everything including all images. I don't understand however why you have a call to repaint()
from within your paint
method. You shouldn't do this.
Upvotes: 1