SchildDerStaerke/scripts/player.gd

115 lines
3.4 KiB
GDScript

class_name Player extends Unit
const PITCH_MIN_DEG := -90.0
const PITCH_MAX_DEG := 30.0
const JOY_DEADZONE := 0.10
@export var mouse_sensitivity: float = 0.006
@export var rotation_speed: float = 24.0
@export var joypad_sensitivity: float = 2.0
@export var spring_arm: SpringArm3D
signal gold_changed(current_gold: int)
signal player_loaded()
var _gold: int = 0
var gold: int:
get:
return _gold
set(value):
if _gold == value:
return
_gold = value
gold_changed.emit(_gold)
func _ready() -> void:
health = maximum_health
stamina = maximum_stamina
player_loaded.emit()
func _physics_process(delta: float) -> void:
# Gravity
velocity.y += -gravity * delta
# Movementw
get_move_input(delta)
move_and_slide()
# Smooth face direction to camera
if velocity.length() > 1.0:
model.rotation.y = lerp_angle(model.rotation.y, spring_arm.rotation.y, rotation_speed * delta)
# Joypad camera
var axis_x := Input.get_joy_axis(0, JOY_AXIS_RIGHT_X)
var axis_y := Input.get_joy_axis(0, JOY_AXIS_RIGHT_Y)
if absf(axis_x) > JOY_DEADZONE or absf(axis_y) > JOY_DEADZONE:
move_camera_joypad(axis_x, axis_y, delta)
func rotate_camera(pitch_delta: float, yaw_delta: float) -> void:
# Apply deltas and clamp pitch; yaw is unbounded
spring_arm.rotation.x += pitch_delta
spring_arm.rotation_degrees.x = clampf(spring_arm.rotation_degrees.x, PITCH_MIN_DEG, PITCH_MAX_DEG)
spring_arm.rotation.y += yaw_delta
func move_camera_joypad(x: float, y: float, delta: float) -> void:
# Scale by sensitivity and frame time; invert to match mouse feel
var pitch_delta := -y * joypad_sensitivity * delta
var yaw_delta := -x * joypad_sensitivity * delta
rotate_camera(pitch_delta, yaw_delta)
func player_game_over():
GameManager.game_over()
queue_free()
func _input(event: InputEvent) -> void:
# Move camera via mouse
if event is InputEventMouseMotion:
var motion := event as InputEventMouseMotion
var pitch_delta := -motion.relative.y * mouse_sensitivity
var yaw_delta := -motion.relative.x * mouse_sensitivity
rotate_camera(pitch_delta, yaw_delta)
var on_floor := is_on_floor()
# Jump
if on_floor and Input.is_action_just_pressed("jump"):
if enough_stamina_available(jump_cost):
use_stamina(jump_cost)
velocity.y = jump_speed
state = States.jumping
anim_tree.set("parameters/conditions/grounded", false)
# We just hit the floor after being in the air
if on_floor and not last_floor:
if state != States.idle:
state = States.idle
anim_tree.set("parameters/conditions/grounded", true)
# We're in the air, but we didn't jump
if not on_floor and state != States.jumping:
anim_state.travel("Jump_Idle")
anim_tree.set("parameters/conditions/grounded", false)
anim_tree.set("parameters/conditions/jumping", state == States.jumping)
last_floor = on_floor
# Menu
if event.is_action_pressed("Menue"):
get_tree().quit()
func get_move_input(delta: float) -> void:
var vy := velocity.y
velocity.y = 0.0
var input_vector := Input.get_vector("left", "right", "forward", "back")
var direction := Vector3(input_vector.x, 0.0, input_vector.y).rotated(Vector3.UP, spring_arm.rotation.y)
if state == States.blocking:
direction = Vector3.ZERO # TODO: Walk while blocking
velocity = velocity.lerp(direction * speed, acceleration * delta)
var v_local := velocity * model.transform.basis
anim_tree.set("parameters/IWR/blend_position", Vector2(v_local.x, -v_local.z) / speed)
velocity.y = vy