Godot Version
v4.2.1.stable.official [b09f793f5]
Question
I’m having problems keeping a rotation correctly clamped, relative to another node’s rotation.
I am setting up a player controller, consisting of two sprites, a body and a head. Depending on the direction the body faces, the head’s rotation should be limited between two limits (an anti-clockwise bound and a clockwise bound) centred on the body’s rotation. Within this range, the head tries to look towards the cursor’s location on the screen, restricted by the edges of the bound.
I’ve used clamping to limit the angles either side of the body’s direction, but it fails when the body is facing backwards (close to -PI or +PI radians). I’m unsure how to keep the head consistently bounded across this part of the body’s rotation.
extends Area2D
@onready var body : Sprite2D = $Body
@onready var head : Sprite2D = $Head
@onready var camera : Camera2D = $Camera
var max_speed := 200.0
var rotational_speed := 2.0
func _process(delta : float) → void:
var input_direction := Vector2(0,0)
var velocity := Vector2(0,0)
var cursor_angle := (get_global_mouse_position() - global_position).angle() # Auto-wraps from Pi to -Pi
var cw_bound := 0.0
var anti_cw_bound := 0.0
input_direction.x = Input.get_axis(“move_left”,“move_right”)
input_direction.y = Input.get_axis(“move_up”,“move_down”)
if input_direction.length() > 1.0:
input_direction = input_direction.normalized()
body.rotation = wrapf(body.rotation,-PI,PI) # Keeps body rotation within radian limit
if Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT): # 'Aiming' ability, to look wherever
head.rotation = cursor_angle
else:
anti_cw_bound = wrapf(body.rotation - PI/4,-PI,PI) # Vision restricted to a cone facing the direction of the body
cw_bound = wrapf(body.rotation + PI/4,-PI,PI)
print("Cursor angle : ", cursor_angle, " . Anti-CW bound : ", anti_cw_bound, " . CW bound : ", cw_bound, " . Body angle : ", body.rotation)
# ERROR
head.rotation = clampf(cursor_angle,anti_cw_bound,cw_bound)
# ERROR here. When body angle is close to 180 degrees (-PI or +PI radians), in -ve or +ve direction, the clamping fails
#print(body.rotation, ": Body rotation.", head.rotation, ": Head rotation.", cursor_angle, ": Cursor angle.")
velocity = input_direction * delta * max_speed
if input_direction.length() > 0.0:
body.rotation += wrapf(velocity.angle() - body.rotation,-PI,PI) * delta * rotational_speed
position += velocity
camera.global_position = (get_global_mouse_position() + global_position)/2