Need help with rotation in Java

Hi, I am trying to write an asteroids remake and I have gotten pretty far, but I'm stuck when I try to rotate my ship object. I have googled various formula's etc. but the code doesn't work as expected. I have posted the relevant ship.class below:

import java.awt.Polygon;

import java.awt.Graphics;

import java.awt.Shape;

import java.awt.*;

publicclass Shipextends MyShape{

Polygon body;

//line2D.Double base;

//line2D.Double lside;

//line2D.Double rside;

double dx;

double dy;

double angle;

double dAngle;

Graphics2D gg;

public Ship(double a,double b){

x=a;

y=b;

//base=new line2D.Double(x,y,x+10,y);

//lside=new line2D.Double(x,y,x+5,y-10);

//rside=new line2D.Double(x+10,y,x-5,y-10);

body=new Polygon();

body.addPoint((int)x,(int)y);

body.addPoint((int)x+20,(int)y);

body.addPoint((int)x+10,(int)y-30);

}

publicvoid advance(){

}

publicdouble getX(){

return x;

}

publicdouble getY(){

return y;

}

publicvoid setY(int y){

this.y=y;

}

publicvoid setX(int x){

this.x=x;

}

publicvoid move(int delta){

body.translate(0,delta);

// body.addPoint(x,y);

// body.addPoint(x+20,y);

// body.addPoint(x+10,y-30);

}

publicvoid rotate(double x,double y,double theta){

//body=new Polygon();

theta=theta*(Math.PI/180);

x=((x-(x+10))*Math.cos(theta)-y*Math.sin(theta)+(x+10));

y=(y*Math.cos(theta)+(x-(x+10))*Math.sin(theta)+y);

//body.translate((int)Math.round(x),(int)Math.round(y));

body.addPoint((int)Math.round(x),(int)Math.round(y));

body.addPoint((int)Math.round(x+20),(int)Math.round(y));

body.addPoint((int)Math.round(x+10),(int)Math.round(y-30));

//g.rotate(theta,x,y);

}

publicvoid warpAround(int x,int y){

body.translate(x,y);

}

publicvoid draw(Graphics2D g){

g.draw(body);

}

}

If you could help me I would appreciate it,

Sincerely,

LJ

P.s. I know its a little rough, I wanted to clean it up soon.

Message was edited by:

nipponman21

[5037 byte] By [nipponman21a] at [2007-11-27 1:13:39]
# 1

I don't know if this helps, as I've done next to no graphical programming (but I don't let my ignorance stop me from making a fool of myself) - are you familiar with this:

http://java.sun.com/j2se/1.4.2/docs/api/java/awt/geom/AffineTransform.html

http://forum.java.sun.com/thread.jspa?threadID=282593&messageID=1101608

Good Luck

Lee

tsitha at 2007-7-11 23:49:01 > top of Java-index,Java Essentials,Java Programming...
# 2
You could use an AffineTransform to do the rotation for you: http://java.sun.com/docs/books/tutorial/2d/advanced/transforming.html
DrLaszloJamfa at 2007-7-11 23:49:01 > top of Java-index,Java Essentials,Java Programming...
# 3

Hmm, thank you both, but I wanted to do this without using an AffineTransform. There is a formula for this but my formula must be off or something because whenever I enter into the KeyEvent.VK_LEFT case after pressing the left key, there is a line that extends around the ship and it just goes in a circle if I hold it. Its kinda wierd. Anyone else?

nipponman21a at 2007-7-11 23:49:01 > top of Java-index,Java Essentials,Java Programming...
# 4
Why don't you want to use AffineTransform?
DrLaszloJamfa at 2007-7-11 23:49:01 > top of Java-index,Java Essentials,Java Programming...
# 5

What is your rotate method supposed to do?

>public void rotate(double x, double y, double theta){

>//body=new Polygon();

>theta=theta*(Math.PI/180);

theta now in radians. You could also have used:

import static java.lang.Math.*;

...

public void rotate(final double x, final double y, final double thetaDegrees){

final theta = toRadians(thetaDegrees);

>x=((x-(x+10))*Math.cos(theta)-y*Math.sin(theta)+(x+10));

(x-(x+10)) = -10

So that's the same as final double x_prime = -10 * cos(theta)-y*Math.sin(theta)+(x+10);

>y=(y*Math.cos(theta)+(x-(x+10))*Math.sin(theta)+y);

so final double y_prime = 10 * sin(theta) + y * cos(theta) + y;

The matrix to rotate by an angle theta is: Rot(θ) = [ cos θ-sin θ ]

[ sin θcos θ ]

So (x, y)' = (x,y) + Rot(θ)?-10, y)

I was using final as I wasn't sure whether x got modified before x was set, but y isn't actually a function of x_prime anyway.

If you vary theta with x,y constant, (x,y)' will orbit (x,y) at a distance √(y² + 100).

> body.addPoint((int)Math.round(x),(int)Math.round(y));

>body.addPoint((int)Math.round(x+20),(int)Math.round(y));

>body.addPoint((int)Math.round(x+10),(int)Math.round(y-30));

These three points give a triangle pointing up with one vertex at (x,y)'

Do you want to rotate about the x,y given as parameters or the origin?

Do you want to update this.x, this.y?

If you want to rotate the figure, define it as offsets from its centre point (0,-20), (-10,10),(10,10), and calculate the values of these points rotated by theta. Then add the x,y of the centre to get the points to plot on the screen.

I think it's worth writing a few programs that use the maths directly before using the affine transform libraries, as then you'll understand what's going on beneath the abstraction.

Pete

pm_kirkhama at 2007-7-11 23:49:01 > top of Java-index,Java Essentials,Java Programming...
# 6

>What is your rotate method supposed to do?

I want it to rotate the ship object when I press the either of the keys.

So (x, y)' = (x,y) + Rot(θ)?-10, y)

Thanks

>Do you want to rotate about the x,y given as parameters or the origin?

Do you want to update this.x, this.y?

x,y given as params, and I don't know what you mean with your second question.

>If you want to rotate the figure, define it as offsets from its centre point (0,-20), (-10,10),(10,10), and calculate the values of these points rotated by theta. Then add the x,y of the centre to get the points to plot on the screen.

What was happening was that The ship would disappear for a second and then it would draw this large circle without ever changing its directional vector.

nipponman21a at 2007-7-11 23:49:01 > top of Java-index,Java Essentials,Java Programming...
# 7

>>Why don't you want to use AffineTransform?

3 reasons actually. Firstly, I don't really know how to use them. Secondly, while it probably wouldn't take me long to learn them, looking over the tutorial made me realize that I would have to change the way my objects were defined, how arguments were passed etc, it seemed like it could get pretty messy. I am still learning and I would like to do as much coding as I can with as little abstraction as possible, as this is just a pet project I am in no rush to finish, I just want to know how to do it. Thanks for the suggestion though

nipponman21a at 2007-7-11 23:49:01 > top of Java-index,Java Essentials,Java Programming...
# 8

Ok, I have officially given up on trying to get it to work via the mathematical definitions of a rotational transform. I decided to use the affine transform and it was MUCH easier than I thought to implement; however, the results are still unexpected, the ship actually turns and moves in a circle which is not what I want, here is the source (its a standalone app so you can compile and run it if you want) import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

public class BouncingBall extends JFrame implements Runnable, KeyListener {

//Windows

private JFrame frame;

private DrawPanel pane;

private Thread t;

//Game Vars.

public Ball ball;

public Ship ship;

public static final int FPS = 30;

public static final int WIDTH = 800;

public static final int HEIGHT = 600;

public static final int MAXSPEED = 30;

public static double dx,dy;

[b]public static int theta=0;[/b]

public BouncingBall() {

frame=new JFrame();

pane=new DrawPanel();

frame.getContentPane().add(pane);

frame.setVisible(true);

frame.pack();

frame.addKeyListener(this);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

initGame();

start();

}

public void initGame(){

ship=new Ship();

ball=new Ball();

}

public void start(){

t=new Thread(this);

t.start();

}

public void run(){

while(true){

try{

Thread.sleep(10);

}catch(Exception e){}

pane.repaint();

}

}

public static void main(String[] args) {

new BouncingBall();

}

public void keyPressed(KeyEvent e){

switch(e.getKeyCode()){

case KeyEvent.VK_UP:

dy--;

if(dy<MAXSPEED){

ship.move(0,dy);

}

else{

dy=MAXSPEED;

ship.move(0,dy);

}

break;

case KeyEvent.VK_LEFT:

[b]theta++;[/b]

break;

case KeyEvent.VK_RIGHT:

[b]theta--;[/b]

break;

}

repaint();

}

public void keyReleased(KeyEvent e){

switch(e.getKeyCode()){

case KeyEvent.VK_UP:

case KeyEvent.VK_DOWN:

dy=0;

break;

}

repaint();

}

public void keyTyped(KeyEvent e){

}

class Ball{

double x;

double y;

private Arc2D.Double body;

public Ball(){

x=600.0;

y=500.0;

body=new Arc2D.Double(x,y,30.0,30.0,0.0,360.0,Arc2D.OPEN);

}

public void move(double dx,double dy){

body=new Arc2D.Double();

x+=dx;

y+=dy;

body=new Arc2D.Double(x,y,30.0,30.0,0.0,360.0,Arc2D.OPEN);

}

public double getX(){

return this.x;

}

public double getY(){

return this.y;

}

}

class Ship{

double x;

double y;

double angle;

private Polygon body;

public Ship(){

x=400.0;

y=300.0;

angle=0;

body=new Polygon();

body.addPoint((int)Math.round(x),(int)Math.round(y));

body.addPoint((int)Math.round(x+15),(int)Math.round(y));

body.addPoint((int)Math.round(x+7.5),(int)Math.round(y-20));

}

public void move(double dx,double dy){

body=new Polygon();

x+=dx;

y+=dy;

body.addPoint((int)Math.round(x),(int)Math.round(y));

body.addPoint((int)Math.round(x+15),(int)Math.round(y));

body.addPoint((int)Math.round(x+7.5),(int)Math.round(y-20));

}

public double getX(){

return this.x;

}

public double getY(){

return this.y;

}

}

class DrawPanel extends JPanel{

public DrawPanel(){

setBackground(Color.black);

setPreferredSize(new Dimension(BouncingBall.WIDTH,BouncingBall.HEIGHT));

}

public void paintComponent(Graphics g){

super.paintComponent(g);

Graphics2D g2d=(Graphics2D)g;

g2d.setColor(Color.white);

g2d.fill(ball.body);

[b]g2d.rotate(theta*Math.PI / 180.0);[/b]

g2d.fill(ship.body);

}

}

}

Can you guys maybe run this and look over the code and tell me what I'm doing wrong? I would definitely appreciate it Thanks.>

nipponman21a at 2007-7-11 23:49:02 > top of Java-index,Java Essentials,Java Programming...
# 9
Try changing the rotate call to:g2d.rotate(theta*Math.Pi/180.0, ship.getX()+5, ship.getY()-5)Message was edited by: KonigsMessage was edited by: KonigsMessage was edited by: Konigs
Konigsa at 2007-7-11 23:49:02 > top of Java-index,Java Essentials,Java Programming...
# 10
Thanks that really worked!
nipponman21a at 2007-7-11 23:49:02 > top of Java-index,Java Essentials,Java Programming...