gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > Changing an object's movement vector

#122580 - Rajveer - Tue Mar 20, 2007 2:09 pm

Hi guys. I have a racing "ship" which has a few forces acting on it,a nd I want to know if my logic in calculating the final direction/speed of the ship is correct:

Forces:
Ship's thrust vector: We'll call this the thrust vector, or thrust velocity when not normalised. Direction is the same as the ship's z-axis.
Ship's speed: Speed at a given time, which I'll increase by a constant acceleration or decrease when no thrust, in the direction of the thrust vector.

Gravity vector: Simply (0, -1, 0) as it always acts downwards on a large scale.
Gravity speed: The speed at a given time of the ship in the -ve y-axis caused by the acceleration of gravity (only when no collision with the ground in my case).

Final vector: Final direction for the ship to move.
Final speed: Magnitude of the final vector before normalisation.

I'm thinking of breaking down the calculations as such:
Code:

----------------------------
-Left/Right held:
*Rotate ship left/right

-A held:
*Increase ship thrust speed i.e. ship accelerates along ship's z-axis
-A NOT held:
*Decrease ship thrust speed
-Limit ship speed:
*Cannot exceed maximum speed, cannot go below 0

-Combine Ship's thrust vector and speed with finalvector and final speed (from previous frame):
*Q: Would I combine the ship's non-normalised thrust vector (so magnitude = thrust speed) with the ship's non-normalised final vector (from the previous frame)?? If I do, every frame I'll be accelerating the ship with a constant force as I'll keep increasing the final vector's magnitude, so instead do I combine the ship's non-normalised thrust vector with the ship's NORMALISED final vector??? And then calculate the final speed from this?? (I.e. magnitude of the final vector)

-Check Collision:
*Check collision between polygons and line from ship's current position and future position
*If intersection, move ship just infront of polygon so it doesn't pass through it
IF Check Collision is false, move ship all the way from current position to future position

-Check Ground Collision:
*Fire ray from bottom of ship to polygons, check if intersects
*If it does intersect and is within certain distance, rotate ship to matrix alignment of the ground (then next frame, the final vector will tend toward this rotation), apply friction i.e. final speed * 0.9f?
*If not, apply gravity: increase "gravity speed" by gravitational acceleration, add to move vector. Again same question: would I add the non-normalised gravity vector to the non-normalised final vector??
----------------------------

#122586 - Rajveer - Tue Mar 20, 2007 3:32 pm

I think I've answered my own questions. I SHOULD add the unnormalised final vector that the ship is moving in from the last frame to the unnormalised thrust vector that is applied during the current frame, and the magnitude of the final vector for the current frame after the additions (i.e. the speed) should keep increasing, BUT the friction should limit this speed with something like "drag(v) = kv^2" where v is the speed, to get a terminal velocity. Is this right?

If it is, in which order should I be doing all of this? At the moment I'm adding the thrust vector, checking for a collision between polygons and the line from the current position and the future position defined by the new final vector, checking if the ship is on the ground THEN adding friction if it is...

#122617 - Ant6n - Tue Mar 20, 2007 9:03 pm

Well the physics for a simple model kind of goes like this:
we know F_total = m*a, with m the mass and a the acceleration
and we know F = F_gravity + F_'thrust' + F_friction + F_lift
F_gravity, F_thrust should be obvious, or one could cook up a simple model, F_lift is mostly relevant for airplane type objects. F_friction in a useful approximation could be written like
F_friction = - a*v^2 - b*v.
a is the fluid, b the viscious drag. Depending on the speed of the object and the sorrounding elements one of the two components is usually negligible. v In this case the unit vector of the volocity (not absolute, but relative to movement of environment, i.e. take wind into account).
If you plug this into the above equation, you get some relation ship on a and v. Since a is the first time derivative of v, and you have three components, you get a system of differential equations. I think in most simple games the solution is not used, instead people use a numerical approximation. That is, one stores the position and velocity, and calculates the new force using the current velocity (and position, if required) and thrust. The new force gives the acceleration. this acceleration is added on top of the velocity (be carefule with the time!), and that new velocity is added onto the position.

#122618 - keldon - Tue Mar 20, 2007 9:07 pm

Objects have a velocity vector. The velocity determines the speed and direction that the object travels. The velocity is altered by acceleration, so gravity acts like a constant acceleration down.

#122660 - poslundc - Wed Mar 21, 2007 1:09 am

Rajveer wrote:
Gravity vector: Simply (0, -1, 0) as it always acts downwards on a large scale.
Gravity speed: The speed at a given time of the ship in the -ve y-axis caused by the acceleration of gravity (only when no collision with the ground in my case).

Final vector: Final direction for the ship to move.
Final speed: Magnitude of the final vector before normalisation.


I find it confusing that you have an implied expectation that Cartesian vectors are normalized.

Vectors express both direction and magnitude, but you are using them to express direction only, which is misleading. (It can be a valid performance optimization, but optimization should come last, and if you have a reason to cache a normalized direction vector then you'll want to call it out as such for that purpose.)

So, I would use either Cartesian vectors exclusively, or spherical coordinates (magnitude plus direction in terms of pitch and yaw) to store your forces, and calculate one from the other when necessary. (Or cache one from the other when necessary, but only expose one at a time rather than combining them as you currently do.)

Between those two, I'd recommend sticking with Cartesian vectors most of the time and calculating things like magnitude when you need them. With Cartesian vectors you can easily add a bunch of forces, velocities or positions together to obtain the resultant force/velocity/position.

Dan.