Files
cards/scripts/ui/sfx.gd
Team3 536a523f50 Dinger: Kartenspiel in Godot 4.7
Elemente, Kombos, Fallen, KI mit Vorausschau, Kampagne, Hotseat und Netzwerk,
Werkstatt, Erfolge, Tagesaufgaben, Tests und Exporte.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPgKvy5W9WRNFHjkm5QsHx
2026-09-16 13:22:07 +02:00

108 lines
3.5 KiB
GDScript

class_name Sfx
extends Node
## Kurze, zur Laufzeit erzeugte Töne (keine Audiodateien nötig).
static var inst: Sfx
var streams := {}
var players: Array[AudioStreamPlayer] = []
var volume := 0.8
var music_player: AudioStreamPlayer
var music_volume := 0.5
func _ready() -> void:
inst = self
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["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()
music_player.stream = _music()
add_child(music_player)
set_music_volume(music_volume)
## 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:
music_player.stop()
else:
music_player.volume_db = linear_to_db(music_volume * 0.6)
if not music_player.playing:
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 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