The bug was quickly tracked down. As it turns out, we were referencing the camera limits, which were in global space, and using that to clamp the player’s local position.
func limit_camera_bounds() -> void:
if camera:
# Incorrect:
position.x = clamp(position.x, camera.limit_left, camera.limit_right)
position.y = clamp(position.y, camera.limit_top, camera.limit_bottom)
# Correct:
global_position.x = clamp(global_position.x, camera.limit_left, camera.limit_right)
global_position.y = clamp(global_position.y, camera.limit_top, camera.limit_bottom)
I keep forgetting that position
is for local position and that if I want to modify the global position, I need to use global_position
.