feat: implement movement state machine architecture and add various sound assets

This commit is contained in:
DottsGit
2026-06-07 16:13:01 -04:00
parent 064bc90f53
commit 22ea918e6d
30 changed files with 372 additions and 13 deletions
+124
View File
@@ -0,0 +1,124 @@
extends Node
class_name StateWallClimb
var machine: MovementStateMachine
var params: MovementParams:
get: return machine.params
var elapsed: float = 0.0
func enter(_data: Dictionary = {}) -> void:
elapsed = 0.0
machine.register_chain_mechanic("wall_climb")
machine.on_ground = false
if machine.player.wallrun_player and not machine.player.wallrun_player.playing:
machine.player.wallrun_player.play()
# Give an initial upward boost
var player := machine.player
player.velocity.y = params.wall_climb_speed
var hvel := Vector3(player.velocity.x, 0.0, player.velocity.z)
player.velocity.x = hvel.x * 0.5
player.velocity.z = hvel.z * 0.5
func exit() -> void:
if machine.player.wallrun_player:
machine.player.wallrun_player.stop()
func update(delta: float) -> void:
elapsed += delta
var player := machine.player
if player.wallrun_player and not player.wallrun_player.playing:
player.wallrun_player.play()
# ── Time limit ────────────────────────────────────────────────────────
if elapsed > params.wall_climb_duration:
_detach()
return
# ── Look/Move away to transition to wall run ──────────────────────────────
var look_dir := -player.global_transform.basis.z
var wish_dir := machine.wish_dir_world
var looking_towards := look_dir.dot(-machine.wall_normal) > 0.0
var moving_sideways := false
if wish_dir.length_squared() > 0.01:
moving_sideways = wish_dir.dot(-machine.wall_normal) <= cos(deg_to_rad(params.wall_climb_max_angle))
if not looking_towards or moving_sideways:
# We are looking away or moving sideways, transition to wall run
# The wall run state will figure out tangent and side
var wall_n = machine.detect_wall_horizontal()
if wall_n != Vector3.ZERO:
machine.switch_to("wall_run")
return
else:
_detach()
return
# ── Ledge Vault Check ─────────────────────────────────────────────────
var fwd_wall = machine.detect_wall_forward()
if not fwd_wall.hit:
# The forward lower ray missed, we fell off the wall completely
_detach()
return
if fwd_wall.is_short:
# The upper ray missed, meaning we reached the top of the wall!
_vault()
return
# ── Movement ──────────────────────────────────────────────────────────
# Slow down over time
var speed_factor = maxf(0.0, 1.0 - (elapsed / params.wall_climb_duration))
player.velocity.y = params.wall_climb_speed * speed_factor
# Push slightly into the wall to maintain contact
player.velocity -= machine.wall_normal * 2.0
player.move_and_slide()
# ── Hit floor during wall climb (should be rare) ──────────────────────
if player.is_on_floor():
machine.on_ground = true
machine.wall_normal = Vector3.ZERO
machine.wall_side = 0.0
machine.current_jump_count = 0
machine.switch_to("ground")
func _detach() -> void:
machine.wall_normal = Vector3.ZERO
machine.wall_side = 0.0
machine.wall_cooldown_timer = 0.3
machine.switch_to("air")
func _vault() -> void:
var player := machine.player
var look_dir := -player.global_transform.basis.z
var h_look := Vector3(look_dir.x, 0.0, look_dir.z)
if h_look.length_squared() > 0.01:
h_look = h_look.normalized()
# Impulse
player.velocity = h_look * params.wall_climb_vault_forward
player.velocity.y = params.wall_climb_vault_up
if player.vault_player:
player.vault_player.play()
# Quick camera animation (tilt up and forward bob)
var camera = player.camera
if camera:
var tween = player.create_tween()
tween.tween_property(camera, "rotation_degrees:x", camera.rotation_degrees.x + 10.0, 0.15).set_trans(Tween.TRANS_SINE)
tween.parallel().tween_property(camera, "v_offset", -0.2, 0.15).set_trans(Tween.TRANS_SINE)
tween.chain().tween_property(camera, "rotation_degrees:x", camera.rotation_degrees.x, 0.2).set_trans(Tween.TRANS_SINE)
tween.parallel().tween_property(camera, "v_offset", 0.0, 0.2).set_trans(Tween.TRANS_SINE)
machine.wall_normal = Vector3.ZERO
machine.wall_side = 0.0
machine.wall_cooldown_timer = 0.3
machine.switch_to("air")