import { playSfx } from '../data/sfxSpecs';
import { MenuList, MenuSceneBase, Panel, PixelText, type SettingsData } from '@rpg/engine';
import { Game } from '../Game';
/**
* Настройки: громкости шин аудио. Панель поверх вызывающей сцены (push/pop),
* изменения сразу применяются через settings.onChange -> AudioManager.
* Громкости рисуются текстовыми барами, left/right/Enter — подстройка.
*/
export class SettingsScene extends MenuSceneBase {
constructor(
private game: Game,
private onBack: () => void
) {
super(
{ input: game.engine.input, inputBlocked: () => game.scenes.transitioning },
{ up: 'up', down: 'down', confirm: 'advance', cancel: 'menu', left: 'left', right: 'right' }
);
}
protected build(): void {
const panel = new Panel({ width: 220, height: 130 });
panel.position.set((Game.VIRTUAL_W - 220) / 2, (Game.VIRTUAL_H - 130) / 2);
const title = new PixelText({ text: 'НАСТРОЙКИ', size: 14, color: 0xd8c79a });
title.anchor.set(0.5);
title.position.set(110, 14);
panel.addChild(title);
this.menu = new MenuList({ width: 180, height: 16, gap: 4, size: 10 });
this.menu.position.set(20, 36);
panel.addChild(this.menu);
this.view.addChild(panel);
this.game.renderer.uiRoot.addChild(this.view);
this.rebuild();
}
/** Enter — на 10% вверх. */
protected onConfirm(index: number): void {
this.adjust(index, 0.1);
}
/** Влево/вправо — подстройка громкости выбранной строки. */
protected onAdjust(delta: number, index: number): void {
this.adjust(index, delta * 0.1);
}
protected onCancel(): void {
this.back();
}
private rebuild(): void {
const s = this.game.settings.data;
this.menu!.setItems([
{ label: this.volumeLabel('Общая', s.master), onSelect: () => this.adjust(0, 0.1) },
{ label: this.volumeLabel('Амбиент', s.ambience), onSelect: () => this.adjust(1, 0.1) },
{ label: this.volumeLabel('Звуки', s.sfx), onSelect: () => this.adjust(2, 0.1) },
{ label: 'Назад', onSelect: () => this.back() }
]);
}
private volumeLabel(name: string, v: number): string {
const bars = Math.round(v * 10);
return `${name} ${'▮'.repeat(bars)}${'▯'.repeat(10 - bars)}`;
}
private adjust(index: number, delta: number): void {
if (index < 0 || index > 2) {
this.back();
return;
}
const s = this.game.settings.data;
const key = (['master', 'ambience', 'sfx'] as const)[index];
const value = Math.round(Math.min(1, Math.max(0, s[key] + delta)) * 10) / 10;
this.game.settings.update({ [key]: value });
if (delta > 0) playSfx(this.game.audio, 'sfx/ui_click');
this.rebuild();
}
private back(): void {
playSfx(this.game.audio, 'sfx/ui_click');
this.onBack();
}
}
/** Тип громкости в SettingsData (для adjust). */
export type VolumeKey = keyof Pick<SettingsData, 'master' | 'ambience' | 'sfx'>;