edc40f9008
- Touch controls: direct InputEventScreenTouch in shop_ui (bypass relay) - ItemDB: static preload list instead of DirAccess scan (export fix) - All 18 items with EN localisation (name_en, desc_en, category_en) - Ship playstyles: NOVA-1 shield, INFERNO ram, AURORA agile/tank - Quasar: SMBH visual, jet boost, merge, push, BH-eating - Atlas & UI text updated EN+DE Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
76 lines
2.9 KiB
GDScript
76 lines
2.9 KiB
GDScript
extends Node
|
|
|
|
# SoundManager - Autoload singleton for all SFX
|
|
|
|
var _bus_sfx := 0
|
|
|
|
func _ready() -> void:
|
|
_bus_sfx = AudioServer.get_bus_index("Master")
|
|
|
|
func play_sfx(sfx_name: String) -> void:
|
|
match sfx_name:
|
|
"player_shoot": _play_tone(880.0, 0.07, "sine", -18.0, 440.0)
|
|
"enemy_shoot": _play_tone(220.0, 0.09, "saw", -20.0, 110.0)
|
|
"enemy_die": _play_noise(0.2, -16.0); _play_tone(180.0, 0.15, "square", -18.0, 60.0)
|
|
"player_die": _play_noise(0.8, -14.0); _play_tone(120.0, 0.8, "sine", -16.0, 30.0)
|
|
"antimatter_hit": _play_tone(1200.0, 0.3, "saw", -16.0, 300.0); _play_noise(0.2, -18.0)
|
|
"bh_swallow": _play_tone(200.0, 0.22, "sine", -20.0, 40.0)
|
|
"wipe_start": _play_tone(35.0, 2.3, "sine", -22.0, 35.0)
|
|
"wipe_flash": _play_noise(0.4, -16.0); _play_tone(80.0, 0.6, "sine", -18.0, 20.0)
|
|
"wipe_survived": _play_chord_fanfare()
|
|
"smbh_spawn": _play_tone(60.0, 1.0, "sine", -18.0, 20.0); _play_noise(0.5, -16.0)
|
|
"quasar_boost": _play_tone(280.0, 0.45, "sine", -15.0, 1500.0); _play_noise(0.15, -22.0)
|
|
"antimatter_swarm":_play_noise(0.28, -18.0)
|
|
|
|
func _play_tone(freq: float, duration: float, wave: String, vol_db: float, end_freq: float) -> void:
|
|
var gen := AudioStreamGenerator.new()
|
|
gen.mix_rate = 44100.0
|
|
gen.buffer_length = duration
|
|
var player := AudioStreamPlayer.new()
|
|
player.stream = gen
|
|
player.volume_db = vol_db
|
|
player.autoplay = false
|
|
add_child(player)
|
|
player.play()
|
|
var playback: AudioStreamGeneratorPlayback = player.get_stream_playback()
|
|
var frames := int(44100.0 * duration)
|
|
var phase := 0.0
|
|
for i in frames:
|
|
var t := float(i) / float(frames)
|
|
var cur_freq := freq + (end_freq - freq) * t
|
|
phase += cur_freq / 44100.0
|
|
var s := 0.0
|
|
match wave:
|
|
"sine": s = sin(phase * TAU)
|
|
"saw": s = fmod(phase, 1.0) * 2.0 - 1.0
|
|
"square": s = 1.0 if sin(phase * TAU) > 0 else -1.0
|
|
var env := 1.0 - t
|
|
playback.push_frame(Vector2(s * env, s * env))
|
|
var timer := get_tree().create_timer(duration + 0.1)
|
|
timer.timeout.connect(player.queue_free)
|
|
|
|
func _play_noise(duration: float, vol_db: float) -> void:
|
|
var gen := AudioStreamGenerator.new()
|
|
gen.mix_rate = 44100.0
|
|
gen.buffer_length = duration
|
|
var player := AudioStreamPlayer.new()
|
|
player.stream = gen
|
|
player.volume_db = vol_db
|
|
add_child(player)
|
|
player.play()
|
|
var playback: AudioStreamGeneratorPlayback = player.get_stream_playback()
|
|
var frames := int(44100.0 * duration)
|
|
for i in frames:
|
|
var t := float(i) / float(frames)
|
|
var s := randf_range(-1.0, 1.0) * (1.0 - t)
|
|
playback.push_frame(Vector2(s, s))
|
|
var timer := get_tree().create_timer(duration + 0.1)
|
|
timer.timeout.connect(player.queue_free)
|
|
|
|
func _play_chord_fanfare() -> void:
|
|
var freqs: Array[float] = [261.6, 329.6, 392.0]
|
|
for i in freqs.size():
|
|
var delay_timer := get_tree().create_timer(i * 0.06)
|
|
var f: float = freqs[i]
|
|
delay_timer.timeout.connect(func(): _play_tone(f, 0.4, "sine", -16.0, f))
|