2D topdown player always look at mouse position

Started by
7 comments, last by vasdee 15 years, 3 months ago
I know this is a bit of a flogged horse, but I've got a bit of a problem with vector angles. I've trawled over the forums and tried every acos / atan2 combination I've dug up but no luck so far. The problem I'm having is that the player can move within a camera bounding area (without the camera following) and I need the player to always look at the mouse position. When the player is at the origin I can get the angle correctly using the atan2 method, but as soon as the player moves from the centre of the screen then the player's aim goes off, as shown in the screenshot. screenshot Does anyone know how I can always have the player pointing towards the mouse_aim position? I've been using the following code to calculate the angle but the values returned are off.... Halp? [help]

// Form the Position-Focus vector and Aim-Camera_Focus Vector
Vector3D a =  mPosition - camera_focus;
Vector3D b =  mAim - camera_focus;

// Normalize 
//a = a.Normalize();
//b = b.Normalize();

float dot = a.x * b.x + a.y * b.y;

// Determine the angle between the two vectors.
angle_inc_r = acos( dot / (a.Length() * b.Length()) );

angle_inc_d = int(RAD2DEG(angle_inc_r));

if( dot < 0 )
{
    angle_inc_d = -angle_inc_d;
}

Advertisement
At the first quick glance over your code I think the problem is that you include the camera_focus vector into the equations, although there should'nt be any reason to do so. The character's angle is derived from character position and mouse position alone.

cheers,
Mike
Quote:Original post by h4tt3n
The character's angle is derived from character position and mouse position alone.


Thanks for the reply.

I think that's what led me to this problem in the first place. If I use the below code to calculate the angle, then the player will be facing the correct direction when in the centre of the screen however if the player strays from the centre then the problem begins.

current_mouse = mAim - mpPosition;angle_r = atan2(current_mouse.y, current_mouse.x);angle_d =  RAD2DEG(angle_r);angle_d = int(angle_d) %360;


I think the problem stems from atan2 returning an angle about the origin. Any idea on how to cater for the player when they are not positioned at the origin?
You're getting side-tracked by where the player is standing. Just make a function

float get_angle ( vec2 v );

Then to get the player's angle
player.angle = get_angle ( mouse.pos - player.pos )

All that remains is to fill in the get_angle function.

One tip, don't just use atan since it will return poor results at certain angles. What you need to do is divide into cases (probably each representing 90 deg).

Something like
if ( v.y >= 0 )
{
if ( v.x >= 0 )
{
return atan(...);
}
else
{
return ...
}
}
else
{
...
}

And then use the best trig function for that domain.

If you don't like vectors, just make a function
get_angle ( float dx, float dy );

Oh, and you'll also want to test against the case when norm(v) is small (ie, the points are close together).
Quote:
One tip, don't just use atan since it will return poor results at certain angles. What you need to do is divide into cases (probably each representing 90 deg).


That's what atan2 is for. It handles this problem internally so you don't have to divide into cases.
Quote:Original post by jdindia
One tip, don't just use atan since it will return poor results at certain angles.


No, not if you use it right. No need for loads of if-then calls. If you feed the atan2 function with sine and cosine to the angle, it returns the angle in radians withing the range -pi, pi flawlessly. It might look something like:

Distance_vector = mouse.pos - character.posDistance_Scalar = sqr(Distance_vector.x*Distance_vector.x+Distance_vector.y* Distance_vector.y)Normalised_distance_vector = Distance_Vector/Distance_ScalarCosine_angle = Normalised_distance_vector.XSine_angle = Normalised_distance_vector.YAngle = Atan2(Sine_Angle, Cosine_Angle)


Cheers,
Mike
@h4tt3n Apart from the normalization part that's what I'm already doing which indeed gives the correct angle if the player is at the camera_focus however it is when the player is away from the camera focus where the angle gets screwy (check the first post pic for a screenshot).

It looks to me like I need some kind of translation vector derived from the player position and camera_focus but I just can't wrap my head around it. [depressed]
There's information missing within your code. What space are the different positions expressed in?

atan2 will not work if your mouse position and your character position are not within the same space. However, I suspect that your character position is expressed in world space but your mouse position is expressed in screen space. Have you converted one of the positions to the space of the other?
Quote:Original post by ToohrVyk
Have you converted one of the positions to the space of the other?


Thanks for the reply and yes i had converted the mouse coords into object coords however it jogged me into looking over it again. Looks like i had a bug in there when converting which was screwing with the vector angle calculations.

For those interested I had to interpolate between the near and far clipping plane using gluUnProject to get correct mouse coords in object space. This link helped:

http://stackoverflow.com/questions/113352/opengl-projecting-mouse-click-onto-geometry

Cheers everyone!

This topic is closed to new replies.

Advertisement