Sign in to follow this  
pix0l

How can I make my gamepad controls adjust to the camera angle?

Recommended Posts

Hi. I need a bit of help on this. I'm trying to make a boxing game and I'm working on making the gamepad controls of the boxer change which direction they make the boxer move in depending on the camera angle and the boxer. The camera is controlled by the mouse and the boxer is controlled by the gamepad. If the camera was facing the same direction as the boxer then you'd be viewing him from behind so it would make sense to press up on the gamepad to make the boxer move forward. If the camera swings around so it's facing the opposite side of the boxer so you're now viewing him from the front it would make more sense to press down on the gamepad to move the boxer forward. That's the basics of what I'm trying to do. To figure out which direction the camera is facing to the boxer I'm using this formula to calculate the angle between two vectors. Where one vector is the boxer vector and the other the camera vector. A . B = ||A|| ||B|| arccos(theta) What that gives me is an angle between 0 and 180 degrees which I was thinking of using to solve my problem and it works fine as long as the boxer remains on the origin of the world while the camera rotates around him. The controls change as I would expect. When I translate (no roation) the boxer off the origin and across the different axis the camera angles calculated become meaningless and don't work as I'm expecting. If you've done this before or have any ideas on a better way to have my gamepad controls change depending on the camera position please enlighten me.

Share this post


Link to post
Share on other sites
No responses eh. I've searched on google and looked into several game programming books and haven't really found anything on this topic yet. I guess it's basically a third person camera and control issue and there really doesn't seem to be much information on 3rd person implementations out there.

I've been stuck on this problem for about two weeks now. I've spent countless hours making modifications to the formula I've been using to calculate the angle between two vectors and also trying to come up with entirely different methods to find the angle between the camera and the player with moderate sucess so far.

I have figured out that if I translate the player back to a fixed position near the origin and move the camera the same amount the calculations come out as I'd expect most of the time but there are still conditions where I'm getting strange angles returned and that's causing my controls to go all wrong. I think it has something to do with when the boxer and/or camera vector crosses the x and z axis and that makes the angle between them go weird.

I'm going to post my angle calculating code in a bit. Maybe someone can see where I'm going wrong.


Real getAngleOfPlayerToCamera()
{
// Get the camera and boxer vectors.

Vector3 cameraVector = g_pCamera->getPosition();
Vector3 boxerVector = g_pActor->sceneNode->getPosition();

// Move the boxer vector back to 0,0,-1 and move the camera vector by the same amount.

// First invert the signs of the boxer vector components. If x is 10 it becomes -10. If x is -10
// it becomes 10. This effectively points the vector in the complete opposite direction.

boxerVector.x *= -1;
boxerVector.z *= -1;

// Now move the camera the opposite direction of the boxer vector. Essentially we're moving the
// the camera in the opposite direction to where the boxer is to simulate the same orientation.
// This way the angles can be calculated in a predictable way.

cameraVector.x += boxerVector.x;
cameraVector.z += boxerVector.z;

// Now we'll pretend the boxer vector is still at 0,0,-1.

boxerVector.x = 0;
boxerVector.z = -1;

// Find the dot product of cameraVector and boxerVector.

Real dotProduct = 0;

dotProduct += (cameraVector.x * boxerVector.x);
dotProduct += (cameraVector.z * boxerVector.z);

// Find the magnitude of the cameraVector and the boxerVector.

Real cameraMagnitude = 0;
Real boxerMagnitude = 0;

// Start by squaring each component of the vectors and summing them.

cameraMagnitude += (cameraVector.x * cameraVector.x);
cameraMagnitude += (cameraVector.z * cameraVector.z);

boxerMagnitude += (boxerVector.x * boxerVector.x);
boxerMagnitude += (boxerVector.z * boxerVector.z);

// Now find the square root of the squared and summed components of each vector to get their magnitudes.

cameraMagnitude = Ogre::Math::Sqrt(cameraMagnitude);
boxerMagnitude = Ogre::Math::Sqrt(boxerMagnitude);

// Next we multiply the camera magnitude by the boxer magnitude to get a denominator for the next exression

Real denominator = cameraMagnitude * boxerMagnitude;

// We'll now find the cosine for the angle between the two vectors by dividing the dot product of the two
// vectors by the denominator.

denominator = dotProduct / denominator;

// Finally we can calculate the angle between the two vectors by using the cosine we just calculated with the
// inverse cosine function. The function returns the angle in radians.

Radian rad = Ogre::Math::ACos(denominator);

// Get the radian amount returned in degrees.

Real myDegrees = rad.valueDegrees();

return myDegrees;
}


Share this post


Link to post
Share on other sites
Hi pix0l; I haven't implemented a 3D graphics engine yet but I have played around a bit with 3D coordinates and have a maths background, so I'll see if I can help...

I'm not sure entirely how you are wanting to control your boxer, but I'll assume that the boxer's movement is constrained to a 2D plane (I'll call this the 'ground plane'). One thing I'm not sure you are using currently is the oreintation of the camera. 3D ojects have six degrees of information needed to represent their position; their (x,y,z) coordinate in 3D space (where they are), and their orientation (tilt, roll, yaw or whatever they are called, I always get confused over terminology [grin]). I'd be using the orientation vector rather than the position vector for determining the movement.

Does this help?

Share this post


Link to post
Share on other sites
Hi Trapper, thanks for the help.

The boxer is constrained to a 2 dimensional ground plane running along the x and z axis. I thought I already tried using the orientation vector but maybe I'll give it another shot since I do have a little more experience with this stuff now.

To give a better idea of the camera I'm using it's a standard first person shooter style camera where w,a,s,d translate the camera position forward, back and strafing left or right and the mouse rotates the look at target, I guess, along the pitch and yaw or whatever. Like you I'm confused by the never ending terminology and can't be bothered to look it up at the moment so we're even. :D

So what I do to test things out is use the mouse and try to keep the camera look at position centered on the boxer while I strafe around the boxer by changing the camera position. This is just the default camera in the rendering engine I'm using to start out with.

I'm really not sure what using the camera look at vector instead of the camera position vector would do. I'll give it a(nother) shot anyway.


Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Try using the angles of the camera for the movement, as in forward vector and right vector, instead of generic X Y or whatever.

If you press forward, move the boxer in the direction of the camera forward. If you move right, move the boxer in the direction of the camera right vector, etc.

Oh and ignore the verticle angle of course ;)

Share this post


Link to post
Share on other sites
I've got a bit of time while this lengthy computation process is running, so I see if I can help a bit more.

I've been thinking about your control system a bit, and maybe an analogy might help, since representing 3D diagrams is a little bit tricky in pure text.

Imaging that your camera is an arrow pointing at your boxer. I'm using a pencil as a guide at the moment as it's sharp and point. Now take a piece of paper, and draw a plus-sign (or compass point) shape labelled 'Up','Down','Left','Right' on the appropriate arms, and stick it on the pencil. (Note: you don't actually have to do this, imagination is okay! [grin])
Then I'm thining from your description the directions on the plus-sign are the ones you want your boxer to move in when you move the joystick in the appropriate directions.

Then the problem you need to solve is what directions the plus-sign corresponds to in the 'ground plane' that the boxer can move it. What you need to do is project the vectors pointing in the direction of the plus sign into the ground plane to give you the direction needed.

Hope that's clear, I'm not that sure I've really explained myself glancing over it a second time.

Share this post


Link to post
Share on other sites
I just finished implementing something as has been similarly described already, i.e. using a forward and right/left vector from the current camera position. It's really not that hard. In my game, the vector <0, 0, -1> represents the forward direction. In my game, when you press the 'w' key you move forward in the direction the camera is facing, ala Descent. It's really easy to do this if you take the unit vector for the forward direction (<0, 0, -1>) and rotate it by the camera angle. Then you're left with a vector that you can use to translate the camera in the direction of the camera. You can do something very similar with a left/right vector (<-1, 0, 0> or <1, 0, 0>). Hope this helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by strtok
I just finished implementing something as has been similarly described already, i.e. using a forward and right/left vector from the current camera position. It's really not that hard. In my game, the vector <0, 0, -1> represents the forward direction. In my game, when you press the 'w' key you move forward in the direction the camera is facing, ala Descent. It's really easy to do this if you take the unit vector for the forward direction (<0, 0, -1>) and rotate it by the camera angle. Then you're left with a vector that you can use to translate the camera in the direction of the camera. You can do something very similar with a left/right vector (<-1, 0, 0> or <1, 0, 0>). Hope this helps.


That's sort of what I was trying to explain, although not very well. [smile]

There's an extra step that needs to be done here since unlike Descent, the boxer is confined to a 2D plane. I'm assuming that the camera here is above the ground, pointing slightly down towards the ring. That's why a vector projection into the ground plane is required.

But, yep, that's the general principle, strtok. Or at least what I'm thinking.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Try using the angles of the camera for the movement, as in forward vector and right vector, instead of generic X Y or whatever.

If you press forward, move the boxer in the direction of the camera forward. If you move right, move the boxer in the direction of the camera right vector, etc.

Oh and ignore the verticle angle of course ;)


I'm not sure I understand what you're telling me. Could you maybe show me a simple example if you have some free time?

What I'm doing now is basing the translation of the boxer on the angle I get back between the camera position vector. So for example if the camera is at a 180 degree angle to the boxer vector then the boxer is facing the viewer while the camera faces the front of the boxer then if I push the down direction on the gamepad this will translate the boxer forward.

If the angle is at 90 degrees then say the camera is facing the left side of the boxer then if I push the left direction on the gamepad the boxer will move forward...etc.

So I'm not using the angles of the camera but the angle of the camera position vector to the boxer vector which is in a constant fixed position near the world origin. Then depending on the angle I get back I change the direction I translate the boxer in.

Hope I'm not repeating myself too much. Just trying to make it clear what I'm doing. I'm probably going to have to study some more camera stuff unless someone spells this out for me.

Read your other posts. Thanks for the replies people. My brain is mathed out for tonight I'll get back to this tomorrow and let you know how it's going. I'd really like to get past this soon. My math is really crappy!

[Edited by - pix0l on July 12, 2005 3:08:49 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Anon here again, I'll try and explain a little more...

The camera should have a forward vector, a vector pointing to its right or left depending on your system, and a vector pointing up.

Damn this is hard without pictures....

Up
^ Forward
| /
| /
|/
------> Right

Now if this was an FPS, if I press forward then I would move in the direction of the camera's forward:

pos += Forward * TimeDelta;

Where forward is a unit vector. And if I press right:

pos += Right * TimeDelta;

Now you can map that directly to your boxer's position. But be sure to ignore the verticle angle; ie..

Y
^ Z
| /
|/
-----> X

In which case you ignore the Y in your vectors.... like...

Camera Forward = (0.4f, 0.5f, 0.4f) then you would ignore the Y and just have:

New Camera Forward = (0.4f, 0.0f, 0.4f)

Then, normalize the vector to make sure it is unit length.

Just remember you aren't actually changing the camera's vectors here, just a copy of it to use in your calculations!

So, all you would do to move the boxer is:

Boxer Position += (0.4f, 0.0f, 0.4f) * TimeDelta;

And of course TimeDelta is the time between frames.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Anon again, if your having trouble getting your camera's vectors, but the camera always faces the boxer, then heres an example:

(Boxer.position - Camera.Position).Normalize() = Camera Forward

If your world Up vector is (0,1,0), then you could use a cross product to get your right vector:

Up.Cross( Forward ) = Right, depending on your coordinate system etc.

Share this post


Link to post
Share on other sites
Thanks anon for the explanation. Also thanks to everyone who replied. I think I get what you are all trying to tell me now. I did some reading up and have a feel for this. I was doing this in a strange way, trying to calculate the angle between two vectors. Just illustrates my crappy math abilities. The solution is so simple I feel like a noob :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this