Shooting from the angle of player

Hey guys, I’m making a 2d top down shooter. So the thing is, I have a player who shoots bullets at the mouse direction from the players x and y. The player also rotates to the angle of the mouse. What I’m trying to make is so the bullets are bieng shoot from the end of the players gun (the gun are a part of the player image, so basically I want to shoot from an specific location on an rotating image). But after reading on the subject, I have yet to figured out how I’m gonna make this happen.

So, I got an angle (from the mouse direction), player x and y, how do I shoot from a specific location (end of the gun barrel) on a rotating image?

Would really appreciate some help here, thanks for reading. :slight_smile:

Where are you anchoring your rotation? At the center of the image? Then simply figure out the displacement of the bullet once and rotate that displacement along with the image.

Yes the rotation happens around it’s center.

Not completely sure what you mean. The bullets starting coordinates are the x and y of the player. My goal is to make these coordinates rotate with the player. My code only rotates the player, not the starting coordinates of the bullet. Which is what I’m trying to make. Would appreciate some help in this area.

If you doesn’t understand what I’m trying to explain please forgive me, english isn’t my native language.

Have a good one :slight_smile:

How far is the “gun” (place where bullets should spawn) from the place of rotation (center of the image)? When you know that, use that information to figure out the bullets displacement (spawn point) relative to any rotation.

Here is a link to a post that helped me out with a similar problem:

Say your character is pointing to the right and the end of the gun is 10 pixels to the right and 5 pixels up in that position. Then whatever rotation your character is at, the end of the gun’s position is 10 pixels in the mouse’s direction (say “angle”) and 5 pixels in the direction orthogonal to the mouse (angle+90 degrees).

If you want to use a unit vector for the direction, [dx,dy], then the orthogonal unit vector is simply [-dy,dx].

I’m currently working on this type of shooting and this is how I’ve done it :


 - According the angle 0 is when the player is looking at the top of the screen
 - bullet_rel_pos(x, y) : the position of the bullet relative to the center of the player at angle 0
        - ex : if gun is in the right, x = 4 and y = -10
 - shooting_dir(x, y) : the shooting unit vector using sin and cos functions like this :
        - shooting_dir.x =  Math.sin(player_angle)
        - shooting_dir.y =  Math.cos(player_angle)
 - bullet_pos.x = player.x + (bullet_rel_pos.x*shooting_dir.y) - (bullet_rel_pos.y*shooting_dir.x)
 - bullet_pos.y = player.y + (bullet_rel_pos.x*shooting_dir.x) + (bullet_rel_pos.y*shooting_dir.y)

Perhaps you will need to tweak it a little, depending of your implementation…

Hey, thanks for your reply. I tried your code. It works okey, but the rotation of the exit point for the bullets seems a bit off.

The black dots/lines are the bullets. I have turned of the move method.

The code I’m using:

			int bullet_rel_posX = 16;
			int bullet_rel_posY = 10;
			
			double shooting_dirX =  Math.sin(angle);
			double shooting_dirY =  Math.cos(angle);
			
			double bullet_posX = x + (bullet_rel_posX * shooting_dirY) - (bullet_rel_posY * shooting_dirX);
			double bullet_posY = y + (bullet_rel_posY * shooting_dirX) + (bullet_rel_posY * shooting_dirX);

Is there a certain fomula you are using for bullet_rel_pos? And why are your angle 0 on top? My is on the right. You use radians right?

And thanks for the help man :slight_smile:

My angle 0 is on the right too, it’s just that in this state, the player is looking to the top of the screen.
When you rotate your player, he turns around his center, right ?
If so, the starting point of the bullet needs also to turn around the same center.
In my example :

  • O is the player’s position and the center of the player’s bitmap
  • B the starting point of the bullet at angle 0
  • relX = B.x - O.x
  • relY = B.y - O.y

so here, relX and relY should be negative.
Hope this is easier to understand :wink:

Also, that last line doesn’t look right, shouldn’t it be:


			double bullet_posX = x + (bullet_rel_posX * shooting_dirY) - (bullet_rel_posY * shooting_dirX);
			double bullet_posY = y + (bullet_rel_posX * shooting_dirX) + (bullet_rel_posY * shooting_dirY);

When the player has the angle (radiens) 0 he points to the right. Should I calculate the offset from the center of the player? So, the player is 32 width and 32 height, in that case the offset for x should be 16 and offset for y should be about 10. But when I do this, the circle of rotation keep occur in the top corner. I feel like I’m missing something in the sense of my offset being a bit off. I will read up on Trigonometry and such because my knowledge is clearly lacking.

Oh sorry, yeah I was testing some stuff and forgot to change the code back.

Thanks for the help guys :slight_smile:

If the player turns on itself (on his center), so yes you need to calculate the offset relative to the center of the player.

To understand where the problem is, you need to do it step by step, so :

  • the first thing you need to verify is, at angle 0 is the bullet’s position correct ?
    At angle 0 :
    shooting_dirX = Math.sin(angle) = 0
    shooting_dirY = Math.cos(angle) = 1
    So the formulas become temporarily :

double bullet_posX = x + (bullet_rel_posX * 1) - (bullet_rel_posY * 0);
double bullet_posY = y + (bullet_rel_posX * 0) + (bullet_rel_posY * 1);

and finally :


// Used to determine the initial position of the bullet at angle 0
double bullet_posX = x + bullet_rel_posX;
double bullet_posY = y + bullet_rel_posY;

With this, you have your correct bullet_rel_pos.

  • Second, when the initial position of the bullet will be correct, you can start playing with rotation. It will be easier to determine if there is a problem with the angle or not.

Courage ;D

I have played around with it a bit now. And yaeh the player rotates around it’s center. So at angle 0, the player points to the right. The offset for this angle are posX = 32 and posY = 8 (The player are 32 with and 32 height). At this angle it’s all perfect. But if I cange the angle, but keep the offset for the player it acts in a similar manner as the picture I showed. So I take it as the offset for the player must change according to the angle? This is problary a given but I cant figure out how I should go about making this happen.

And thanks man, I really appreciate you taking your time helping this noob. :slight_smile:

Here comes the pro and jack of all trades! You’re sure to get stuff working now!
jk…

Ok… So lets say you have a rotation of the player, call it rotation.
Now you want to make 2 values: x,y of where the bullet will appear once shot from the gun at rotation 0. It shouldn’t be relative to the player… Just a position where it will spawn on the map.
You can make it appear on the top-right corner by doing something like:


float bullet_x = player.x + player.width;
float bullet_y = player.y;

This would make the bullet appear on top-right corner of the player when player is rotated 0 degrees.

Now, using my almighty Rotation class, we can calculate where the bullet should appear when player is actually rotated.


public class Rotation {
		
	public static vec2 point(vec2 pivot, vec2 point, float rotation) {
		
		float rot = (float)(1f / 180 * rotation * Math.PI);
		
		float x = point.x - pivot.x;
		float y = point.y - pivot.y;
		
		float newx = (float)(x * Math.cos(rot) - y * Math.sin(rot));
		float newy = (float)(x * Math.sin(rot) + y * Math.cos(rot));
		
		
		newx += pivot.x;
		newy += pivot.y;
		
		return new vec2(newx, newy);
	}
	
}

pivot is basically a point on which to around another point.
point is a position which needs to be rotated around the pivot.

Here is vec2…


public class vec2 {

	public float x, y;
	
	public vec2(float x, float y) {
		this.x = x;
		this.y = y;
	}
	
	public int getX() {
		return (int) x;
	}
	
	public int getY() {
		return (int) y;
	}
}

Now we have all that we need.
To calculate were the bullet should appear rotated, we do something like this.


vec2 point = Rotation.point(new vec2(player.x + player.width / 2, player.y + player.height / 2), new vec2(bullet_x, bullet_y), rotation);

bullet_x = point.x;
bullet_y = point.y;

Gz, you should now have a bullet which should appear to be shooting from the gun…

One more thing… When you render the bullet, you need to rotate it around top-left corner, not around the center. Otherwise, you will have a strange position of the bullet depending on the player rotation.

All this code is useless. What it boils down to is very simple geometry.

You have all the keys to make it work…

I think you should stop playing with the code for a bit and take few minutes to really think on how it must work :

  • The player is drawn using his top-left corner bitmap
  • The player has his pivot in the center of his bitmap and rotates around it
  • The bullet has also his pivot in the center of the player’s bitmap and also rotates around it
  • The distance between the pivot and the bullet position is always the same

  • Verify all these and more if your implementation is different, make a scheme to really see it on paper and I’m pretty sure you will find the solution !

After that, if you can’t resolve it, we also can check your code to find the problem.

I’m sorry in advance with what I advocate ;D

public static double lengthdir_x(double len, double dir) {
	return len * Math.cos(Math.toRadians(dir));
}

public static double lengthdir_y(double len, double dir) {
	return -len * Math.sin(Math.toRadians(dir));
}

public void shoot() {
	//First param is length, second is direction.
	double bx = x + lengthdir_x(16, direction-20);
	double by = y + lengthdir_y(16, direction-20);

	new Bullet(bx, by);
}

I’ve dealt with this problem before. This is how I fixed it :slight_smile:
To imagine it visually… Imagine there is a circle 16 units in radius around your player. The bullet is going to be created somewhere ON that circle.
The value 20 represents an offset to the direction. This number can be changed to offset the bullet to the left/right from the players direction.

Hell yaeh thanks orange your code pretty much did it! I changed a few things and now it all runs as it should!

		    double degrees = Math.toDegrees(angle);
			
		    double directionX = Math.cos(Math.toRadians(degrees - 25));
	       double directionY = Math.sin(Math.toRadians(degrees - 25));
			
		    double bx = 15 + x + (16 * directionX);
		    double by = 15 + y + (16 * directionY);

And special thanks to you Gef, got a much better understanding of it all thanks to you. I truly appreciate it. I know it can be frustrating helping somebody who dont know much regarding the subject.

And thanks to the rest of you guys, this forum got some really awesome people! :slight_smile:

@orange451 : Interesting !
After understanding the difference with my method, where you finally transpose my bullet initial relative position by a delta angle, I see that I persisted in explaining the same thing but more complicated mathematically…
Nice ! I had not thought of this way before and I’m glad I learned it ! :slight_smile: