feat: add double-barrel shotgun weapon, player movement state machine, and procedural sound assets
This commit is contained in:
@@ -10,6 +10,19 @@ var head_pivot: Node3D = null # FPSCameraRig node
|
||||
var camera: Camera3D = null
|
||||
var _damage_layer: CanvasLayer = null
|
||||
|
||||
# Audio
|
||||
var footstep_player: AudioStreamPlayer
|
||||
var dash_player: AudioStreamPlayer
|
||||
var hit_player: AudioStreamPlayer
|
||||
var slide_player: AudioStreamPlayer
|
||||
var wallrun_player: AudioStreamPlayer
|
||||
var wind_player: AudioStreamPlayer
|
||||
var jump_player: AudioStreamPlayer
|
||||
var double_jump_player: AudioStreamPlayer
|
||||
|
||||
# UI
|
||||
var hit_marker: Control
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var sm := _ensure_machine()
|
||||
@@ -25,10 +38,72 @@ func _ready() -> void:
|
||||
|
||||
_damage_layer = CanvasLayer.new()
|
||||
add_child(_damage_layer)
|
||||
|
||||
_setup_audio()
|
||||
_setup_hit_marker()
|
||||
|
||||
set_process(true)
|
||||
set_physics_process(true)
|
||||
|
||||
func _setup_audio() -> void:
|
||||
footstep_player = AudioStreamPlayer.new()
|
||||
footstep_player.stream = load("res://assets/sounds/footstep.wav")
|
||||
add_child(footstep_player)
|
||||
|
||||
jump_player = AudioStreamPlayer.new()
|
||||
jump_player.stream = load("res://assets/sounds/jump.wav")
|
||||
add_child(jump_player)
|
||||
|
||||
double_jump_player = AudioStreamPlayer.new()
|
||||
double_jump_player.stream = load("res://assets/sounds/double_jump.wav")
|
||||
add_child(double_jump_player)
|
||||
|
||||
dash_player = AudioStreamPlayer.new()
|
||||
dash_player.stream = load("res://assets/sounds/dash.wav")
|
||||
dash_player.volume_db = -5.0
|
||||
add_child(dash_player)
|
||||
|
||||
hit_player = AudioStreamPlayer.new()
|
||||
hit_player.stream = load("res://assets/sounds/hit_confirm.wav")
|
||||
add_child(hit_player)
|
||||
|
||||
slide_player = AudioStreamPlayer.new()
|
||||
slide_player.stream = load("res://assets/sounds/slide.wav")
|
||||
slide_player.volume_db = -10.0
|
||||
add_child(slide_player)
|
||||
|
||||
wallrun_player = AudioStreamPlayer.new()
|
||||
wallrun_player.stream = load("res://assets/sounds/wallrun.wav")
|
||||
wallrun_player.volume_db = -10.0
|
||||
add_child(wallrun_player)
|
||||
|
||||
wind_player = AudioStreamPlayer.new()
|
||||
wind_player.stream = load("res://assets/sounds/wind.wav")
|
||||
wind_player.volume_db = -80.0 # Start silent
|
||||
add_child(wind_player)
|
||||
wind_player.play()
|
||||
|
||||
func _setup_hit_marker() -> void:
|
||||
hit_marker = Control.new()
|
||||
hit_marker.set_anchors_preset(Control.PRESET_CENTER)
|
||||
hit_marker.modulate.a = 0.0 # Hidden by default
|
||||
_damage_layer.add_child(hit_marker)
|
||||
|
||||
# Draw an X perfectly centered
|
||||
var length = 12
|
||||
var thickness = 2
|
||||
for angle in [PI/4, 3*PI/4, 5*PI/4, 7*PI/4]:
|
||||
var rect = ColorRect.new()
|
||||
rect.color = Color.WHITE
|
||||
rect.size = Vector2(length, thickness)
|
||||
rect.pivot_offset = rect.size / 2.0
|
||||
# Center the rect itself at (0,0) before offset
|
||||
var center_pos = -rect.size / 2.0
|
||||
# Move it outward along the angle so it doesn't cover the exact center dot
|
||||
rect.position = center_pos + Vector2(cos(angle), sin(angle)) * (length / 2.0)
|
||||
rect.rotation = angle
|
||||
hit_marker.add_child(rect)
|
||||
|
||||
func spawn_damage_number(amount: float, hit_pos: Vector3) -> void:
|
||||
if not camera or not _damage_layer: return
|
||||
|
||||
@@ -45,7 +120,12 @@ func spawn_damage_number(amount: float, hit_pos: Vector3) -> void:
|
||||
label.camera = camera
|
||||
|
||||
_damage_layer.add_child(label)
|
||||
|
||||
|
||||
# Play sound and flash hit marker
|
||||
hit_player.play()
|
||||
hit_marker.modulate.a = 1.0
|
||||
var tween = create_tween()
|
||||
tween.tween_property(hit_marker, "modulate:a", 0.0, 0.4)
|
||||
|
||||
func _ensure_machine() -> MovementStateMachine:
|
||||
if is_instance_valid(_machine):
|
||||
@@ -58,8 +138,15 @@ func _ensure_machine() -> MovementStateMachine:
|
||||
_machine = null
|
||||
return null
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
var speed = velocity.length()
|
||||
var wind_factor = clampf((speed - 10.0) / 25.0, 0.0, 1.0)
|
||||
# Decibel scale is non-linear, so lerping from -80 means it stays inaudible for a long time.
|
||||
# -40 db is practically silent for a background loop, -15 db is our max quiet wind.
|
||||
wind_player.volume_db = lerpf(-40.0, -15.0, wind_factor)
|
||||
if not wind_player.playing and wind_factor > 0.0:
|
||||
wind_player.play()
|
||||
|
||||
var sm := _ensure_machine()
|
||||
if not sm:
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user