Files
cards/scripts/ui/sfx.gd
team3 c245c7af87
Some checks failed
Tests / headless (push) Has been cancelled
Tests / fenster-schnell (push) Has been cancelled
Tests / fenster-voll (push) Has been cancelled
Tests / balance (push) Has been cancelled
update
2026-10-08 14:28:52 +02:00

124 lines
4.2 KiB
GDScript

class_name Sfx
extends Node
## Kurze, zur Laufzeit erzeugte Töne (keine Audiodateien nötig).
var streams := {}
var players: Array[AudioStreamPlayer] = []
var volume := 0.0 # Ton ist standardmäßig aus
var muted := false # Tests: nie etwas abspielen, egal was die Regler sagen
var music_player: AudioStreamPlayer
var music_volume := 0.0
var music_task := -1 # die Musik wird im Hintergrund berechnet (spart ~150 ms beim Start)
var music_box := {}
func _ready() -> void:
streams["click"] = _tone(880, 0.05, "sine")
streams["play"] = _tone(440, 0.14, "sine", 660)
streams["attack"] = _tone(220, 0.16, "square", 90)
streams["damage"] = _tone(140, 0.12, "square")
streams["heal"] = _tone(523, 0.22, "sine", 784)
streams["combo"] = _tone(660, 0.2, "sine", 1100)
streams["buy"] = _tone(1200, 0.08, "sine", 1700)
streams["turn"] = _tone(520, 0.3, "sine", 1040)
streams["win"] = _tone(400, 0.6, "sine", 1200)
streams["lose"] = _tone(320, 0.7, "square", 90)
for i in 4:
var p := AudioStreamPlayer.new()
add_child(p)
players.append(p)
music_player = AudioStreamPlayer.new()
add_child(music_player)
var box := music_box
music_task = WorkerThreadPool.add_task(func(): box["wav"] = _music())
func _process(_delta: float) -> void:
if music_task >= 0 and WorkerThreadPool.is_task_completed(music_task):
WorkerThreadPool.wait_for_task_completion(music_task)
music_task = -1
music_player.stream = music_box.wav
set_music_volume(music_volume)
func _exit_tree() -> void:
if music_task >= 0:
WorkerThreadPool.wait_for_task_completion(music_task)
music_task = -1
## Leise Hintergrundmusik: Arpeggio über vier Akkorde, als Schleife erzeugt.
func _music() -> AudioStreamWAV:
var rate := 22050
var chords := [[220.0, 261.63, 329.63], [174.61, 220.0, 261.63], [130.81, 164.81, 196.0], [196.0, 246.94, 293.66]]
var note_len := 0.25
var pattern := [0, 1, 2, 1, 0, 2, 1, 2]
var total := chords.size() * pattern.size() * note_len
var n := int(total * rate)
var data := PackedByteArray()
data.resize(n * 2)
for i in n:
var t := float(i) / rate
var step := int(t / note_len)
var chord: Array = chords[(step / pattern.size()) % chords.size()]
var f: float = chord[pattern[step % pattern.size()]]
var lt := t - step * note_len
var env := minf(1.0, lt * 30.0) * maxf(0.0, 1.0 - lt / note_len)
var v := sin(TAU * f * t) * 0.6 + sin(TAU * f * 2.0 * t) * 0.15 + sin(TAU * chord[0] * 0.5 * t) * 0.25
data.encode_s16(i * 2, int(clampf(v * env * 0.25, -1.0, 1.0) * 32767))
var wav := AudioStreamWAV.new()
wav.format = AudioStreamWAV.FORMAT_16_BITS
wav.mix_rate = rate
wav.stereo = false
wav.data = data
wav.loop_mode = AudioStreamWAV.LOOP_FORWARD
wav.loop_begin = 0
wav.loop_end = n
return wav
func set_music_volume(v: float) -> void:
music_volume = clampf(v, 0.0, 1.0)
if music_volume <= 0.0 or muted:
music_player.stop()
else:
music_player.volume_db = linear_to_db(music_volume * 0.6)
if not music_player.playing and music_player.stream != null:
music_player.play()
func set_volume(v: float) -> void:
volume = clampf(v, 0.0, 1.0)
func play(kind: String) -> void:
if volume <= 0.0 or muted or not streams.has(kind):
return
for p in players:
if not p.playing:
p.stream = streams[kind]
p.volume_db = linear_to_db(volume)
p.play()
return
func _tone(freq: float, dur: float, shape: String, freq_end: float = -1.0) -> AudioStreamWAV:
var rate := 22050
var n := int(dur * rate)
var data := PackedByteArray()
data.resize(n * 2)
for i in n:
var t := float(i) / rate
var f := freq if freq_end < 0 else lerpf(freq, freq_end, t / dur)
var env := 1.0 - t / dur
var v := sin(TAU * f * t)
if shape == "square":
v = 1.0 if v >= 0 else -1.0
data.encode_s16(i * 2, int(clampf(v * env * 0.4, -1.0, 1.0) * 32767))
var wav := AudioStreamWAV.new()
wav.format = AudioStreamWAV.FORMAT_16_BITS
wav.mix_rate = rate
wav.stereo = false
wav.data = data
return wav