extends CharacterBody3D @export var camera: Camera3D var SPEED = 2.0 const JUMP_VELOCITY = 4.5 const MOUSE_SENSITIVITY = 0.004 const ROTATION_SPEED := 4.0 # How fast to interpolate (higher = snappier) var target_rotation := Vector2.ZERO # x = pitch, y = yaw func _ready() -> void: assert(camera != null, "Forgot to set camera in editor") Input.mouse_mode = Input.MOUSE_MODE_CAPTURED # Initialize target rotation from current rotation target_rotation.y = rotation.y target_rotation.x = camera.rotation.x func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: target_rotation.y -= event.relative.x * MOUSE_SENSITIVITY target_rotation.x -= event.relative.y * MOUSE_SENSITIVITY target_rotation.x = clamp(target_rotation.x, deg_to_rad(-80), deg_to_rad(80)) func _process(delta: float) -> void: # Smoothly interpolate current rotation toward target rotation.y = lerp_angle(rotation.y, target_rotation.y, delta * ROTATION_SPEED) camera.rotation.x = lerp_angle(camera.rotation.x, target_rotation.x, delta * ROTATION_SPEED) const ACCELERATION := 10.0 const DECELERATION := 6.0 var input_direction := Vector3.ZERO var target_velocity := Vector3.ZERO func _get_input_direction() -> Vector3: var direction := Vector3.ZERO if Input.is_key_pressed(KEY_LEFT) or Input.is_key_pressed(KEY_A): direction.x -= 1 if Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_D): direction.x += 1 if Input.is_key_pressed(KEY_UP) or Input.is_key_pressed(KEY_W): direction.z += 1 if Input.is_key_pressed(KEY_DOWN) or Input.is_key_pressed(KEY_S): direction.z -= 1 return direction.normalized() func _physics_process(delta: float) -> void: # Get input direction relative to player orientation input_direction = _get_input_direction() var basis := global_transform.basis var forward := -basis.z.normalized() var right := basis.x.normalized() # Desired horizontal movement direction in world space var desired_velocity : Vector3 = (right * input_direction.x + forward * input_direction.z) * SPEED desired_velocity.y = 0 # Only horizontal # Smooth acceleration/deceleration var accel := DECELERATION if input_direction == Vector3.ZERO else ACCELERATION target_velocity.x = lerp(target_velocity.x, desired_velocity.x, accel * delta) target_velocity.z = lerp(target_velocity.z, desired_velocity.z, accel * delta) # Preserve existing vertical velocity if not is_on_floor(): target_velocity.y += get_gravity().y * delta else: target_velocity.y = 0 if Input.is_action_just_pressed("ui_accept"): target_velocity.y = JUMP_VELOCITY # Apply movement velocity = target_velocity move_and_slide()