|
|
|
|
@ -1,18 +1,17 @@
|
|
|
|
|
class_name Player extends Unit
|
|
|
|
|
|
|
|
|
|
const PITCH_MIN_DEG := -90.0
|
|
|
|
|
const PITCH_MAX_DEG := 30.0
|
|
|
|
|
const JOY_DEADZONE := 0.10
|
|
|
|
|
class_name Player
|
|
|
|
|
extends Unit
|
|
|
|
|
|
|
|
|
|
const CAMERA_PITCH_MIN_DEG := -90.0
|
|
|
|
|
const CAMERA_PITCH_MAX_DEG := 30.0
|
|
|
|
|
const JOYPAD_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
|
|
|
|
|
@ -22,56 +21,95 @@ var gold: int:
|
|
|
|
|
_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)
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
|
|
|
# Physik: Schwerkraft, Bewegung, Ausrichtung, Kamera per Joypad
|
|
|
|
|
apply_gravity(delta)
|
|
|
|
|
update_movement(delta)
|
|
|
|
|
move_and_slide()
|
|
|
|
|
update_facing(delta)
|
|
|
|
|
handle_joypad_camera(delta)
|
|
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
# Deltas anwenden; Pitch clampen, Yaw ungebunden
|
|
|
|
|
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_degrees.x = clampf(spring_arm.rotation_degrees.x, CAMERA_PITCH_MIN_DEG, CAMERA_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
|
|
|
|
|
# Skalierung nach Sensitivität und Framezeit; invertiert für Maus-ähnliches Gefühl
|
|
|
|
|
var pitch_delta := -y * joypad_sensitivity * delta
|
|
|
|
|
var yaw_delta := -x * 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
|
|
|
|
|
# Kamera per Maus
|
|
|
|
|
handle_mouse_camera(event)
|
|
|
|
|
# Boden-/Luft-Logik
|
|
|
|
|
var on_floor := is_on_floor()
|
|
|
|
|
handle_jump(on_floor)
|
|
|
|
|
update_ground_state(on_floor)
|
|
|
|
|
# Menü
|
|
|
|
|
if event.is_action_pressed("Menue"):
|
|
|
|
|
get_tree().quit()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# --- Extracted/neu strukturierte Hilfsfunktionen ---
|
|
|
|
|
|
|
|
|
|
func apply_gravity(delta: float) -> void:
|
|
|
|
|
velocity.y += -gravity * delta
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func update_movement(delta: float) -> void:
|
|
|
|
|
# Bewegungsinput lesen und anwenden
|
|
|
|
|
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: Gehen während Blocken erlauben
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func update_facing(delta: float) -> void:
|
|
|
|
|
# Sanft in Blickrichtung der Kamera drehen, wenn wir uns merklich bewegen
|
|
|
|
|
if velocity.length() > 1.0:
|
|
|
|
|
model.rotation.y = lerp_angle(model.rotation.y, spring_arm.rotation.y, rotation_speed * delta)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func handle_joypad_camera(delta: float) -> void:
|
|
|
|
|
var right_stick_x := Input.get_joy_axis(0, JOY_AXIS_RIGHT_X)
|
|
|
|
|
var right_stick_y := Input.get_joy_axis(0, JOY_AXIS_RIGHT_Y)
|
|
|
|
|
if absf(right_stick_x) > JOYPAD_DEADZONE or absf(right_stick_y) > JOYPAD_DEADZONE:
|
|
|
|
|
move_camera_joypad(right_stick_x, right_stick_y, delta)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func handle_mouse_camera(event: InputEvent) -> void:
|
|
|
|
|
if event is InputEventMouseMotion:
|
|
|
|
|
var motion := event as InputEventMouseMotion
|
|
|
|
|
var motion := event as InputEventMouseMotion
|
|
|
|
|
var pitch_delta := -motion.relative.y * mouse_sensitivity
|
|
|
|
|
var yaw_delta := -motion.relative.x * mouse_sensitivity
|
|
|
|
|
var yaw_delta := -motion.relative.x * mouse_sensitivity
|
|
|
|
|
rotate_camera(pitch_delta, yaw_delta)
|
|
|
|
|
|
|
|
|
|
var on_floor := is_on_floor()
|
|
|
|
|
|
|
|
|
|
# Jump
|
|
|
|
|
func handle_jump(on_floor: bool) -> void:
|
|
|
|
|
if on_floor and Input.is_action_just_pressed("jump"):
|
|
|
|
|
if enough_stamina_available(jump_cost):
|
|
|
|
|
use_stamina(jump_cost)
|
|
|
|
|
@ -79,36 +117,16 @@ func _input(event: InputEvent) -> void:
|
|
|
|
|
state = States.jumping
|
|
|
|
|
anim_tree.set("parameters/conditions/grounded", false)
|
|
|
|
|
|
|
|
|
|
# We just hit the floor after being in the air
|
|
|
|
|
|
|
|
|
|
func update_ground_state(on_floor: bool) -> void:
|
|
|
|
|
# Gerade gelandet
|
|
|
|
|
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
|
|
|
|
|
# In der Luft ohne aktiven Sprung
|
|
|
|
|
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
|
|
|
|
|
|