Trig work in c++

So I am making a 3d game in c++, and right now I am working on movement. At first I only had absolute movement (forward was always forward even if you were turned) but that obviously would not be appropriate so I began work on a relative movement equation. This is what I have so far:

     //x is x-axis movement
     //z is the z axis movement
     //theta is the player's rotation around the y axis
     //joypos[0] is the joystick x axis
     //joypos[1] is the joystick y axis
     //The goal is to make it so even if you turn 90 degrees
     //and you are pushing the joystick forward, you still move
     //forward in relation to your player.

     if(theta > 3.1415 * 2) theta = 0;
     if(theta < -3.1415 *2) theta = 0;

     r = sqrt(pow(joypos[0], 2) + pow(joypos[1], 2));

     if(r != 0) 
	x -= r * cos(acos(joypos[0]/r) + theta);
	z += r * sin(asin(joypos[1]/r) + theta);

Right now it is not working if your theta value is around pi or -pi radians. When you are around that rotation, there is no difference between pushing the joystick right or left (or up and down), you always move the same way.

Also: The equations essentially convert the raw input to polar and add the angle of rotation, then convert back to rectangular so opengl can render it.
For starters... you want to avoid calling trig functions. They're computationally expensive. You want to call them only when needed.

For instance... pow(x,2) is a terrible way to square a number. (x*x) should be preferred.

You also do not want to do this:
if(theta > 3.1415 * 2) theta = 0;

If you must reduce the numbers (which may not even be necessary... as sin/cos wrap as you'd expect anyway) you should subtract 2*pi, not reset to zero. After all if the user rotates to 3*pi, and you reset to 0, their new direction will be 0 instead of pi like it should be.

Same problem with your other if.

All of that said... this can probably be simplified.

Assuming this works like a normal, modern 3D game (X,Y axis control movement/strafe and Z axis controls which way the user is facing)...

Your angle theta should be calculated based on the direction the player is currently facing. From this angle, you should form a 2x2 rotation matrix used for movement:

However, for your pursposes, you don't need to fully implement a matrix... you can just shortcut it with this formula:

x2 = x*cos(theta) + z*sin(theta)
z2 = -x*sin(theta) + z*cos(theta)

Now since movement is going to occur more frequently than the player reorienting themself, you should keep track of sin(theta) and cos(theta) separately so they do not need to be calucated as much.

// whenever 'theta' changes
sinTheta = sin(theta);
cosTheta = cos(theta);

Now on playermovement, you have everything you need to push the player in the right direction. You simply take their movement vector (your joystick input) and run it through the rotation matrix (previously given):

playerX = /* -1.0 to 1.0 depending on joystick input */;
playerZ = /* -1.0 to 1.0 depending on joystick input */;

pos.x += playerX*cosTheta + playerZ*sinTheta;
pos.z += -playerX*sinTheta + playerZ*cosTheta;

EDIT: fixed they're / their
Last edited on
First of all, thank you for replying! It fixed my problem (for the most part) and it helped speed up the program.

However, when the player is turned in the direction of pi/2 radians in any direction relative to the world, their movements are inverted from what they should be. However all their other movements are fine. Any suggestions?

P.S. I could debug this on my own, but you seem to have implemented this before and you could most likely offer a quick fix.
Sounds like one of your axis might be inverted. Try negating the Z axis.
Topic archived. No new replies allowed.