megalith/src/player/movement_controller.gd

62 lines
1.6 KiB
GDScript

class_name MovementController extends Node
## Character movement controller
@export var movement_enabled := true
@export_group("Speed")
@export var run_speed := 80.0
@export var sprint_speed := 160.0
@export var air_speed_factor := 0.1
@export_group("Jump")
@export var jump_force := 4.0
@export_group("Friction")
@export var ground_friction := 0.3
@export var air_friction := 0.04
var sprinting := false
var movement := Vector2.ZERO
@onready var character: CharacterBody3D = get_parent()
func get_speed() -> float:
var speed := run_speed
if sprinting:
speed = sprint_speed
if not character.is_on_floor():
speed *= air_speed_factor
return speed
func get_friction() -> float:
return ground_friction if character.is_on_floor() else air_friction
## Make the character jump.
func jump() -> void:
if movement_enabled and character.is_on_floor():
character.velocity.y = jump_force
func _physics_process(delta: float) -> void:
if not character.is_on_floor():
# Apply gravity
character.velocity += character.get_gravity() * delta
if movement_enabled:
# Apply movement input
var rel_movement := movement.rotated(-character.global_rotation.y)
var direction := Vector3(rel_movement.x, 0, rel_movement.y).normalized()
var motion := direction * get_speed() * delta
character.velocity.x += motion.x
character.velocity.z += motion.z
# Apply friction
var weight := 1.0 - exp(-get_friction() * 60 * delta)
character.velocity.x = lerpf(character.velocity.x, 0, weight)
character.velocity.z = lerpf(character.velocity.z, 0, weight)
character.move_and_slide()