1. ## Velocity vector troubles

In my recent asteroids clone I've encountered a lot of problems with the velocity vector of the ship and the actual rotation angle of the ship.

What I'm currently doing is when the user presses a rotate key (left or right arrow if it has not been re-assigned) I simply change the Z rotation of the ship without altering the velocity vector. The velocity vector is only altered when the user presses the thrust key (up arrow). This makes for a really cool floating type effect where you can actually be heading in one direction but have your ship pointed in another firing on whatever you need to fire on.

Big problem: I cannot clamp the velocity vector to reasonable values using this method. In other words it's possible to speed the ship up to some insane rates - to the point of not being able to distinguish what is going on in the game with your ship.

Code:
```void GetKeys(void)
{
Keyboard.Update();

if (Keyboard.KeyDown(AST_LEFT))
{
Ship.Rotate(LEFT);
Ship.ZRotation.x=cos(Ship.GetAngle());
Ship.ZRotation.y=sin(Ship.GetAngle());
}
if (Keyboard.KeyDown(AST_RIGHT))
{
Ship.Rotate(RIGHT);
Ship.ZRotation.x=cos(Ship.GetAngle());
Ship.ZRotation.y=sin(Ship.GetAngle());
}

if (Keyboard.KeyDown(AST_THRUST))
{
Ship.VelVector+=(Ship.ZRotation);
}```

Solutions I've tried:

Keep the velocity vector normalized and multiply the normalized vector by a scalar speed amount.
Problem: Since the speed value is a scalar, you cannot simply increase it every time the user presses the thrust key. This results in the velocity vector overshooting the actual rotation vector - the ship goes nuts.

Clamp the velocity vector components to certain ranges
This works but since you are clamping based on range instead of x/y relation the final velocity vector might not represent the actual rotation vector. For instance clamping x and y to .50 while having a rotation vector of 135 would not work.

Clamp based on the length of the velocity vector
This works until you max the length - then there is no way to lessen the length because the thrust key is effectively locked out, thus the length stays constant.

I'm open to any ideas you might have.

2. It seems that the thrust should be a set ammount, say 0.25f.
normalize the direction vector of the thrust (ie ships pointing direction) and multiply that vector by the 0.25f scaler.
Then add this new acclereation vector to the current velocity vector of the ship.
Code:
``` If accel vector+velocity vector > max velocity scaler
velocity vector = normalize( velocity vector + accel vector ) * max velocity
else if accel vector + velocity vector <= max velocity scaler
velocity vector = velocity vector + accel vector```
I'm pretty sure that method should achieve desired results.

3. PS: (4:57am my time) I've uploaded a javascript demonstration, mostly for my own exercise in coding since it's been a while and I need to warm up for next semester but to also show you what I meant.

try http://www.jeremygiberson.com/javascripts/velocity.html (ie only, my scripts too hard for mozilla ;p)

edit: standard W,S,A,D controlls the ship.

4. Pretty much what jeremy said:

The orientation of the thrust should be some normalized direction. When the user presses 'forward', you apply a force in that direction, that force over the mass of the spacecraft is the acceleration.

dt is the change in time for the frame. Use this if you want the force to be applied continuously. If this is an 'impulse' force, i.e a force that acts over a very very short (infinitely small) period of time, get rid of the dt and come up with some realistic values for the impulse

if(FORWARD)
{
Vector Force = Spacecraft.ForwardOrientationVector * ForceMagnitude * dt;

Vector Accel = Force * (1/Spacecraft.Mass);

Spacecraft.WorldspaceVelocity += Accel;

}

that's the basic idea

5. Isn't that what he is already doing?

Wouldn't this method work?
Code:
```if |vel| > max
vel = max/|vel|  * vel```
Do not lock the thrust key, just keep this check afterwards!
That way you'll still be able to change the velocity the way you are doing it now.

6. I agree with Sandrax. Use the magnitude of the vector determine if it is greater than max. then if so normalize it to max. What is wrong with that.

7. If you read my post I already tried to clamp based on the magnitude of the vector but it does not work. Problem is that even though the magnitude of the vector might be at some value that is no guarantee that the ship is moving only in that direction. A magnitude implies that regardless of direction we clamp....which is not good because it is possible to clamp the vector even though it does not line up with the z rotation of the ship.

For instance. Press forward several times to thrust. Press left and right to rotate - stop the rotation near, but not at, the same rotation angle that you thrusted at to start with. Now apply lots of thrust in this direction. The magnitude of the resulting vector will clamp before your ship actually begins to follow the new z rotation of your ship because the first vector was so large. In essence:

1. Rotate to face right (90 degrees in my setup), thrust several times.
2. Rotate right 90 degrees to face down. Thrust several times.
3. If you clamp on magnitude the ship will face straight down (180 in my setup), but the resulting vector will clamp somewhere between 90 and 180 since the magnitude does not care about direction, it only cares about a scalar quantity.

So this won't work.

Code:
```...
float dist=D3DXVec3Length(&Ship.VelVector);
if (dist<some_scalar)
{
...```
Also if you notice when the vector does finally clamp...you cannot add any more thrust because there is no way to decrease it's magnitude since the vector summation happens inside of the condition that assumes the length or magnitude is less than some scalar quantity.

if(FORWARD)
{
Vector Force = Spacecraft.ForwardOrientationVector * ForceMagnitude * dt;

Vector Accel = Force * (1/Spacecraft.Mass);

Spacecraft.WorldspaceVelocity += Accel;

}
This is what I'm doing minus the physics. I'm not using actual physics in the game since it's just an asteroids clone.
And I don't need a speed_scalar to multiply by since I'm only doing vector summation, thus when the velocity vector lines up with the z rotation of the ship, the ship acceleration along that vector is increased since the velocity vector now is no longer normalized.

8. Originally Posted by Bubba
For instance. Press forward several times to thrust. Press left and right to rotate - stop the rotation near, but not at, the same rotation angle that you thrusted at to start with. Now apply lots of thrust in this direction. The magnitude of the resulting vector will clamp before your ship actually begins to follow the new z rotation of your ship because the first vector was so large.
Not using the method I posted. The direction of the velocity will always approach the new direction.

The ship will hit max speed, true, but the direction of the velocity will still change because you aren't disabling the thrust key when the speed is at the maximum.
Code:
```float dist=D3DXVec3Length(&Ship.VelVector);
if (dist<some_scalar)
{
There's your problem. The thrust key should always be able to add thrust, then use the simple check I posted to keep the magnitude of the velocity vector below the limit.

9. Ok I think I'm understanding. In other words clamp the magnitude of the vector, but prior to that go ahead and do the vector summation so that the thrust key works. I'm locking the thrust key out not by literally locking it out, but by clamping the final value.

Like this:

Code:
```
x+=increment;
if (x>some_scalar)  x=max_value;```
This allows x to still increment yet when it maxes, it is clamped to a max value.

That makes sense. Not sure why this threw me for a loop. I've been working with so much other math pertaining to 3D as well as scripts, vertex/pixel shaders...my head is spinning.

Thanks a bunch Sang-drax for clearing this up.