How to shoot from the tip of a rotating gun?

So far in my game, I have been rotating by rendering w/ slick2d. I was working, and realized that I needed the coords of a point on an object when it is rotated. So that, say I rotate it 78 degrees: the object should rotate and I should be able to get the coords of (6, 1) on the image, while rotating.
Sorry if it is unclear what I am asking!

EDIT:
I realize that that is incredibly unclear, let me elaborate:
I have a gun that rotates, and I need to shoot from the tip of the gun. The gun’s sprite is 8x8, and the tip is at (1, 6). When I rotate, I want to make the bullets instantiate at the tip, so how would I do that? I tried this post, but it did not work at the last post. Just looped around in circles around the x and y… Useless. So what would I do?

ANOTHER EDIT:
Okay, here is my problem in excruciating detail:
I have a player that I render. Then I have a gun that I render. See the two sprites:

http://imageshack.us/a/img811/3299/v6w.png

I have the gun take the player’s rotation, and fire from a point, 1, 6 on the gun. I want to rotate it. So I do this formula:


float tipx = (float) ((getPlayer().getX() + 1) + 8 * Math.cos(Math.toRadians(getPlayer().getRot())));
float tipy = (float) ((getPlayer().getY() + 6) + 8 * Math.sin(Math.toRadians(getPlayer().getRot())));
shotline = new Line(tipx, tipy, mousex, mousey);

But instead of the line starting at 1,6 on the gun, and ending on the mouse, I get this:
NOTE: Mouse is not visible, but the mouse is in all pictures at the farthest point on the line away from the player.

http://imageshack.us/a/img845/1859/dlny.png

http://imageshack.us/a/img153/1391/sjr.png

http://imageshack.us/a/img824/3922/veix.png

Oh, I think you can solve this quite simply.

I’ll guess you know your rotation angle that was applied to rotate the gun. What you need to do is to calculate the angle of the vector from (x,y) to (1,6) (using atan2). The angle of that vector to the vector of the bullet that will launch from the tip is your “base rotation”. You just add your gun rotation to that and use sin() and cos() to calculate the new location of your original (1,6). This way you know the location where the bullet launches. Your gun rotation without the “base rotation” gives you the flying vector of the bullet.

Is that in anyway a help? ^^

Nitram

A simple solution would be to have the projectile movement vector angle match that of the rotating shooter, and then just “teleport” the bullet upon instantiation a distance equal to the barrel length.

That way you save on calculating the position of the barrel’s tip.

But you do need to have a decent vector class to handle the projectile’s motion in any case.

Relevant:
http://www.rodedev.com/tutorials/gamephysics/

It’s just simple trigonometry.

Basic Trigonometry: http://www.youtube.com/watch?v=Jsiy4TxgIME
Basic Vectors: http://www.youtube.com/watch?v=xp6ibuI8UuQ

From this thread:

Really, there’s a lot of information about this stuff. Use the forum’s search function.

Here is a very simple way of seeing it:

First, have an angle in radians.
Then, use Math.cos( angle ) to get the X amount, and Math.sin( angle ) to get the Y amount.

Cos always is X, and Sin always is Y.

Code dump inbound: (sorry if this is long enough to qualify pastebin, wasn’t sure)

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;


public class RotationDemo extends JFrame implements Runnable {

	BufferedImage buffer;
	Player player;
	
	public RotationDemo() {
		super("Test");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(600,400);
		buffer = new BufferedImage(60,40,BufferedImage.TYPE_INT_RGB);
		player = new Player();
		Thread t = new Thread(this);
		setVisible(true);
		t.start();
	}

	@Override
	public void run() {
		while(true) {
			Graphics g = getGraphics();
			Graphics bufferGraphics = buffer.createGraphics();
			if(g==null)
				continue;
			player.update();
			render(bufferGraphics);
			g.drawImage(buffer,0,0,getWidth(),getHeight(),null);
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {}
		}
		
	}
	
	public void render(Graphics g) {
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());
		player.render(g);
	}
	public static void main(String[] args) {
		new RotationDemo();
	}
}

class Player /*implements Updatable, Renderable or whatever*/ {
	int x=30,y=20;
	float rot=0;//in degrees
	
	
	private int radius = 4;
	private int gunOffsetX = 6, gunOffsetY = 1;       //gun "grip" location relative to player
	private int gunTipOffsetX = 0, gunTipOffsetY = 5; // "muzzle" location relative to "grip" (your mousex, mousey)
	
	public void update() {
		//sample behavior: spin in a circle
		rot++;
	}
	
	public void render(Graphics g) {
		g.setColor(Color.GREEN);
		g.fillOval(x-radius, y-radius, radius*2, radius*2);
		g.setColor(Color.RED);
@@		double rad = Math.toRadians(rot);
@@		double gunPosMag = Math.hypot(gunOffsetX, gunOffsetY);
@@		double gunPosX = x+gunPosMag*Math.cos(rad + Math.atan2(gunOffsetX, gunOffsetY));
@@		double gunPosY = y+gunPosMag*Math.sin(rad + Math.atan2(gunOffsetX, gunOffsetY));
		
@@		double gunLength = Math.hypot(gunTipOffsetX, gunTipOffsetY);

	//now note here the gunPosX instead of x, this keeps the frame of referance correct (if we use from muzzle to grip, use
	// x if you want muzzle to player)

@@		double gunTipPosX = gunPosX+gunLength*Math.cos(rad + Math.atan2(gunTipOffsetX, gunTipOffsetY));
@@		double gunTipPosY = gunPosY+gunLength*Math.sin(rad + Math.atan2(gunTipOffsetX, gunTipOffsetY));

		g.drawLine((int)Math.round(gunPosX), (int)Math.round(gunPosY), (int)Math.round(gunTipPosX), (int)Math.round(gunTipPosY));
	}
}

Quick demo of the maths highlighted there for you. Give it a quick run. Its a bit messy with keeping track of separate x and y values instead of nice Vector2’s, but alas. You need to make sure you keep track of the local frame of reference when calculating coordinates for parts of the sprite.

Look up 2D vector rotation, etc.

“Grip” is the handle of the gun, basically where Player is holding it (the point rotating around the player’s location, in your case (1,6)).
The “muzzle” in my example is the end of the gun’s barrel, but looking at your post, you are using mousex and mousey, so you can likely ignore that.

Mainly the gunPosX and gunPosY are what you were looking for and I hope I showed how to calculate them. (Although if I spent more than 5 mins I could put together a better way)

EDIT: Relevant: Wikipedia: Rotation(mathematics)
Using this, here is much more straightforward method (shoulda just looked this up earlier… oops):


double gunPosX = x+gunOffsetX*Math.cos(rad) - gunOffsetY*Math.sin(rad);
double gunPosY = y+gunOffsetX*Math.sin(rad) + gunOffsetY*Math.cos(rad);

Well, based on your original code:


float tipx = (float) ((getPlayer().getX() + 1) + 8 * Math.cos(Math.toRadians(getPlayer().getRot())));
float tipy = (float) ((getPlayer().getY() + 6) + 8 * Math.sin(Math.toRadians(getPlayer().getRot())));
shotline = new Line(tipx, tipy, mousex, mousey);

(not sure what that 8 is though…)

I think it would be this:


float rad = (float)Math.toRadians(getPlayer().getRot()); // for convenience and readability

float tipx = (float) (getPlayer().getX() + 1 * Math.cos(rad) - 6 * Math.sin(rad));
float tipy = (float) (getPlayer().getY() + 1 * Math.sin(rad) + 6 * Math.cos(rad));
shotline = new Line(tipx, tipy, mousex, mousey);

I’m not familiar with Slick, so I’m assuming no crazy coordinate systems or anything, but aside from something like that, this should work.

Based on that pic, it looks like the rotation is working correctly, but your player x and y are already offset from where it is being rendered. (I hope that makes sense) It looks like the circle is centered out in front of his head, when it’s supposed to be centered on the top of his head.

Try making offx and offy smaller, especially the offy, that should (should) bring it back toward the player sprite.

Does the circle stay out in front of his head, even when you face a different direction? Or does it stay to to the above left of him, no matter where he faces? I’m pretty sure I know what it is if it is the latter.

Good news then: I know what’s wrong, or at least how to fix it: subtract the player sprite’s [radius] from it’s coords when rendering.

Watch what happens when you change my demo code above:

g.fillOval(x-radius, y-radius, radius*2, radius*2);

to this:

g.fillOval(x, y, radius*2, radius*2); // now it's not centered on (x,y)! oh no!

It will now exhibit your same problem.
This is due to the fact that drawOval(x,y,w,h) draws the oval’s top left corner at the given (x,y), instead of it’s center.
I suspect this is what is happening to you, as I know that Slick is supposed to act like J2D.

So were ever you render the sprite, subtract width/2 from x and height/2 from y, or add them to the tipx,tipy if that interferes with your collision detection, etc.

No prob, was bored tonight, figured I help out the first person I saw here. I suspect that maybe the offsets could be divided by an equal factor, possibly related to the ‘8’ earlier. Try some nums between 2 and 8 and see. Or just calculate how far off you are and find the exact constant.

Funny looking. High-res lighting on 8x8 sprites.