Files
scopone/src/scenes/SettingsScene.ts
2026-04-09 23:00:59 +02:00

193 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Phaser from 'phaser';
import {
AudioPreferences,
SettingsSceneData,
loadAudioPreferences,
saveAudioPreferences,
} from '../game/preferences';
type ToggleDefinition = {
key: keyof AudioPreferences;
label: string;
description: string;
};
type ToggleVisuals = {
background: Phaser.GameObjects.Rectangle;
statusText: Phaser.GameObjects.Text;
};
const TOGGLE_DEFINITIONS: ToggleDefinition[] = [
{
key: 'musicEnabled',
label: 'Musica del tavolo',
description: 'Controlla il tappeto sonoro di sottofondo durante la partita.',
},
{
key: 'effectsEnabled',
label: 'Effetti di gioco',
description: 'Attiva prese, scope e segnali sonori senza toccare la musica.',
},
];
export class SettingsScene extends Phaser.Scene {
private preferences: AudioPreferences = loadAudioPreferences();
private returnSceneKey = 'MenuScene';
private toggleVisuals = new Map<keyof AudioPreferences, ToggleVisuals>();
constructor() {
super({ key: 'SettingsScene' });
}
create(data?: SettingsSceneData): void {
const width = this.scale.width;
const height = this.scale.height;
this.preferences = loadAudioPreferences();
this.returnSceneKey = data?.returnSceneKey ?? 'MenuScene';
this.add.rectangle(0, 0, width, height, 0x123d22).setOrigin(0);
this.add.rectangle(width / 2, height / 2, width - 120, height - 120, 0x0d2216, 0.88)
.setStrokeStyle(2, 0xd9b75f, 0.45);
this.add.text(width / 2, 120, 'Impostazioni audio', {
fontFamily: 'Georgia, serif',
fontSize: '46px',
color: '#ffd700',
stroke: '#000000',
strokeThickness: 4,
resolution: 2,
}).setOrigin(0.5);
this.add.text(width / 2, 176, 'Musica ed effetti sono separati: ogni scelta viene salvata subito e sarà usata nelle prossime partite.', {
fontFamily: 'Georgia, serif',
fontSize: '19px',
color: '#d7ead1',
resolution: 2,
align: 'center',
wordWrap: { width: 760 },
}).setOrigin(0.5);
TOGGLE_DEFINITIONS.forEach((definition, index) => {
this.createToggleRow(definition, width / 2, 286 + index * 132, 760, 96);
});
this.add.text(width / 2, 556, 'Puoi tornare al menu in qualsiasi momento: la difficoltà si sceglie lì, laudio resta salvato qui.', {
fontFamily: 'Georgia, serif',
fontSize: '16px',
color: '#cfe5cd',
resolution: 2,
align: 'center',
wordWrap: { width: 720 },
}).setOrigin(0.5);
this.createButton(width / 2, height - 112, 280, 60, 'Torna al menu', 'Rientra alla schermata iniziale', () => {
this.returnToMenu();
});
}
private createToggleRow(definition: ToggleDefinition, x: number, y: number, width: number, height: number): void {
const row = this.add.rectangle(x, y, width, height, 0x173323, 0.96)
.setStrokeStyle(2, 0xcaa74a, 0.35)
.setInteractive({ useHandCursor: true });
this.add.text(x - width / 2 + 28, y - 16, definition.label, {
fontFamily: 'Georgia, serif',
fontSize: '24px',
color: '#ffffff',
resolution: 2,
}).setOrigin(0, 0.5);
this.add.text(x - width / 2 + 28, y + 14, definition.description, {
fontFamily: 'Georgia, serif',
fontSize: '16px',
color: '#d8ead2',
resolution: 2,
wordWrap: { width: 470 },
}).setOrigin(0, 0.5);
const toggleBackground = this.add.rectangle(x + width / 2 - 106, y, 148, 46, 0x356b39, 1)
.setStrokeStyle(2, 0xf5e1a4, 0.45);
const statusText = this.add.text(x + width / 2 - 106, y, '', {
fontFamily: 'Georgia, serif',
fontSize: '20px',
color: '#ffffff',
resolution: 2,
}).setOrigin(0.5);
this.toggleVisuals.set(definition.key, {
background: toggleBackground,
statusText,
});
row.on('pointerdown', () => {
this.togglePreference(definition.key);
});
row.on('pointerover', () => row.setFillStyle(0x1d402c, 1));
row.on('pointerout', () => row.setFillStyle(0x173323, 0.96));
this.refreshToggle(definition.key);
}
private createButton(
x: number,
y: number,
width: number,
height: number,
label: string,
subtitle: string,
onClick: () => void,
): void {
const button = this.add.rectangle(x, y, width, height, 0x1f6f78, 1)
.setStrokeStyle(2, 0xf5e1a4, 0.4)
.setInteractive({ useHandCursor: true });
this.add.text(x, y - 10, label, {
fontFamily: 'Georgia, serif',
fontSize: '21px',
color: '#ffffff',
stroke: '#000000',
strokeThickness: 2,
resolution: 2,
}).setOrigin(0.5);
this.add.text(x, y + 14, subtitle, {
fontFamily: 'Georgia, serif',
fontSize: '13px',
color: '#f7f1d5',
resolution: 2,
align: 'center',
}).setOrigin(0.5);
button.on('pointerover', () => button.setFillStyle(0x2f8f99));
button.on('pointerout', () => button.setFillStyle(0x1f6f78));
button.on('pointerdown', onClick);
}
private togglePreference(key: keyof AudioPreferences): void {
this.preferences = saveAudioPreferences({
...this.preferences,
[key]: !this.preferences[key],
});
this.refreshToggle(key);
}
private refreshToggle(key: keyof AudioPreferences): void {
const visuals = this.toggleVisuals.get(key);
if (!visuals) {
return;
}
const enabled = this.preferences[key];
visuals.background.setFillStyle(enabled ? 0x356b39 : 0x7a2f2f);
visuals.statusText.setText(enabled ? 'Attivo' : 'Disattivato');
}
private returnToMenu(): void {
this.cameras.main.fadeOut(250, 0, 30, 0);
this.cameras.main.once('camerafadeoutcomplete', () => {
this.scene.start(this.returnSceneKey);
});
}
}