import {
Container,
MenuList,
Panel,
PixelText,
type Scene,
type SettingsData
} from '@rpg/engine';
import type { Game } from '../Game';
/**
* Настройки: громкости шин аудио. Панель поверх вызывающей сцены (push/pop),
* изменения сразу применяются через settings.onChange -> AudioManager.
*/
export class SettingsScene implements Scene {
private view = new Container();
private menu: MenuList;
/** Куда вернуться (закрыть панель). */
constructor(
private game: Game,
private onBack: () => void
) {
const panel = new Panel({ width: 220, height: 130 });
panel.position.set((480 - 220) / 2, (270 - 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: 14, gap: 4, size: 9 });
this.menu.position.set(20, 36);
panel.addChild(this.menu);
this.view.addChild(panel);
this.game.renderer.uiRoot.addChild(this.view);
this.rebuild();
}
enter(): void {}
exit(): void {
this.view.destroy({ children: true });
}
render(): void {}
update(_dt: number): void {
if (this.game.scenes.transitioning) return;
const input = this.game.engine.input;
if (input.isActionJustPressed('menu')) {
this.back();
return;
}
if (!this.menu) return;
if (input.isActionJustPressed('up')) this.menu.moveCursor(-1);
if (input.isActionJustPressed('down')) this.menu.moveCursor(1);
// влево/вправо меняют громкость выбранной строки, Enter — на 10% вверх
const step = input.isActionJustPressed('advance') ? 0.1 : 0;
const dir = input.isActionJustPressed('right') ? 0.1 : input.isActionJustPressed('left') ? -0.1 : step;
if (dir !== 0) this.adjust(this.menu.index, dir);
}
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.music), 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', 'music', '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) void this.game.audio.play('sfx/ui_click');
this.rebuild();
}
private back(): void {
void this.game.audio.play('sfx/ui_click');
this.onBack();
}
}
/** Тип громкости в SettingsData (для adjust). */
export type VolumeKey = keyof Pick<SettingsData, 'master' | 'music' | 'sfx'>;