update
This commit is contained in:
114
scripts/ui/Sfx.gd
Normal file
114
scripts/ui/Sfx.gd
Normal file
@@ -0,0 +1,114 @@
|
||||
class_name Sfx
|
||||
extends Node
|
||||
|
||||
## Primitive Klänge, im Code erzeugt: kurze Töne mit Hüllkurve.
|
||||
## Keine Audiodateien, passend zu den primitiven Meshes.
|
||||
|
||||
const RATE := 22050
|
||||
const HIT_COOLDOWN := 0.06
|
||||
|
||||
var _streams := {}
|
||||
var _players: Array = []
|
||||
var _next := 0
|
||||
var _hit_gate := 0.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
for i in 8:
|
||||
var pl := AudioStreamPlayer.new()
|
||||
pl.volume_db = -8.0
|
||||
add_child(pl)
|
||||
_players.append(pl)
|
||||
_streams["kauf"] = _tone([[660.0, 0.07]], 0.5)
|
||||
_streams["verkauf"] = _tone([[520.0, 0.05], [330.0, 0.07]], 0.45)
|
||||
_streams["wuerfeln"] = _noise(0.04, 0.35)
|
||||
_streams["setzen"] = _tone([[180.0, 0.06]], 0.6, true)
|
||||
_streams["aufwerten"] = _tone([[523.0, 0.08], [659.0, 0.08], [784.0, 0.12]], 0.55)
|
||||
_streams["level"] = _tone([[440.0, 0.08], [880.0, 0.14]], 0.5)
|
||||
_streams["treffer"] = _noise(0.03, 0.22)
|
||||
_streams["krit"] = _tone([[220.0, 0.05]], 0.55, true)
|
||||
_streams["heilung"] = _tone([[988.0, 0.06]], 0.3)
|
||||
_streams["zauber"] = _tone([[880.0, 0.05], [1320.0, 0.09]], 0.45)
|
||||
_streams["sieg"] = _tone([[523.0, 0.1], [659.0, 0.1], [784.0, 0.1], [1046.0, 0.2]], 0.6)
|
||||
_streams["niederlage"] = _tone([[392.0, 0.12], [311.0, 0.12], [261.0, 0.24]], 0.6)
|
||||
_streams["runde"] = _tone([[440.0, 0.06], [440.0, 0.06]], 0.4)
|
||||
_streams["fehler"] = _tone([[200.0, 0.1]], 0.5, true)
|
||||
|
||||
|
||||
## Lautstärke 0..1, 0 schaltet stumm.
|
||||
func set_volume(linear: float) -> void:
|
||||
for pl in _players:
|
||||
pl.volume_db = linear_to_db(maxf(0.0001, linear)) - 8.0
|
||||
pl.stream_paused = false
|
||||
_muted = linear <= 0.001
|
||||
|
||||
|
||||
var _muted := false
|
||||
|
||||
|
||||
func play(name: String) -> void:
|
||||
if _muted:
|
||||
return
|
||||
if not _streams.has(name):
|
||||
return
|
||||
if name == "treffer":
|
||||
var now := Time.get_ticks_msec() / 1000.0
|
||||
if now < _hit_gate:
|
||||
return
|
||||
_hit_gate = now + HIT_COOLDOWN
|
||||
var pl: AudioStreamPlayer = _players[_next]
|
||||
_next = (_next + 1) % _players.size()
|
||||
pl.stream = _streams[name]
|
||||
pl.play()
|
||||
|
||||
|
||||
## Tonfolge [[frequenz, dauer], ...] mit Ein- und Ausblenden.
|
||||
func _tone(notes: Array, gain: float, square: bool = false) -> AudioStreamWAV:
|
||||
var total := 0.0
|
||||
for n in notes:
|
||||
total += n[1]
|
||||
var frames := int(total * RATE)
|
||||
var data := PackedByteArray()
|
||||
data.resize(frames * 2)
|
||||
var idx := 0
|
||||
for n in notes:
|
||||
var freq: float = n[0]
|
||||
var len_frames := int(n[1] * RATE)
|
||||
for i in len_frames:
|
||||
var t := float(i) / RATE
|
||||
var env := minf(1.0, float(i) / (0.005 * RATE)) * minf(1.0, float(len_frames - i) / (0.02 * RATE))
|
||||
var v := sin(TAU * freq * t)
|
||||
if square:
|
||||
v = 1.0 if v >= 0.0 else -1.0
|
||||
_put(data, idx, v * env * gain)
|
||||
idx += 1
|
||||
if idx >= frames:
|
||||
break
|
||||
return _wav(data)
|
||||
|
||||
|
||||
## Kurzes Rauschen für Treffer und Würfeln.
|
||||
func _noise(dur: float, gain: float) -> AudioStreamWAV:
|
||||
var frames := int(dur * RATE)
|
||||
var data := PackedByteArray()
|
||||
data.resize(frames * 2)
|
||||
var rng := RandomNumberGenerator.new()
|
||||
rng.seed = 1234
|
||||
for i in frames:
|
||||
var env := 1.0 - float(i) / float(frames)
|
||||
_put(data, i, rng.randf_range(-1.0, 1.0) * env * env * gain)
|
||||
return _wav(data)
|
||||
|
||||
|
||||
func _put(data: PackedByteArray, index: int, v: float) -> void:
|
||||
var s := int(clampf(v, -1.0, 1.0) * 32767.0)
|
||||
data.encode_s16(index * 2, s)
|
||||
|
||||
|
||||
func _wav(data: PackedByteArray) -> AudioStreamWAV:
|
||||
var w := AudioStreamWAV.new()
|
||||
w.format = AudioStreamWAV.FORMAT_16_BITS
|
||||
w.mix_rate = RATE
|
||||
w.stereo = false
|
||||
w.data = data
|
||||
return w
|
||||
Reference in New Issue
Block a user