Player Aim at Mouse Cursor
by Jesse Allen · in Torque 3D Professional · 10/30/2014 (11:48 am) · 7 replies
Hi all, I'm looking for some guidance around adjusting $mvPitch. Most of the math is already figured out, but there is one piece missing that is preventing this from working. Here's the scenario:
Here's the stuff that's already been done to solve this:
So now that the position data is in place, time to do some work. First thing is to get the point where the mouse's ray is hitting the plane the player is on (thanks to Daniel Buckmaster for the initial math about the plane point, adjusted to fit the new script call here):
Okay, so now the next step. Time to get the Tangent of the two points to calculate our angle:
There is one missing link here. Above I just plugged in the mClamp from the original pitch function( in client/default.bind.cs ) which should limit the range of the aiming angle. The sensitivity dampening part was just trial and error a bit since by default sensitivity was way too high. It's not enough though, and something is not being calculated properly:
So, I've got the basis for something great but there is a missing piece. I feel that it is dealing with the range and sensitivity but there could be an additional factor I've overlooked. If anyone has any ideas, I'd love to give them a shot. Thanks in advance for any guidance.
- The scene is sideview, so the camera is aimed at a 90 degree angle at the Player.
- The Player moves left and right on the 'x' axis.
- The goal is to move the mouse cursor and have the player aim at the mouse cursor.
Here's the stuff that's already been done to solve this:
- Noticing that the PlayGUI is a GameTSCtrl, I observed that the 'onMouseMove' callback for the class didn't have a proper script call.
- To fix this, I added a call to the function GameTSCtrl::makeScriptCall() into the GameTSCtrl::onMouseMove() callback function. This makes it so that we can do this in script:
function PlayGui::onMouseMove(%this, %pos, %start, %ray)
function PlayGui::onMouseMove(%this, %pos, %start, %ray)
{
%ray = VectorScale(%ray, 100);
%end = VectorAdd(%start, %ray);
%planePoint = "0 0 0";
%planeNormal = "0 -1 0";
%t = VectorDot(%planeNormal, VectorSub(%planePoint, %start))
/ VectorDot(%planeNormal, VectorSub(%end, %start));
%intersect = VectorAdd(%start, VectorScale(VectorSub(%end, %start), %t));
echo(%intersect);
}This works fine, and if the mouse is dragged it will echo out the proper position data on 'x' and 'z'. Since the Player is moving left and right on 'x', the 'y' will always be 0. Also to note is ultimately the %planePoint may end up being the Player's location or eyeVector?function PlayGui::onMouseMove(%this, %pos, %start, %ray)
{
%ray = VectorScale(%ray, 100);
%end = VectorAdd(%start, %ray);
%planePoint = "0 0 0";
%planeNormal = "0 -1 0";
%t = VectorDot(%planeNormal, VectorSub(%planePoint, %start))
/ VectorDot(%planeNormal, VectorSub(%end, %start));
%intersect = VectorAdd(%start, VectorScale(VectorSub(%end, %start), %t));
echo(%intersect);
%x = getWord(%intersect, 0);
echo (%x);
%z = -getWord(%intersect, 2); // Flip the z
echo (%z);
// Should be using inverse tangent...
// Get the inverse tangent of the mouse intersect point
%angle = mAtan(%z, %x);
// ...but tangent works too
// Get the tangent of the mouse intersect point
// %angle = mTan( %z / %x );
// Clamp the range and...
%angle = mClamp(%angle, -m2Pi() + 0.01, m2Pi() - 0.01);
// ...dampen the sensitivity a bit
%angle *= 0.06;
// Set the pitch
$mvPitch += %angle;
}Now this part works as well, as far as getting the Tangent and it actually does make the player's pitch move with the mouse cursor. Notice I tried the inverse and the regular Tangent and both seem to give the same result(technically I think the inverse Tangent is proper). There is one missing link here. Above I just plugged in the mClamp from the original pitch function( in client/default.bind.cs ) which should limit the range of the aiming angle. The sensitivity dampening part was just trial and error a bit since by default sensitivity was way too high. It's not enough though, and something is not being calculated properly:
- The Player will aim up and down as the mouse cursor goes up and down. Correct.
- The Player will not aim precisely at the mouse cursor at all times. Incorrect.
So, I've got the basis for something great but there is a missing piece. I feel that it is dealing with the range and sensitivity but there could be an additional factor I've overlooked. If anyone has any ideas, I'd love to give them a shot. Thanks in advance for any guidance.
About the author
Skilled Artist and Musician. Intermediate Torque Developer.
#2
I did actually try to simulate what you're suggesting with the AIPlayer just to see what would happen. In the AIPlayer class, there exists the function setAimLocation(). When I set that location with the AIPlayer to the location found with the mouse ray/plane intersection, the AIPlayer did indeed aim at the position - although it was very 'jittery' and not fluid. Also I believe the 'range' isn't proper.
Unfortunately, there isn't such a function for the standard Player class that accepts an input 'aim Location'. Instead, we're forced to shoot the data at the player with the $mvPitch variable and get the math/sensitivity/range just right :/
10/30/2014 (12:00 pm)
Thanks for the quick reply Richard. I did actually try to simulate what you're suggesting with the AIPlayer just to see what would happen. In the AIPlayer class, there exists the function setAimLocation(). When I set that location with the AIPlayer to the location found with the mouse ray/plane intersection, the AIPlayer did indeed aim at the position - although it was very 'jittery' and not fluid. Also I believe the 'range' isn't proper.
Unfortunately, there isn't such a function for the standard Player class that accepts an input 'aim Location'. Instead, we're forced to shoot the data at the player with the $mvPitch variable and get the math/sensitivity/range just right :/
#3
Also, at this point, I'd suggest looking up PID control. You might want to do some variant of that. Skip the I and use PD control, so your pitch calculations would look something like
$mv_pitch = %a * %pitch_diff + %b * $mv_pitch_last;
I think. %a is your proportional (P) gain and %b is your differential (D) gain.
10/30/2014 (3:14 pm)
More detailed info, pics or a vid would be really helpful. If the player doesn't always aim at the cursor, when does it? Where does it aim at the other times? Not sure what specific issues you're running into.Also, at this point, I'd suggest looking up PID control. You might want to do some variant of that. Skip the I and use PD control, so your pitch calculations would look something like
$mv_pitch = %a * %pitch_diff + %b * $mv_pitch_last;
I think. %a is your proportional (P) gain and %b is your differential (D) gain.
#4
I'll give a good stab at it, but soon I'll just upload a simple sideview template to GitHub with all of this in it so you can just run it :D Besides, it could prove useful for others who try to approach side-scrollers in the future - not to mention it could be built off of for a side-scrolling template!
10/30/2014 (3:31 pm)
Thanks Danny. I'll definitely do some research around the suggestion you've pointed out :)I'll give a good stab at it, but soon I'll just upload a simple sideview template to GitHub with all of this in it so you can just run it :D Besides, it could prove useful for others who try to approach side-scrollers in the future - not to mention it could be built off of for a side-scrolling template!
#5
10/30/2014 (10:24 pm)
I am not totally understanding all of what is going on here, but I think I will need to soon because I need to have the player position his/ her view when in talking mode to point at the NPC's face. Is this principle being described here down the correct road of what I need to know or is it for something completely different? Thank you as always for your direction.
#6
What the topic is dealing with is trying to adjust the angle at which the Player aims up/down by using the mouse cursor instead of allowing it to happen 'auto' by movement of the mouse when the cursor is not present.
If it is a sideview project you are working on, perhaps it is only necessary for the Player to face left or right towards the NPC (assuming the NPC's are about the same height). If this is the case, it's just a simple matter of setting the transform. If you do, indeed, want to look up/down at NPC's it could probably be adjusted a bit easier than what we've got here.
I'm more than happy to help if you need it, just let me know :)
10/30/2014 (11:59 pm)
@DreamPharoah: Based on your description, it's hard to tell. Is your project sideview? If so, is your Player shorter/taller than the NPC's with which it'll need to speak with - in other words, would it need to adjust its head to look up or down at NPC's? What the topic is dealing with is trying to adjust the angle at which the Player aims up/down by using the mouse cursor instead of allowing it to happen 'auto' by movement of the mouse when the cursor is not present.
If it is a sideview project you are working on, perhaps it is only necessary for the Player to face left or right towards the NPC (assuming the NPC's are about the same height). If this is the case, it's just a simple matter of setting the transform. If you do, indeed, want to look up/down at NPC's it could probably be adjusted a bit easier than what we've got here.
I'm more than happy to help if you need it, just let me know :)
#7
10/31/2014 (2:33 pm)
@Jesse: All of what you are trying to do makes sense to me now. This is something that is completely different to what I will eventually need. The NPC's currently are just repeats of the main character and so they are about head level, and it is in a free roam first person perspective. I know there will be NPC's that will be of different sizes soon once I finalize this main character though. I have been able to set transform before but I will also eventually want the player to be able to select follow, and have the player's character auto follow an NPC on quest eventually as well. I think I will wait on doing all of this at a later time. Thank you for offering to help.
Torque Owner Richard Ranft
Roostertail Games