Basic rotation and Moving toward angle direction (car movement)

Hello,
i don’t know if am able to post here or not, but i finally find the “correct” way to rotate an object and make it move toward the its rotation direction, and i decided to share it in case someone else has find himself facing the same problem i have for this whole week.

[if you found any error please correct me]

so,
1st thing you need to know is the “head” of your object, if you draw a rectangle and its rotation angle is still 0, which mean you didn’t rotate it yet, then the head is filled rectangle like this picture show

http://s3.postimg.org/bhyew5glb/image.png

i don’t know if am the only one who made that error, but i was thinking that the head is the upper line ::slight_smile:

anyway, here is a very simple example on how to rotate a square and make it move forward and backward (car movement )

this is the Hero class, the object that we will rotate


//this is the hero class

package rot;

public class Hero {

	private double x, y, a; // x,y and angle
	private int w, h; // width and height

	// constructor
	public Hero(double x, double y, double a, int w, int h) {

		this.x = x;
		this.y = y;
		this.a = a;
		this.w = w;
		this.h = h;
	}

	// returning all the necessary value of this class

	public double getX() {
		return x;
	}

	public double getY() {
		return y;
	}

	public double getA() {
		return a;
	}

	public int getW() {
		return w;
	}

	public int getH() {
		return h;
	}

	// setting the angle
	public void setA(int aa) {

		a = Math.toRadians(aa);
	}

	// move toward the angle
	// //forward
	public void moveForward() {
		x += Math.cos(a);
		y += Math.sin(a);
	}
	// //backward
	public void moveBackword() {
		x -= Math.cos(a);
		y -= Math.sin(a);
	}

}


this is the Board class, it have the game loop, the game control key and the game logic


package rot;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;

import javax.swing.JPanel;

public class Board extends JPanel implements Runnable {

	private Thread loop;

	private Hero hero;

	private int tmpAngle;

	private boolean moveForward, moveBackward;

	// constructor
	public Board() {
		init();
		addKeyListener(new Controll());
		setFocusable(true);
		setBackground(new Color(0, 50, 100));
		setDoubleBuffered(true);
		setFocusable(true);

	}

	// initialisation
	private void init() {
		hero = new Hero(400, 300, 0, 70, 50);
		tmpAngle = 0;
		moveForward = moveBackward = false;

		loop = new Thread(this);
		loop.start();

	}

	public void paint(Graphics g) {
		super.paint(g);

		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		AffineTransform old = g2d.getTransform();

		g2d.setColor(Color.white);

		// rotating the hero, rotation point is the middle of the square
		g2d.rotate(hero.getA(), hero.getX() + hero.getW() / 2, hero.getY()
				+ hero.getH() / 2);
		// drawing the square
		g2d.drawRect((int) hero.getX(), (int) hero.getY(), hero.getW(),
				hero.getH());

		// to know the "head"
		g2d.fillRect((int) hero.getX() + hero.getW(), (int) hero.getY() + 10,
				10, 30);

		//in case you have other things to rotate
		g2d.setTransform(old);

	}

	public void play() {

		// this is just to keep the angle between 0 and 360
		if (tmpAngle > 360) {
			tmpAngle = 0;
		} else if (tmpAngle < 0) {
			tmpAngle = 360;

		}

		// setting the hero angle
		hero.setA(tmpAngle);

		// moving the hero
		if (moveForward) {

			hero.moveForward();
		} else if (moveBackward) {
			hero.moveBackword();
		}

	}

	// game loop
	@Override
	public void run() {

		while (true) {
			repaint();
			play();
			try {
				loop.sleep(2);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

	// game key controll
	private class Controll extends KeyAdapter {

		public void keyPressed(KeyEvent e) {

			if (e.getKeyCode() == e.VK_UP) {
				moveForward = true;
			}
			if (e.getKeyCode() == e.VK_DOWN) {
				moveBackward = true;
			}
			if (e.getKeyCode() == e.VK_LEFT) {
				tmpAngle -= 5;
			}
			if (e.getKeyCode() == e.VK_RIGHT) {
				tmpAngle += 5;
			}

		}

		public void keyReleased(KeyEvent e) {

			if (e.getKeyCode() == e.VK_UP) {
				moveForward = false;
			}
			if (e.getKeyCode() == e.VK_DOWN) {
				moveBackward = false;
			}
			if (e.getKeyCode() == e.VK_LEFT) {

				tmpAngle -= 0;
			}
			if (e.getKeyCode() == e.VK_RIGHT) {
				tmpAngle += 0;
			}

		}
	}

}


and finally this is the frame class, the one that have the main class

//this is the game window 

package rot;

import javax.swing.JFrame;

public class RotateME extends JFrame {

	private final int width = 800, height = 600;

	public RotateME() {

		add(new Board());

		setTitle("rotate me please");
		setSize(width, height);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setResizable(true);
		setVisible(true);

	}

	public static void main(String[] args) {
		new RotateME();

	}

}

i hope what i said is correct and can be helpful for new developers like me

thank you

Nice article but I have some recommendations.


-   init();
    addKeyListener(new Controll());
    setFocusable(true);
    setBackground(new Color(0, 50, 100));
    setDoubleBuffered(true);
    setFocusable(true);
+   init();

You are adding keylistener after the starting of gameloop! This can make the player think that the game is too slow if the game starts playing when it’s started and input may take some time. So create keylistener first.

The second issue is with your game loop.


while (true) {
    repaint();
    play();
    try {
@@        loop.sleep(2);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

You are calling [icode]loop.sleep(2)[/icode]. You should call it like [icode]Thread.sleep(2)[/icode] since [icode]sleep[/icode] is a static method. Also the precision of the sleep method is not guaranteed across platforms. Please read the article Game Loops!.

Other than those, it’s a nice article.

about the calling thing, you are right, i usually do these kinda of mistake ::slight_smile: hopefully it’s not that deadly, but yeah people who read this article should be aware of it.
about the loop thing, well …
the loop am using is definitely a BAD game loop and no one should use it for a full project, but the goal here is just how to make an object move toward it’s rotation (which caused a little problem for me )
otherwise, thank you for replying :slight_smile:

about the calling thing, you are right, i usually do these kinda of mistake ::slight_smile: hopefully it’s not that deadly, but yeah people who read this article should be aware of it.
about the loop thing, well …
the loop am using is definitely a BAD game loop and no one should use it for a full project, but the goal here is just how to make an object move toward it’s rotation (which caused a little problem for me )
otherwise, thank you for replying :slight_smile: