Replace game audio with Pixabay tracks
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1270,6 +1270,10 @@ export class BattleScene extends Phaser.Scene {
|
||||
await this.animateCombatGauge(defenderStatus.hpFill, result.previousDefenderHp / result.defender.maxHp, result.defender.hp / result.defender.maxHp, 420);
|
||||
defenderStatus.hpText.setText(`${result.defender.hp} / ${result.defender.maxHp}`);
|
||||
|
||||
if (result.characterGrowth.amount > 0) {
|
||||
soundDirector.playEffect('exp-gain', { volume: result.characterGrowth.leveled ? 0.44 : 0.28, stopAfterMs: 1000 });
|
||||
}
|
||||
|
||||
await this.animateCombatGauge(
|
||||
attackerStatus.expFill,
|
||||
result.characterGrowth.previousExp / result.characterGrowth.next,
|
||||
@@ -1400,6 +1404,7 @@ export class BattleScene extends Phaser.Scene {
|
||||
) {
|
||||
const direction = result.attacker.faction === 'ally' ? 1 : -1;
|
||||
if (result.action === 'attack') {
|
||||
soundDirector.playEffect('sword-slash', { volume: 0.52, stopAfterMs: 700 });
|
||||
this.tweens.add({
|
||||
targets: attackerSprite,
|
||||
x: attackerX + direction * 84,
|
||||
@@ -1418,6 +1423,11 @@ export class BattleScene extends Phaser.Scene {
|
||||
return;
|
||||
}
|
||||
|
||||
soundDirector.playEffect(result.action === 'item' ? 'cart-roll' : 'strategy-cast', {
|
||||
volume: result.action === 'item' ? 0.34 : 0.44,
|
||||
stopAfterMs: result.action === 'item' ? 720 : 950
|
||||
});
|
||||
|
||||
const projectile =
|
||||
result.action === 'item'
|
||||
? this.createCombatCart(attackerX + direction * 78, groundY - 10, depth)
|
||||
@@ -1462,6 +1472,8 @@ export class BattleScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
private showCombatImpact(result: CombatResult, x: number, y: number, depth: number) {
|
||||
soundDirector.playEffect('combat-impact', { volume: result.action === 'strategy' ? 0.3 : 0.48, stopAfterMs: 650 });
|
||||
|
||||
const impact = this.trackCombatObject(this.add.star(x, y, 8, 12, 42, result.action === 'strategy' ? 0x6cc5ff : 0xffdf7b, 0.92));
|
||||
impact.setDepth(depth);
|
||||
this.tweens.add({
|
||||
|
||||
Reference in New Issue
Block a user