Files
pirate-dice/scripts/klang.gd
2026-09-16 12:09:47 +02:00

86 lines
2.4 KiB
GDScript

extends Node
## Klänge ohne Dateien. Die kurzen Wellen werden beim Start berechnet - so wie
## Würfel und Münzen gemalt statt geladen werden. Auf dem Spielserver ohne
## Tongerät spielt das ins Leere, stört aber nicht.
const RATE := 22050
var _wuerfel: AudioStreamWAV
var _muenze: AudioStreamWAV
var _becher: AudioStreamWAV
var _chime: AudioStreamWAV
var _rng := RandomNumberGenerator.new()
func _ready() -> void:
_rng.randomize()
# Klack: Rauschen, das sofort wieder weg ist.
_wuerfel = _wav(0.07, func(t: float) -> float:
return _rausch() * exp(-t * 60.0))
# Klirren: drei unharmonische Töne, die langsam ausklingen.
_muenze = _wav(0.35, func(t: float) -> float:
return (sin(TAU * 2600.0 * t) + 0.5 * sin(TAU * 4100.0 * t)
+ 0.3 * sin(TAU * 6300.0 * t)) / 1.8 * exp(-t * 9.0))
# Dumpfer Schlag: tiefer Ton plus kurzes Rauschen.
_becher = _wav(0.14, func(t: float) -> float:
return sin(TAU * 110.0 * t) * exp(-t * 22.0) + _rausch() * 0.3 * exp(-t * 80.0))
# Zwei Töne aufwärts - für den Gewinn.
_chime = _wav(0.55, func(t: float) -> float:
var a := sin(TAU * 880.0 * t) * exp(-t * 4.0)
var b := 0.0
if t > 0.14:
b = sin(TAU * 1320.0 * (t - 0.14)) * exp(-(t - 0.14) * 4.0)
return (a + b) * 0.5)
func _rausch() -> float:
return _rng.randf_range(-1.0, 1.0)
func _wav(sek: float, f: Callable) -> AudioStreamWAV:
var n := int(RATE * sek)
var data := PackedByteArray()
data.resize(n * 2)
for i in n:
var v: float = clampf(f.call(float(i) / RATE), -1.0, 1.0)
data.encode_s16(i * 2, int(v * 32000.0))
var w := AudioStreamWAV.new()
w.format = AudioStreamWAV.FORMAT_16_BITS
w.mix_rate = RATE
w.data = data
return w
func _spiel(w: AudioStreamWAV, db: float, pitch := 1.0) -> void:
var p := AudioStreamPlayer.new()
p.stream = w
p.volume_db = db
p.pitch_scale = pitch
add_child(p)
p.finished.connect(p.queue_free)
p.play()
## Mehrere Würfel fallen: ein paar Klacker kurz hintereinander, verschieden hoch.
func wuerfel(anzahl := 5) -> void:
for i in mini(anzahl, 8):
await get_tree().create_timer(_rng.randf_range(0.0, 0.35)).timeout
_spiel(_wuerfel, -8.0, _rng.randf_range(0.8, 1.3))
## Ein kurzer heller Klick - je gezähltem Würfel einer.
func tick() -> void:
_spiel(_wuerfel, -14.0, 2.2)
func muenze() -> void:
_spiel(_muenze, -6.0, _rng.randf_range(0.95, 1.05))
func becher() -> void:
_spiel(_becher, -3.0)
func chime() -> void:
_spiel(_chime, -8.0)