extends Node3D const ROTATION_SPEED := 2.5 const MOUSE_SENSITIVITY := 0.003 const MIN_PITCH := deg_to_rad(-50.0) const MAX_PITCH := deg_to_rad(45.0) const ZOOM_MIN := 3.0 const ZOOM_MAX := 7.0 const ZOOM_SPEED := 5.0 const ZOOM_DEADZONE := 0.3 var yaw := 0.0 var pitch := deg_to_rad(20.0) var zoom_distance := 4.0 func _ready() -> void: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) zoom_distance = $Camera3D.position.z func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_RIGHT: if event.pressed: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) return if event.button_index == MOUSE_BUTTON_WHEEL_UP and event.pressed: zoom_distance = clampf(zoom_distance - ZOOM_SPEED * 0.05, ZOOM_MIN, ZOOM_MAX) return if event.button_index == MOUSE_BUTTON_WHEEL_DOWN and event.pressed: zoom_distance = clampf(zoom_distance + ZOOM_SPEED * 0.05, ZOOM_MIN, ZOOM_MAX) return if event is InputEventKey: if event.keycode == KEY_ESCAPE: if event.pressed: Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) return if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: yaw -= event.relative.x * MOUSE_SENSITIVITY pitch -= event.relative.y * MOUSE_SENSITIVITY pitch = clampf(pitch, MIN_PITCH, MAX_PITCH) func _physics_process(delta: float) -> void: var stick := _get_camera_stick_input() if stick.length() > ZOOM_DEADZONE: yaw -= stick.x * ROTATION_SPEED * delta pitch -= stick.y * ROTATION_SPEED * delta pitch = clampf(pitch, MIN_PITCH, MAX_PITCH) var player := get_parent() as Node3D var player_rot: float = player.rotation.y rotation_degrees.y = rad_to_deg(yaw) - rad_to_deg(player_rot) rotation_degrees.x = rad_to_deg(pitch) _handle_zoom_input(delta) var camera := $Camera3D camera.position.z = zoom_distance func _handle_zoom_input(delta: float) -> void: var zoom_in = Input.get_action_strength("camera_zoom_in") var zoom_out = Input.get_action_strength("camera_zoom_out") if zoom_in > 0 or zoom_out > 0: zoom_distance += (-zoom_in + zoom_out) * ZOOM_SPEED * delta zoom_distance = clampf(zoom_distance, ZOOM_MIN, ZOOM_MAX) func _get_camera_stick_input() -> Vector2: var right_x := Input.get_joy_axis(0, JoyAxis.JOY_AXIS_RIGHT_X) var right_y := Input.get_joy_axis(0, JoyAxis.JOY_AXIS_RIGHT_Y) return Vector2(right_x, right_y)