Replace game audio with Pixabay tracks

This commit is contained in:
2026-06-22 12:22:09 +09:00
parent 381b2cf14c
commit 89f2251d0b
21 changed files with 112 additions and 7 deletions

View File

@@ -1,21 +1,33 @@
type AudioTrackMap = Record<string, string>;
type PlayEffectOptions = {
volume?: number;
rate?: number;
stopAfterMs?: number;
};
class SoundDirector {
private context?: AudioContext;
private master?: GainNode;
private started = false;
private muted = false;
private musicTracks: AudioTrackMap = {};
private effectTracks: AudioTrackMap = {};
private music?: HTMLAudioElement;
private currentMusicKey?: string;
private pendingMusicKey?: string;
private musicFadeTimer?: number;
private readonly musicVolume = 0.14;
private readonly musicVolume = 0.22;
private readonly effectVolume = 0.42;
registerMusicTracks(tracks: AudioTrackMap) {
this.musicTracks = tracks;
}
registerEffectTracks(tracks: AudioTrackMap) {
this.effectTracks = tracks;
}
start() {
if (this.started) {
this.resume();
@@ -70,10 +82,48 @@ class SoundDirector {
}
playSelect() {
if (this.playEffect('ui-select', { volume: 0.24, stopAfterMs: 420 })) {
return;
}
this.playTone(300, 0.07, 0.04, 'sine');
window.setTimeout(() => this.playTone(450, 0.08, 0.028, 'sine'), 70);
}
playEffect(key: string, options: PlayEffectOptions = {}) {
if (!this.started || this.muted) {
return false;
}
const src = this.effectTracks[key];
if (!src) {
return false;
}
const effect = new Audio(src);
effect.preload = 'auto';
effect.volume = options.volume ?? this.effectVolume;
effect.playbackRate = options.rate ?? 1;
effect.muted = this.muted;
effect.addEventListener(
'ended',
() => {
effect.src = '';
},
{ once: true }
);
if (options.stopAfterMs) {
window.setTimeout(() => {
effect.pause();
effect.src = '';
}, options.stopAfterMs);
}
void effect.play().catch(() => undefined);
return true;
}
playMusic(key?: string) {
if (!key) {
return;

View File

@@ -1,8 +1,14 @@
import battlePrepUrl from '../../assets/audio/bgm/battle-prep.wav';
import militiaThemeUrl from '../../assets/audio/bgm/militia-theme.wav';
import oathThemeUrl from '../../assets/audio/bgm/oath-theme.wav';
import storyDarkUrl from '../../assets/audio/bgm/story-dark.wav';
import titleThemeUrl from '../../assets/audio/bgm/title-theme.wav';
import battlePrepUrl from '../../assets/audio/bgm/battle-prep.mp3';
import militiaThemeUrl from '../../assets/audio/bgm/militia-theme.mp3';
import oathThemeUrl from '../../assets/audio/bgm/oath-theme.mp3';
import storyDarkUrl from '../../assets/audio/bgm/story-dark.mp3';
import titleThemeUrl from '../../assets/audio/bgm/title-theme.mp3';
import cartRollUrl from '../../assets/audio/sfx/cart-roll.mp3';
import combatImpactUrl from '../../assets/audio/sfx/combat-impact.mp3';
import expGainUrl from '../../assets/audio/sfx/exp-gain.mp3';
import strategyCastUrl from '../../assets/audio/sfx/strategy-cast.mp3';
import swordSlashUrl from '../../assets/audio/sfx/sword-slash.mp3';
import uiSelectUrl from '../../assets/audio/sfx/ui-select.mp3';
export const musicTracks = {
'title-theme': titleThemeUrl,
@@ -12,4 +18,14 @@ export const musicTracks = {
'battle-prep': battlePrepUrl
} as const;
export const effectTracks = {
'ui-select': uiSelectUrl,
'sword-slash': swordSlashUrl,
'combat-impact': combatImpactUrl,
'strategy-cast': strategyCastUrl,
'cart-roll': cartRollUrl,
'exp-gain': expGainUrl
} as const;
export type MusicTrackKey = keyof typeof musicTracks;
export type EffectTrackKey = keyof typeof effectTracks;