Rotating my character to aim

Godot Version

v4.3 stable

Question

I’m trying to rotate my character to aim with the right stick in a top down 2D twin stick shooter. I figured I could do it 2 ways.

1st way:

func rotationTan(delta):
	var newAimDirection = Vector2(Input.get_axis("AimLeft", "AimRight"), Input.get_axis("AimUp", "AimDown"))
	if newAimDirection!= Vector2.ZERO:
		theta = wrapf(atan2(newAimDirection.y, newAimDirection.x) - rotation, -PI, PI)
		rotation += clamp(rotationSpeed * delta, 0, abs(theta)) * sign(theta)

This works smoothly

2nd way:

func aimRotation(delta):
	var newAimDirection = Input.get_vector("AimLeft", "AimRight","AimUp", "AimDown")
	if newAimDirection!= Vector2.ZERO:
		theta = aimDirection.angle_to(newAimDirection)
		rotate(min(delta * rotationSpeed, abs(theta)) * sign(theta))
		aimDirection = newAimDirection

I believe my math is correct but that does not work. I think it’s because every frame I am doing this:

aimDirection = newAimDirection

but not sure how to fix it

I think its because rotation is being done over time due to rotationSpeed but the rotation is coming from the theta between aiming directions, and doesn’t consider current rotation.

When you aim around I think the most you rotate is by delta * rotationSpeed and then, unless you keep wiggling the aim, you just get ~0 theta afterwards.

Edit: How to fix it depends on how you want it to feel. If you stop aiming and you haven’t finished rotating, should it finish rotating or should it stop?

If you want it to stop rotating when you stop aiming, I think you can just change theta to come from the difference between current rotation and newAimDirection.

If you want it to always rotate to where you last aimed then you separate rotation from aiming and have a simple “if current angle not aligned with aim direction, rotate towards aim direction.”

The 2nd solution you proposed if i want to always rotate to where I last aimed is basically my first way of doing it right?

unc rotationTan(delta):
	var newAimDirection = Vector2(Input.get_axis("AimLeft", "AimRight"), Input.get_axis("AimUp", "AimDown"))
	if newAimDirection!= Vector2.ZERO:
		theta = wrapf(atan2(newAimDirection.y, newAimDirection.x) - rotation, -PI, PI)
		rotation += clamp(rotationSpeed * delta, 0, abs(theta)) * sign(theta)

Is there a way to get the same result using the rotate function?

Right now rotation happens when aim input is not zero. So separate the function into two parts (or two funcs).

  1. Check player input for aim dir. If it’s not zero, update our current aim direction.

  2. You have current rotation in radians, something like aimdir.angle() should work to give desired radians, theta is from those two. Then you limit it like before, rotating with max speed or the remaining distance, whatever is smaller.

Thanks
My issue ended up being me not understanding how the godot rotate function works.