# Implementing a multishot powerup for a top down shooter

I have a top down shooter wherein I generate a projectile on each mouse click at the player's position and translate it in a straight line until it reaches the edge of the screen.

I also have powerups that enhance the player's current weapon by giving a multishot for a certain time span. Here's my problem. I'm not sure of how to place the projectiles relative to the player so that they are offset to the "left" and the "right" instead of directly on the player's position.

In order words, I will need to:

Vector2 playerPosition = playerOne.Position;
Vector2 projectileOnePosition = playerPosition + offsetVector;
Vector2 projectileTwoPosition = playerPosition - offsetVector;


I'm having trouble calculating the offset vector because I need to take the current rotation of the player in to account as well.

TL;DR: How do I find a point relative to the player's current position taking rotation of the current player in to account? My theory is that it involves calculating a circle around the player with a specific radius that determines the distance away from the player and placing the points somewhere on that circle.

I can draw a picture if necessary. Right now I'm on my laptop so it isn't draw-friendly.

• So you are saying that you have a hotspot relative to the player's sprite where the projectile needs to be initially shot from? – Austin Brunkhorst Aug 3 '12 at 23:28
• Yea, I'd like to have the bullets offset from the player's position. I just need to spawn the bullets apart from each other so they don't overlap. – Justin Skiles Aug 3 '12 at 23:34
• I'll do some more testing tonight. My suspicion is that it's going to end up being a simple solution involving x = rcos(theta) and y = rsin(theta). – Justin Skiles Aug 3 '12 at 23:36

If you want something like this, this is the way to achieve it:

// you should probably put this somewhere near the initialization code;
// no point in assigning it every frame:
float distance = 10.0; // how much our projectiles will be distant from the ship
// if your ship's rotation is stored in playerOne.Rotation and expressed in radians:
projectileOnePosition.X = playerPosition.X + Math.cos(playerOne.Rotation + Math.PI/12) * distance;
projectileOnePosition.Y = playerPosition.Y + Math.sin(playerOne.Rotation + Math.PI/12) * distance;
// for projectileTwo, substract ninety degrees, i.e. + Math.PI/12
// also, it is a good idea to keep PI/12 precalculated as constant
// PI/12 is 15 degrees. so we're setting th origins of the bullets on a circle
// and they are shifted by 15 degrees 'left' and 'right' relative to ship's
// rotation


If you are using degrees for rotation (I am not familiar with XNA enough, but this is basic stuff), you can convert them using simple formula Radians = Math.PI * Degrees / 180.0

Oh, and here is the source code for the swf

• The final value will multiplied by distance. You will need to separate with parentheses. posX + (cos() * distance). Also XNA has a static class MathHelper which provides constant values such as PI / 2. MathHelper.PiOver2. Documentation can be found here - msdn.microsoft.com/en-us/library/…. – Austin Brunkhorst Aug 3 '12 at 23:52
• I'm pretty sure multiplication comes first, so it will be 1. multiply cos value of the angle with distance 2. add it to posX – Vladimir Mitrovic Aug 3 '12 at 23:54
• Yes, this is exactly what I was going for. I'm glad that my thoughts weren't far off track. Thanks to you both. – Justin Skiles Aug 4 '12 at 2:57

If you are looking to have a hotspot for each shot I would do something like this. This uses the hotspot (10, 0) in the example. I would not initialize projectileHotspot every game loop, this is just for the example.

Vector2 projectileHotspot = new Vector2(10, 0);

projectilePosition.X = player.Position.X + (Math.Cos(player.Rotation) * projectileHotspot.X);
projectilePosition.Y = player.Position.Y + (Math.Cos(player.Rotation) * projectileHotspot.Y);


Note that player.Rotation is assumed to be in Radians. MathHelper.ToRadians(deg) is a simple way to convert between radians, degrees, vice versa.

I created a simple image to help understand my perception of your question. The coordinates are not to scale but you should get the idea.