Files
the-tower/Player/player_controller.gd

110 lines
3.4 KiB
GDScript3
Raw Normal View History

extends CharacterBody3D
const JUMP_SPEED: float = 5
const MOUSE_SENSITIVITY: float = 0.002
const CROUCH_MOVE_SPEED: float = 3
const BASE_MOVE_SPEED: float = 5
const SPRINT_MOVE_SPEED: float = 8
const BASE_HEIGHT: float = 2.0
const CROUCH_HEIGHT: float = 1.0
const CROUCH_TRANSITION_SPEED: float = 0.1
enum MovementMode {
Crouching,
Sprinting,
Walking,
}
var current_movement := MovementMode.Walking
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
var move_speed: float = BASE_MOVE_SPEED
var target_height: float = BASE_HEIGHT
@onready var body_collision_shape: CollisionShape3D = $BodyCollisionShape
@onready var fps_camera: Camera3D = $FPSCamera
@onready var head_collision_shape: CollisionShape3D \
= $HeadCollider/HeadCollisionShape
@onready var head_collider: Area3D = $HeadCollider
func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
head_collision_shape.set_deferred("disabled", true)
func _process(_delta: float) -> void:
if Input.is_action_just_pressed("pause"):
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
else:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _physics_process(delta: float) -> void:
handle_state_transition()
handle_movement(delta)
body_collision_shape.shape.height = lerpf(body_collision_shape.shape.height,
target_height, CROUCH_TRANSITION_SPEED)
move_and_slide()
if is_on_floor() and Input.is_action_just_pressed("jump"):
velocity.y = JUMP_SPEED
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion \
and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
rotate_y(-event.relative.x * MOUSE_SENSITIVITY)
fps_camera.rotate_x(-event.relative.y * MOUSE_SENSITIVITY)
fps_camera.rotation.x = clampf(fps_camera.rotation.x,
-deg_to_rad(70), deg_to_rad(70))
func handle_movement(delta: float) -> void:
velocity.y += -gravity * delta
var input = Input.get_vector("strafe_left", "strafe_right",
"move_forward", "move_backward")
var movement_dir := transform.basis * Vector3(input.x, 0, input.y)
velocity.x = movement_dir.x * move_speed
velocity.z = movement_dir.z * move_speed
func handle_state_transition() -> void:
match current_movement:
MovementMode.Crouching:
if not Input.is_action_pressed("crouch") \
and not head_collider.has_overlapping_bodies():
change_state(MovementMode.Walking)
MovementMode.Walking:
if Input.is_action_pressed("crouch"):
change_state(MovementMode.Crouching)
elif Input.is_action_pressed("sprint"):
change_state(MovementMode.Sprinting)
MovementMode.Sprinting:
if Input.is_action_pressed("crouch"):
change_state(MovementMode.Crouching)
elif not Input.is_action_pressed("sprint"):
change_state(MovementMode.Walking)
func change_state(new_state: MovementMode) -> void:
if new_state == current_movement:
return
exit_state()
current_movement = new_state
enter_state()
func exit_state() -> void:
match current_movement:
MovementMode.Crouching:
head_collision_shape.set_deferred("disabled", true)
func enter_state() -> void:
match current_movement:
MovementMode.Walking:
move_speed = BASE_MOVE_SPEED
target_height = BASE_HEIGHT
MovementMode.Crouching:
head_collision_shape.set_deferred("disabled", false)
move_speed = CROUCH_MOVE_SPEED
target_height = CROUCH_HEIGHT
MovementMode.Sprinting:
move_speed = SPRINT_MOVE_SPEED
target_height = BASE_HEIGHT