[XNA] 3D Bullet offset

Started by
26 comments, last by -XM- 13 years, 9 months ago
Hey guys, I'm working on a 3D space shooter. Right now I have my ship flying around and firing bullets.... except the bullets are firing underneath the ship. So to fix this I added an offset vector (Vector3 bulletOffset = new Vector3(80.0f, 600.0f, 0.0f);) that fixes the bullet to where I need it to go.

However, when I move my ship downwards the bullet starts firing in weird places, I understand what I need to do to fix this I'm just not sure how. I need to update that offset when the ship rotates, but how would I go about doing that? Is there a formula that would easily fix this or do I need to manually update the offset when the X Y and X values are at a certain place?

Thanks for your time

Advertisement
Don't know what your parameters look like, but, assuming you have the ship's position and direction vectors:

bullet_start = ship_position + ship_dir * some_distance_to_nose_of_ship
bullet_dir = ship_dir

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I plugged in that formula and the bullet stayed in the same position for some reason....

It currently looks like this:


Vector3 bulletOffset = new Vector3(80.0f, 600.0f, 0.0f);
Bullet newBullet = new Bullet();
newBullet.position = ship.Position + ship.Direction * bulletOffset;
newBullet.rotation = ship.Direction;

bulletList.Add(newBullet);


ship.Direction and bulletOffset should both be vector objects.

Check how the operators + and * are overloaded.

Then find out what maths they are set to carry out and try it on paper. I'll figure it out and edit this or reply if I can shed any light on it.

Basically your intention is to have ship.Direction * bulletOffset give a new vector which is of the magnitude of bulletOffset but in the direction of shipDirection. Then you want to add the components of the resulting vector and the ship's positional vector - which should give what you want, the correct location for the bullet to spawn.

Try ** instead of *, which might be overloaded for the cross product rather than * which may be the dot product.

+, (Ax + Bx )i + (Ay + By )j + (Az + Bz )k
*, Ax*Bx + Ay*By + Az*Bz
**, i*(Ay*Bz-Az*By) - j*(Ax*Bz - Az*Bx) + k*(Ax*By - Ay*Bx)

I think. I might have confused myself.

It may also be that the operator overloads are strange, and you have to use the methods to do vector operations.

Try Vector3.Cross(Vector3,Vector3)

[Edited by - Bozebo on July 3, 2010 10:11:40 AM]
Quote:ship.Direction and bulletOffset should both be vector objects

Incorrect. "buttetOffset" should be a length ("some_distance_to_nose_of_ship"), not a vector. It is the distance (a simple float value) from the center of the ship to the point where you want the bullet to appear along the direction the ship is facing when it is fired.

E.g., assume it is 5 units from the center (position) of the ship to the nose of the ship. Also assume that the ship is at a position ( 10,40,0 ) with a direction ( 0.7, 0.7, 0 ) when a bullet is fired.

The bullet will be given a position of:
ship_position + distance * ship_direction =
( 10, 40, 0 ) + 5*( 0.7, 0.7, 0) =
( 10, 40, 0 ) + ( 3.5, 3.5, 0 ) =
( 13.5, 43.5, 0 )

The bullet's direction (not rotation) = ( 0.7, 0.7, 0 ).

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Quote:ship.Direction and bulletOffset should both be vector objects


Actually, they both are in XM's second post, otherwise he'd got a compilation error (Edit: Sorry, now I was confused, too, since I thought of a scalar product).

Smells like operator overloading confusion. According to the XNA docs:

Quote:Vector3.op_Multiply (Vector3, Vector3) Multiplies the components of two vectors by each other.


i.e. (x1,y1,z1) * (x2,y2,z2) => (x1*x2, y1*y2, z1*z2)

This is a.k.a. as a modulate and is not appropriate here.

If you have an offset other than on the x-axis alone you will need to transform the offset with the current transformation matrix of your ship. How do you draw your ship ? Do you use a transformation (i.e. XNA Matrix class) ? If so, you probably can use Vector3.Transform() for the offset and Vector3.TransformNormal() for the bullets direction. If not, you have to create one or do what Buckeye did for every axis seperately (which is basically the same).

Hope that helps.

unbird
Quote:"buttetOffset" should be a length

That would be convenient, but we are talking about a Microsoft framework here :D

I may be wrong but, does the order of the operators do something in particular when they are overloaded? Ie, if an integer is then multiplied with * by a vector3 object, would vector3 pick up that it was called to be multiplied by that integer? Or does it only overload the operators placed after the object in question? I think it can be made to do both, but in my inexperience I havn't actually delved much into the area yet. That is probably something I should learn quite soon.

ie:
int someInt 5;
Vector3 someVector(4,11,-0.21);
Vector3 result;

result = someInt * someVector; //can this be overloaded in the someVector class?
result = someVector * someInt; //someVector is overloaded to take someInt into a method?

What if overloaded operators are on both sides of 2 objects, would it know which to take the overload from? I could be totally wrong however, I am speculating.

Because, otherwise you would have to make a definition that works like int but has an overloaded operator? Or do you just work with ordering your logic in the correct way? Again, speculation... I need to go and learn these things.
Quote:Original post by unbird
Quote:ship.Direction and bulletOffset should both be vector objects


Actually, they both are in XM's second post, otherwise he'd got a compilation error (Edit: Sorry, now I was confused, too, since I thought of a scalar product).

Smells like operator overloading confusion. According to the XNA docs:

Quote:Vector3.op_Multiply (Vector3, Vector3) Multiplies the components of two vectors by each other.


i.e. (x1,y1,z1) * (x2,y2,z2) => (x1*x2, y1*y2, z1*z2)

This is a.k.a. as a modulate and is not appropriate here.

If you have an offset other than on the x-axis alone you will need to transform the offset with the current transformation matrix of your ship. How do you draw your ship ? Do you use a transformation (i.e. XNA Matrix class) ? If so, you probably can use Vector3.Transform() for the offset and Vector3.TransformNormal() for the bullets direction. If not, you have to create one or do what Buckeye did for every axis seperately (which is basically the same).

Hope that helps.

unbird


Yeah, I need the offset on the X and Y axis to make it look correct. So, would I stll use "newBullet.position = ship.Position + ship.Direction * bulletOffset;" after I transform the offset and TransformNormal for the direction?

Also, bulletOffset should be a vector because I have to change both X and Y? From my understanding from what you guys are saying bulletOffset should be a length only if I need to change one axis?

Thanks everyone for the replies, learning a lot from these posts.... this is my first 3D game attempt, all of my other programming endeavors have been in 2D.
Sorry, I apparently made an assumption about how you were setting the position for the bullet to start. Maybe you can clarify your variables.

Is your bulletOffset vector with respect to the ship position vector, or is it a world position? It's not really clear how you are using that offset.

That is, when a bullet is fired, do you set the bullet's starting position as ship_position + bulletOffset?

Perhaps you could post some code.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

No problem, I probably wasn't being very clear. My code is set up exactly like you mentioned (ship_position + bulletOffset)

if (aButtonPressed == 1)
{
double currentTime = gameTime.TotalGameTime.TotalMilliseconds;
if (currentTime - lastBulletTime > 100)
{
Vector3 bulletOffset = new Vector3(60.0f, 600.0f, 0.0f);
Bullet newBullet = new Bullet();
newBullet.position = ship.Position + bulletOffset;
newBullet.rotation = ship.Direction;

bulletList.Add(newBullet);

lastBulletTime = currentTime;
}

aButtonPressed = 0;
}


That is all of my code for creating a bullet. ship.Position is taken from my ship class where all of the ship movement is being calculated, as is the ship.Direction.

When I run the code the bullet is perfectly positioned except when I start to move down or up it starts to fire in the weird positions.

If I can post anything else to help just let me know :)

This topic is closed to new replies.

Advertisement