43 lines
1.4 KiB
GDScript
43 lines
1.4 KiB
GDScript
extends Node
|
|
## Small synthesized arcade effects; no external audio assets required.
|
|
var voices: Array[AudioStreamPlayer] = []
|
|
var sounds: Dictionary = {}
|
|
var voice_index := 0
|
|
func _ready() -> void:
|
|
for i in range(6):
|
|
var voice := AudioStreamPlayer.new()
|
|
voice.volume_db = -17.0
|
|
add_child(voice)
|
|
voices.append(voice)
|
|
sounds["fire"] = tone(1300.0, 220.0, 0.09)
|
|
sounds["hit"] = tone(170.0, 40.0, 0.18)
|
|
sounds["zap"] = tone(1700.0, 70.0, 0.55)
|
|
sounds["death"] = tone(440.0, 35.0, 0.7)
|
|
sounds["level"] = tone(220.0, 880.0, 0.4)
|
|
func tone(start: float, finish: float, duration: float) -> AudioStreamWAV:
|
|
var samples := PackedByteArray()
|
|
var count := int(22050 * duration)
|
|
samples.resize(count * 2)
|
|
var phase := 0.0
|
|
for i in range(count):
|
|
var t := float(i) / count
|
|
phase += lerpf(start, finish, t) * TAU / 22050.0
|
|
var envelope := minf(t * 50.0, 1.0) * pow(1.0 - t, 1.5)
|
|
var value := int((sin(phase) + sin(phase * 2.0) * 0.25) * envelope * 18000)
|
|
samples.encode_s16(i * 2, value)
|
|
var stream := AudioStreamWAV.new()
|
|
stream.format = AudioStreamWAV.FORMAT_16_BITS
|
|
stream.mix_rate = 22050
|
|
stream.data = samples
|
|
return stream
|
|
func play(effect: String) -> void:
|
|
if not sounds.has(effect) or voices.is_empty():
|
|
return
|
|
var voice := voices[voice_index]
|
|
voice_index = (voice_index + 1) % voices.size()
|
|
voice.stream = sounds[effect]
|
|
voice.play()
|
|
func stop() -> void:
|
|
for voice in voices:
|
|
voice.stop()
|