Code quality first and foremost
That's a lot of duplicated code you've got going on there. If you've got duplicated code, you need to do it differently - duplicated code is dangerous (you'll change one side but forget to change the other and get logic errors).
- If you've got duplicated code down both ends of a conditional, take it out of the conditional.
- If you still need to only execute it conditionally (e.g. when the key is a or d) wrap it all in its own conditional.
- Consider helper methods.
Now the answer
What you need is to get the Camera's rotation matrix: the exact direction it's pointing.
If the classes you're working with can return that from the camera itself, great! If it can't, you can calculate it based on the camera position and target - see here for one way to do that.
Once you have the camera's rotation matrix, you can just set up the movement vector then rotate it to point in the camera's direction using its rotation matrix.
The advantage of this approach is you can instantiate one general movement matrix, throw in all the vertical, horizontal and forward movement for your character in that update, do all the calculations you'd like on all of it then you do one rotation to face the camera and make that movement happen all at once.
I have no idea which language or framework you're using so I'm going to be using some C# and XNA here.
var keys = Keyboard.GetState();
if (MovementKeysPressed())
{
var eyeOriginal = g_eye;
var targetOriginal = g_target;
var viewEye = g_math.subVector(g_eye, g_target);
var viewTarget = g_math.subVector(g_target, g_eye);
// The important camera rotation stuff happens here
// Determine camera rotation. I am assuming that:
// g_eye is the camera's location,
// g_target is where it's looking,
// and they are both Vector3s
var up = [0, g_up[1]*-1, 0];
var cameraRotationMatrix4 = g_math.matrix4.lookAt(g_eye, g_target, up);
// The rotation component of a 4D transformation matrix is always
// the upper-left 3x3
var cameraRotation = g_math.getUpper3x3(cameraRotationMatrix4);
// Right now we're only doing *direction* of movement - working with 1s only.
// Speed comes after rotation.
var xMovement = 0;
if (keys.A.Down) xMovement -= 1;
if (keys.D.Down) xMovement += 1;
var movementVector = [xMovement, 0, 0];
// Note that holding both A and D is possible and gets you nowhere.
// Sets the vector's length to 1. You'll understand why this is important
// after we introduce speed.
var movementVector = g_math.normalize(movementVector);
// rotate movement to face camera.
var realMovementVector = g_math.rowMajor.mulVectorMatrix(movementVector, cameraRotation);
// Now for speed.
// We earlier normalized movementVector to give it a magnitude (length) of 1.
// After we rotated it, it still only had magnitude of 1.
// Any movement would always create only 1 unit of movement in any direction.
// Let's say you want your character to move faster than that though!
// What if you want your character to move at 4.2 units per update?
// By multiplying it by a scalar (aka integer), we multiplied its magnitude,
// which is now (1 x 4.2) = 4.2. It will now move 4.2 units either left or right
// of the camera (unless the player has both 'a' and 'd' held down).
var speed = 4.2;
var speedThisStep = delta * speed;
realMovementVector = g_math.mulVectorScalar(realMovementVector, speedThisStep);
viewEye = g_math.addVector(realMovementVector, viewEye);
viewTarget = g_math.addVector(realMovementVector, viewTarget);
// End important camera stuff
g_eye = g_math.addVector(viewEye, targetOriginal);
g_target = g_math.addVector(viewTarget, eyeOriginal);
}
MovementKeysPressed = function() {
// current state of the keyboard, stores for each key
// whether it's pressed or not
var keys = Keyboard.GetState();
return (keys.A.State == KeyState.Down || keys.D.State == KeyState.Down);
}
Changes:
- Complete refactor
- Did camera-rotatey things in the code.
- Changed the first argument in the last two occurrences of
viewEye
and viewTarget