Tower Defense: Rotating Tower

Right, so here is another post for my tower defense game ::)… this time I would like to know how to rotate my cannon tower according to the position of the enemy it is locked on… I know that there is a method in Graphics2D called rotate in which you specify the amount in radians, but every time I use this the screen flickers because I use Graphics to draw everything. So my main question is what is the best way to rotate the tower image, and what is a method/equation to get which way to rotate it? Thanks, cMp

It would be in your case I believe

angle = atan2(y2 - y1, x2 - x1) * 180 / PI;

where (x1,y1) is the location of tower and (x2,y2) is the location of bad guy.

Then plug into rotate and bam.

Good practice IMO for using graphics objects is this.


public void render(Graphics g)
{
    Graphics2D g2d = g.create();
    //do stuff with g2d
    g2d.dispose();
}

that way you will not be reusing stuff from other rendering operations. You can also not do thing and return it to its original orientation after your done rendering but I never liked doing that.

awesome thank you very much! Would you mind explaining what atan2 does? I am rather shady in that area.

Thats just stuff whats easy googled.
Its an mathematical function:

aahhh ok I see now, thanks

The visual interpretation of atan2 is that it gives you the angle from the origin to the x,y point you give it. The x and y are reversed in atan2 – you pass it as y,x – because tan itself is described in those terms (sin/cos, i.e. y/x on the unit circle)

alright, tried for quite a while but this is not working… Here is my code:

	
Graphics2D g2d = (Graphics2D) g.create();
double angle = Math.atan2(targetY - pixY, targetX - pixX) * 180 / Math.PI;
g2d.rotate(Math.toRadians(angle));
g2d.drawImage(Screen.tileset_air[id], pixX, pixY, Screen.room.blockSize, Screen.room.blockSize, null);
g2d.dispose();

nothing happens when I use this code. If I dont use Math.toRadians(angle) the image just flies around the screen in a circle, but it is facing the mob… Any ways to fix this??

You need to translate to where you’re drawing, then rotate, then draw the image at 0,0. Also, rotate takes degrees already. Something like this:


Graphics2D g2d = (Graphics2D) g.create();
double angle = Math.atan2(targetY - pixY, targetX - pixX) * 180 / Math.PI;
- g2d.rotate(Math.toRadians(angle));
- g2d.drawImage(Screen.tileset_air[id], pixX, pixY, Screen.room.blockSize, Screen.room.blockSize, null);
+ g2d.translate(pixX, pixY);
+ g2d.rotate(angle);
+ g2d.drawImage(Screen.tileset_air[id], 0, 0, Screen.room.blockSize, Screen.room.blockSize, null);
g2d.dispose();

I can confirm this:


	public static void main(String[] args)
	{
		for ( double x = -30; x <= 30; x++ )
		{
			for ( double y = -30; y <= 30; y++ )
			{
				double atan = 2 * Math.atan( ( Math.sqrt(x * x + y * y) - x ) / y );
				double atan2 = Math.atan2( y, x );
				
				if ( Math.abs( atan - atan2 ) > 0.000001 )
				{
					System.out.println( atan + " isn't equal to " + atan2 );
				}
			}
		}
	}

(yes, when y is 0 there are problems, didn’t feel like accounting for this)

Alright, that makes sense, and it draws the image, but it still swings around and around the x and y.

Hm, I’m not familiar enough with slick2d. Could you pastebin your current drawing code and maybe someone else more experienced with it could see what’s wrong?

No I am not using slick… just the build in java libraryu\

Zounds, that would be why it says Graphics2D. I’m such a dummy. :emo: (We need a :facepalm: emoticon).

Well pastebin anyway, I know a little more about transforms in Java2D, but not enough.

Ok, its a very large program though, here is the tower class and the cannon tower class: http://pastebin.com/qi7eNAde

Change


  g2d.translate(pixX, pixY);
  g2d.rotate(angle);

to


  g2d.rotate(angle);
  g2d.translate(pixX, pixY);

let me know how that goes.

Almost


Graphics2D g2d = (Graphics2D) g.create();
double angle = Math.atan2(targetY - pixY, targetX - pixX) * 180 / Math.PI;
- g2d.rotate(Math.toRadians(angle));
- g2d.drawImage(Screen.tileset_air[id], pixX, pixY, Screen.room.blockSize, Screen.room.blockSize, null);
+ g2d.translate(pixX + Screen.room.blockSize/2, pixY + Screen.room.blockSize/2);
+ g2d.rotate(angle);
+ g2d.drawImage(Screen.tileset_air[id], -Screen.room.blockSize/2, -Screen.room.blockSize/2, Screen.room.blockSize, Screen.room.blockSize, null);
g2d.dispose();

Im sure this can be optimized, but it will work.

well the image is on the tile its supposed to be on! the only problem is that it just spins around instead of pointing at the mob…

I think g2d.rotate(angle) should be called in radians, as you had before.

See:

http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/Graphics2D.html#rotate(double)

Hmmm. Well it is obviously rotating a lot slower now, its actually about 45 degrees off though haha I will try and fix this

Ok, well if I use

		double angle = Math.atan2(targetY - pixY, targetX - pixX) * 270 / Math.PI;
[\code]

instead, it locks on fine, buuut it doesnt stay right on target..