feat: add narrative page turn audio cue

This commit is contained in:
2026-07-22 01:21:36 +09:00
parent 3a41f8b671
commit fa26992b56
6 changed files with 91 additions and 7 deletions

Binary file not shown.

View File

@@ -57,7 +57,7 @@ export type MusicDuckOptions = {
releaseMs?: number;
};
type SemanticCueGroup = 'turn' | 'operation' | 'objective';
type SemanticCueGroup = 'turn' | 'operation' | 'objective' | 'narrative';
type MusicDuckState = {
multiplier: number;
@@ -102,7 +102,8 @@ export class SoundDirector {
private readonly semanticCueCooldownMs: Record<SemanticCueGroup, number> = {
turn: 900,
operation: 650,
objective: 1200
objective: 1200,
narrative: 220
};
private readonly semanticCuePlayedAt = new Map<SemanticCueGroup, number>();
private lastPlayedSemanticCue?: { group: SemanticCueGroup; key: string; at: number };
@@ -434,6 +435,13 @@ export class SoundDirector {
});
}
playStoryAdvanceCue() {
return this.playSemanticCue('narrative', 'story-page-turn', {
volume: 0.15,
stopAfterMs: 1100
});
}
playStrategyPulse() {
this.playEffect('strategy-cast', { volume: 0.44, rate: 0.96, stopAfterMs: 960 });
this.playTone(460, 0.08, 0.012, 'sine');
@@ -500,7 +508,7 @@ export class SoundDirector {
private playSemanticCue(
group: SemanticCueGroup,
key: string,
options: PlayEffectOptions & { duck: MusicDuckOptions }
options: PlayEffectOptions & { duck?: MusicDuckOptions }
) {
if (!this.started || this.muted || !this.effectTracks[key]) {
return false;
@@ -519,7 +527,9 @@ export class SoundDirector {
return false;
}
this.duckMusic(options.duck);
if (options.duck) {
this.duckMusic(options.duck);
}
const played = this.playEffect(key, options);
if (played) {
this.semanticCuePlayedAt.set(group, now);

View File

@@ -29,6 +29,7 @@ import objectiveSuccessUrl from '../../assets/audio/sfx/objective-success.mp3';
import operationAlertUrl from '../../assets/audio/sfx/operation-alert.mp3';
import shieldBlockUrl from '../../assets/audio/sfx/shield-block.mp3';
import strategyCastUrl from '../../assets/audio/sfx/strategy-cast.mp3';
import storyPageTurnUrl from '../../assets/audio/sfx/story-page-turn.mp3';
import swordSlashUrl from '../../assets/audio/sfx/sword-slash.mp3';
import swordSwingVariantUrl from '../../assets/audio/sfx/sword-swing-variant.mp3';
import uiSelectUrl from '../../assets/audio/sfx/ui-select.mp3';
@@ -80,6 +81,7 @@ export const effectTracks = {
'critical-impact': criticalImpactUrl,
'critical-boom': criticalBoomUrl,
'strategy-cast': strategyCastUrl,
'story-page-turn': storyPageTurnUrl,
'cart-roll': cartRollUrl,
'exp-gain': expGainUrl,
'level-up': levelUpUrl,