Files
godot-interaction-system/Scripts/PlayerController.gd
T

144 lines
4.2 KiB
GDScript

extends CharacterBody3D
@export var speed: float = 6.0
@export var jumpVelocity: float = 5.0
@export var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") as float
@export var acceleration: float = 20.0
@export var airAcceleration: float = 4.0
@export var friction: float = 10.0
var mouseBaseSensitivity: float = 0.004
var mouseSensitivity: float = 0.0
@export var mouseSensitivityMultiplier: float = 0.2
@export var head: Node3D
@export var camera: Camera3D
@export var raycast: RayCast3D
@export var hand: Marker3D
@export var crosshair: CanvasLayer
var lateJumpTime: float = 0.15
var lateJumpTimer: float = 0.0
var currentInteractable: Interactable
var dragging: bool = false
var pitch: float = 0.0
var playerId: String
var displayName: String
var mouseDelta: Vector2 = Vector2.ZERO
var interactionMouseDelta: Vector2 = Vector2.ZERO
var mouseHorizontalFactor: float = 1.0
var mouseVerticalFactor: float = 1.0
var targetMouseHorizontalFactor: float = 1.0
var targetMouseVerticalFactor: float = 1.0
@export var mouseFactorLerpSpeed: float = 2.0
func _ready():
mouseSensitivity = mouseBaseSensitivity * mouseSensitivityMultiplier
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
else:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _unhandled_input(event: InputEvent) -> void:
if Input.mouse_mode != Input.MOUSE_MODE_CAPTURED:
return
if event is InputEventMouseMotion:
if dragging and currentInteractable:
interactionMouseDelta += event.relative
mouseDelta += event.relative
func _physics_process(delta):
mouseHorizontalFactor = lerp(mouseHorizontalFactor, targetMouseHorizontalFactor, delta * mouseFactorLerpSpeed)
mouseVerticalFactor = lerp(mouseVerticalFactor, targetMouseVerticalFactor, delta * mouseFactorLerpSpeed)
if mouseDelta != Vector2.ZERO:
rotate_y(-mouseDelta.x * mouseSensitivity * mouseHorizontalFactor)
pitch -= mouseDelta.y * mouseSensitivity * mouseVerticalFactor
pitch = clamp(pitch, deg_to_rad(-90), deg_to_rad(90))
head.rotation.x = pitch
mouseDelta = Vector2.ZERO
if !is_on_floor():
velocity.y -= gravity * delta
lateJumpTimer -= delta
else:
lateJumpTimer = lateJumpTime
# Interaction search
if !dragging:
if raycast.is_colliding():
currentInteractable = Interactable.find(raycast.get_collider())
crosshair.setHover(true)
else:
currentInteractable = null
crosshair.setHover(false)
# Start interaction
if !dragging and currentInteractable:
if Input.is_action_just_pressed("interact"):
dragging = true
currentInteractable.beginInteract(self, raycast.get_collision_point())
# Update interaction
if dragging and currentInteractable:
if Input.is_action_just_pressed("throw"):
if currentInteractable is Pickupable:
currentInteractable.throw()
stopInteraction()
return
currentInteractable.updateInteract(self)
interactionMouseDelta = Vector2.ZERO
# End interaction
if dragging and currentInteractable:
if Input.is_action_just_released("interact"):
stopInteraction()
# Late jump buffering
if Input.is_action_just_pressed("jump") and lateJumpTimer > 0.0:
velocity.y = jumpVelocity
# Movement
var inputDir := Input.get_vector("left", "right", "forward", "backward")
var direction := (transform.basis * Vector3(inputDir.x, 0, inputDir.y)).normalized()
if is_on_floor():
if direction != Vector3.ZERO:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
velocity.x = lerp(velocity.x, 0.0, delta * friction)
velocity.z = lerp(velocity.z, 0.0, delta * friction)
else:
velocity.x = lerp(velocity.x, direction.x * speed, delta * airAcceleration)
velocity.z = lerp(velocity.z, direction.z * speed, delta * airAcceleration)
move_and_slide()
func setMouseFactors(horizontal: float, vertical: float):
targetMouseHorizontalFactor = clamp(horizontal, 0.0, 1.0)
targetMouseVerticalFactor = clamp(vertical, 0.0, 1.0)
func stopInteraction():
if currentInteractable:
currentInteractable.endInteract(self)
currentInteractable = null
dragging = false
interactionMouseDelta = Vector2.ZERO