extends CharacterBody3D const SPEED := 5.0 const JUMP_VELOCITY := 4.5 const MOUSE_SENSITIVITY := 0.003 const ACCEL := 20.0 const DECEL := 15.0 func _ready() -> void: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED func _input(event: InputEvent) -> void: if event is InputEventKey: if event.keycode == KEY_ESCAPE and event.pressed: Input.mouse_mode = Input.MOUSE_MODE_VISIBLE return if event.keycode == KEY_SPACE and event.pressed and is_on_floor(): velocity.y = JUMP_VELOCITY if event.keycode == KEY_E and event.pressed and not event.echo: var node = $yaw/pitch/Facing.get_collider() if node and node.has_method("interact"): node.interact(self) if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: $yaw.rotate_y(-event.relative.x * MOUSE_SENSITIVITY) $yaw/pitch.rotate_x(-event.relative.y * MOUSE_SENSITIVITY) $yaw/pitch.rotation.x = clamp( $yaw/pitch.rotation.x, deg_to_rad(-89.0), deg_to_rad(89.0) ) func _physics_process(delta: float) -> void: # Gravity if not is_on_floor(): velocity += get_gravity() * delta # Read keyboard state directly var input_x := 0.0 var input_z := 0.0 if Input.is_key_pressed(KEY_A): input_x -= 1.0 if Input.is_key_pressed(KEY_D): input_x += 1.0 if Input.is_key_pressed(KEY_W): input_z -= 1.0 if Input.is_key_pressed(KEY_S): input_z += 1.0 # Create movement vector var input_direction := Vector3(input_x, 0.0, input_z) # Prevent diagonal movement from being faster if input_direction.length_squared() > 0.0: input_direction = input_direction.normalized() # Rotate movement relative to yaw var direction : Vector3 = $yaw.global_transform.basis * input_direction direction.y = 0.0 if direction.length_squared() > 0.0: direction = direction.normalized() # Target velocity var target := direction * SPEED var acceleration := ACCEL if direction.length_squared() == 0.0: acceleration = DECEL # Smooth movement toward target velocity.x = move_toward( velocity.x, target.x, acceleration * delta ) velocity.z = move_toward( velocity.z, target.z, acceleration * delta ) move_and_slide()