/** * Klangdateien (Kenney, CC0) und Abspieloptionen je Effekt. * * Mehrere Dateien pro Effekt werden zufällig abgewechselt, damit Dauerfeuer nicht * monoton klingt. Fehlt eine Datei oder kann der Browser OGG nicht dekodieren, * springt der Synthesizer in `Synth.js` ein. * @module systems/AudioAssets */ /** Pfad relativ zu `static/assets/`. */ export const AUDIO_PATH = 'kenney/audio/'; /** @type {Readonly>} */ export const SOUND_FILES = Object.freeze({ 'shot-carbine': ['laserSmall_000.ogg', 'laserSmall_001.ogg', 'laserSmall_002.ogg'], 'shot-shotgun': ['laserLarge_000.ogg', 'laserLarge_001.ogg'], 'shot-pistol': ['laserRetro_000.ogg', 'laserRetro_001.ogg'], 'turret-shot': ['laserRetro_002.ogg'], 'enemy-shot': ['laserSmall_003.ogg', 'laserSmall_004.ogg'], 'hit-flesh': ['impactSoft_medium_000.ogg', 'impactSoft_medium_001.ogg', 'impactSoft_medium_002.ogg'], 'hit-metal': ['impactMetal_light_000.ogg', 'impactMetal_light_001.ogg', 'impactMetal_light_002.ogg'], 'death-swarm': ['slime_000.ogg', 'slime_001.ogg'], 'death-legion': ['explosionCrunch_000.ogg', 'explosionCrunch_001.ogg'], 'explosion-small': ['explosionCrunch_002.ogg', 'explosionCrunch_003.ogg'], 'explosion-big': ['lowFrequency_explosion_000.ogg'], 'player-hit': ['impactPunch_heavy_000.ogg', 'impactPunch_heavy_001.ogg'], 'player-death': ['lowFrequency_explosion_001.ogg'], reload: ['impactPlate_light_000.ogg'], 'reload-done': ['click_001.ogg'], switch: ['select_001.ogg'], 'combo-step': ['tick_001.ogg'], 'combo-fail': ['error_001.ogg'], 'orbital-call': ['confirmation_001.ogg'], pickup: ['maximize_001.ogg'], brood: ['slime_001.ogg'], 'ui-click': ['click_001.ogg'], 'ui-confirm': ['confirmation_002.ogg'], 'wave-start': ['jingles_HIT15.ogg'], 'wave-cleared': ['jingles_STEEL07.ogg'], alarm: ['jingles_HIT11.ogg'], 'game-over': ['jingles_PIZZI07.ogg'], // Nur synthetisch (kein passendes kurzes Sample): Ausweichrolle, Mörserpfeifen. dodge: [], mortar: [], }); /** * Lautstärke (0..1), Tonhöhe (1 = original) und Tonhöhenstreuung je Effekt. * Jingles laufen über den Musikkanal, damit „Musik leiser“ auch sie betrifft. * @type {Readonly>} */ export const SOUND_OPTIONS = Object.freeze({ 'shot-carbine': { volume: 0.35, spread: 0.08 }, 'shot-shotgun': { volume: 0.5, rate: 0.8, spread: 0.06 }, 'shot-pistol': { volume: 0.4, spread: 0.06 }, 'turret-shot': { volume: 0.22, rate: 1.4, spread: 0.1 }, 'enemy-shot': { volume: 0.22, rate: 0.7, spread: 0.1 }, 'hit-flesh': { volume: 0.35, spread: 0.15 }, 'hit-metal': { volume: 0.3, spread: 0.15 }, 'death-swarm': { volume: 0.5, spread: 0.15 }, 'death-legion': { volume: 0.4, rate: 1.2, spread: 0.1 }, 'explosion-small': { volume: 0.6, spread: 0.1 }, 'explosion-big': { volume: 1 }, 'player-hit': { volume: 0.6, spread: 0.1 }, 'player-death': { volume: 1, rate: 0.8 }, reload: { volume: 0.45 }, 'reload-done': { volume: 0.4 }, switch: { volume: 0.4 }, 'combo-step': { volume: 0.5 }, 'combo-fail': { volume: 0.5 }, 'orbital-call': { volume: 0.6 }, pickup: { volume: 0.6 }, brood: { volume: 0.5, rate: 0.7 }, 'ui-click': { volume: 0.4 }, 'ui-confirm': { volume: 0.5 }, 'wave-start': { volume: 0.8, channel: 'music' }, 'wave-cleared': { volume: 0.8, channel: 'music' }, alarm: { volume: 0.8, channel: 'music' }, 'game-over': { volume: 0.9, channel: 'music' }, dodge: { volume: 0.35 }, mortar: { volume: 0.3 }, }); /** @returns {string[]} Alle benötigten Dateien ohne Duplikate. */ export function allSoundFiles() { return [...new Set(Object.values(SOUND_FILES).flat())]; }