I have a turret with a 2 gunbarrels. The turret rotates towards my mouse. So far no problem. When it creates a few bullets and positions them at the end of the gun barrels.

Here is the problem. It only works the moment the gun is point upwards. The moment it rotates the end of the gun barrels have moved ofcourse, thus the bullets don't spawn at the end of the gun battels, but at the place the where the gun barrels are when the turret is pointing upwards.

How can I check where the end of the gun barrels are the moment it rotates?

EDIT: With the following code it positions the bullet next to turret, not at the end of the gun barrels.

To see what I mean:


    Vector2 _bulletPosition = new Vector2();
    _bulletPosition.X = (float)((Math.Cos(_rotation)) * _barrelLenght) + _position.X;
    _bulletPosition.Y = (float)((Math.Sin(_rotation)) * _barrelLenght) + _position.Y;

_rotation = the angle the turret is rotated at.

_barrelLenght = the length of the barrels.

_position = the position of the turret.

EDIT 2: With this code I get the bullets right between the 2 gun barrels.

    _bulletPosition.X = (float)((Math.Cos(_rotation - (float)(Math.PI / 2))) * _barrelLenght) + _position.X;
    _bulletPosition.Y = (float)((Math.Sin(_rotation - (float)(Math.PI / 2))) * _barrelLenght) + _position.Y;

With this code I get the 2 bullets at the right end of the gun barrels, but only when the turret is pointing upwards.

    _bulletPosition.X = (float)((Math.Cos(_rotation - (float)(Math.PI / 2))) * _barrelLenght) + _position.X + bulletSpawn.X;
    _bulletPosition.Y = (float)((Math.Sin(_rotation - (float)(Math.PI / 2))) * _barrelLenght) + _position.Y + bulletSpawn.Y;

I have to get the bulletSpawn relative to the end of the gun barrels position.


I found a fix that worked

    //Create Matrix with rotation value
    Matrix rotationMatrix = Matrix.CreateRotationZ(_rotation);
    //Create Vector2 with offset from turret center to end of barrel.
    Vector2 _bulletPosition = point;
    //Do a transform with the bulletPosition Vector2 and the rotationmatrix
    _bulletPosition = _position + Vector2.Transform(_bulletPosition, rotationMatrix);
  • \$\begingroup\$ I fixed it, see last Edit for the fix I used \$\endgroup\$
    – DijkeMark
    Commented Jul 12, 2012 at 10:57

2 Answers 2


This is pretty elementary math, just use sin and cosine together with the angle the gun is at.

First we need to define a stationary position. This is when the gun points east. The angle is then 0, giving us X = cos(0) = 1 and Y = sin(0) = 0.

Changing the angle of the gun gives us a different position. For example pointing south would give us an angle of 1.5PI which give us the coordinates X = cos(1.5PI) = 0 and Y = sin(1.5PI) = -1.

So these formula give us a direction vector (X,Y) which tells us which direction the turret is facing based on the angle. Now all we need to do is lengthen (multiply) this vector by the length of the barrel and offset it with the position of the turret. This gives us the 'bulletStart' vector.

X = cos(angle) * barrelLength + turret.Postion.X;
Y = sin(angle) * barrelLength + turret.Position.Y;

Note that the direction vector can directly be used to specify the direction your bullets should fly/face

Edit: re-read and I see you're using double barrels. You can use 1 sprite which shows 2 bullets or you can take the cross product (Vector2.Cross(...)) of the above direction vector to get a vector that points towards the relative 'left' of the direction vector then use the (bulletStart + rleft * barrelDistance) and (bulletStart - rleft * barrelDistance) vectors instead of just the bulletStart vector to place sprites neatly in front of both barrels

  • \$\begingroup\$ I was never strong with using sin and cosine, but I'll give it a try. It looks simple, hope I can get it to work. \$\endgroup\$
    – DijkeMark
    Commented Jul 11, 2012 at 10:57
  • \$\begingroup\$ I edited my post with more info on what I mean. \$\endgroup\$
    – DijkeMark
    Commented Jul 11, 2012 at 11:51
  • \$\begingroup\$ @DijkeMark if you're not good at trigonometry, you're going to have hard times in game development. \$\endgroup\$
    – Zonko
    Commented Jul 11, 2012 at 23:02
  • \$\begingroup\$ Yes, I know. But I won't let that be a reason to not to try game development. It just takes more time for me to develop. :) \$\endgroup\$
    – DijkeMark
    Commented Jul 12, 2012 at 9:08
  • \$\begingroup\$ @DijkeMark good attitude. The more you practice with trigonometry, the more it will begin to make sense. Just take the time to think about what you are doing when you write these sections of code and you will begin to understand what different trig functions do intuitively. \$\endgroup\$
    – A-Type
    Commented Jul 12, 2012 at 16:59

I agree with Roy's answer, but I want to provide a different point of view.

What you want to do is transform the spawn point for your bullets depending on the orientation of the barrel.

In 3D math this is typically done with a matrix, but in 2D it's much more common to see people just using plain sine and cosine. I think this is a bit silly, because the problem becomes much easier to solve by using matrix math.

First, let's define the orientation of your turret. It has a position and a rotation.

I'm going to use pseudocode to explain the solution, but it should be easy to convert to XNA C#.

// a 3x3 matrix holds a 2D rotation and a 2D translation

mat3x3 transform;

This is what the matrix will look like inside:

[  cos(deg2rad(angle)),  sin(deg2rad(angle)), 0.0 ]
[ -sin(deg2rad(angle)),  cos(deg2rad(angle)), 0.0 ]
[ position.x,            position.y,          1.0 ]

Keep in mind that is an OpenGL matrix, which is row-oriented, while DirectX most likely uses a column-oriented version.

So how do we get the updated spawn positions? We first define the two spawn points in the object's local space. In this case, that means "relative to the camera's position".

vec2 spawn_bullet1(-16.0, -16.0);
vec2 spawn_bullet2( 16.0, -16.0);

Now we can use our matrix to transform these positions to world space:

vec2 world_spawn_bullet1 = transform * spawn_bullet1;
vec2 world_spawn_bullet2 = transform * spawn_bullet2;

Now you can use these new positions to spawn your bullets and they will always be at the end of the barrels.

That was easy, right? Let's see what happens inside the transformation function:

vec2 result;

float x = (a_Position.x * cos(deg2rad(turret_angle))) + (a_Position.y * -sin(deg2rad(turret_angle))) + turret_position.x;
float y = (a_Position.x * sin(deg2rad(turret_angle))) + (a_Position.y *  cos(deg2rad(turret_angle))) + turret_position.y;
float z = (a_Position.x * 0.0)                        + (a_Position.y * 0.0)                         + 1.0;

result.x = x / z;
result.y = y / z;

Let's remove the cruft and unnecessary operations:

result.x = (a_Position.x * cos(deg2rad(angle))) + position.x;
result.y = (a_Position.y * sin(deg2rad(angle))) + position.y;

And you get the same operations as you would when doing it manually, but in convenient matrix form.

What are the benefits of using matrices?

  • Matrices can store rotation, translation and scale. You only need to know the relative offset to the turret's position. The rest can be done with the matrix.
  • Matrices can be stacked. If you want to put your turret on a bigger ship that moves and rotates, it's a simple of case of multiplying the turret's matrix with the ship's matrix.
  • Matrices simplify the math. Instead of keeping track of radians or angles, it's all done and verified by a matrix.

I use a matrix whenever possible, even in a 2D game.

  • \$\begingroup\$ Well, I have nver used a matrix before, but I'll give it a try. \$\endgroup\$
    – DijkeMark
    Commented Jul 11, 2012 at 10:58
  • \$\begingroup\$ I tried a bit, but I got no idea what I am doing. I also got no idea how I can use matrixes and stuff. Do you think you could make a short XNa version of this? \$\endgroup\$
    – DijkeMark
    Commented Jul 11, 2012 at 19:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .