Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How can I 'clamp' an angle calculated by math.atan2?

Asked by 7 years ago
Edited 7 years ago

I'm trying to mimic a third person camera in an old game I used to play, and I'm using math.atan2() to calculate the angle at which the camera should rotate, relative to the head (so it's looking at the head). However, when I move my character via the mouse (mouse is locked to the center of the screen), the rotation goes crazy.

I want to 'clamp' it, or prevent it from going completely bonkers.

Here's the code for the camera:

--> Constantly update the camera.
RS:BindToRenderStep( "Camera", 201, function()
    local z = camera.CFrame.Z - character.Head.CFrame.Z
    local y = camera.CFrame.Y - character.Head.CFrame.Y

    pitch = atan2( y, z )

    root.CFrame = cf( root.Position ) * ca( -0, rad( yaw * 5 ), 0 )

    camera.CFrame = camera.CFrame:lerp(
        root.CFrame * cf( 0, -2.5, 7.5 ) * ca( pitch, 0, 0 ),
        0.4
    )
end )

root is the character's HumanoidRootPart.

cf and ca are both CFrame.new() and CFrame.Angles() respectively.

atan2 is of course math.atan2().

I apologize if what I'm asking is too vague. Here's a gif to illustrate my problem:

I want the camera to pitch up and down, always pointing at the head as the mouse moves up and down (not yet implemented, but I manipulated the CFrame so you could see the angle) without doing what it does now when I rotate the character.

Any help would be appreciated, thank you!

2 answers

Log in to vote
1
Answered by
duckwit 1404 Moderation Voter
7 years ago
Edited 7 years ago

Ah, periculosa, you're so close! Your solution would be perfect for a 2-dimensional world. You want to find the vertical angle between the camera and the head, which means you need to calculate the angle between a line and a plane, not between 2 lines.

Notice in your GIF that the strange rotation happens only when you're facing in a certain direction - this is a hint that you've overlooked one of the 3 spatial dimensions.

Take these two lines:

    local z = camera.CFrame.Z - character.Head.CFrame.Z
    local y = camera.CFrame.Y - character.Head.CFrame.Y

What will happen when the character is facing directly in the x-direction, but not in the z-direction? z will become very tiny, so the vertical difference would be relatively much larger than this negligible horizontal difference. atan2 will interpret this as looking up at a very steep angle. This is confirmed empirically in your tests; when facing a certain direction, the camera flips upwards.

What is the solution? Instead of finding the difference in just the z-axis, you want to find the whole horizontal distance, that is, the length of a 2-dimensional vector in the horizontal plane x-z.

--Remove vertical component
local camera_horizontal = Vector3.new(camera.CFrame.X, 0, camera.CFrame.Z)
local head_horizontal = Vector3.new(character.Head.CFrame.X, 0, character.Head.CFrame.Z)

--Find magnitude of difference
local diff = (camera_horizontal - head_horizontal).Magnitude

pitch = atan2( y, diff )

EDIT: The angle didn't need to be clamped, per se, but I think the calculation of the angle was incorrect and I addressed that. When you do need to clamp values into a range, which you probably will want to do for some effects when creating your own Scriptable cameras, refer to evaera's suggested technique.

0
Thank you! It really works a charm and I love your explanation on it - thank you and evaera both, I've learned a couple new things today! pericuIosa 32 — 7y
Ad
Log in to vote
0
Answered by
evaera 8028 Trusted Badge of Merit Snack Break Game Jam Winner Moderation Voter Administrator Community Moderator Super Administrator
7 years ago

Really having trouble understanding what you mean still, but you can use this code to clamp an angle.

angle = math.max(-2.8, math.min(angle, 0.4))

where -2.8 is the bottom, and 0.4 is the top. Note that this is in radians

0
That's my fault, I'm sorry - I should've tried to illustrate my problem more. Thank you for telling me how to clamp though, I've learned two new things! pericuIosa 32 — 7y

Answer this question