diff --git a/src/game/scenes/TitleScene.ts b/src/game/scenes/TitleScene.ts index 9512950..905239b 100644 --- a/src/game/scenes/TitleScene.ts +++ b/src/game/scenes/TitleScene.ts @@ -9,6 +9,7 @@ import { startLazyScene } from './lazyScenes'; export class TitleScene extends Phaser.Scene { private focusedButton?: Phaser.GameObjects.Text; private settingsPanel?: Phaser.GameObjects.Container; + private newGameConfirmPanel?: Phaser.GameObjects.Container; private navigating = false; constructor() { @@ -18,6 +19,7 @@ export class TitleScene extends Phaser.Scene { create() { this.focusedButton = undefined; this.settingsPanel = undefined; + this.newGameConfirmPanel = undefined; this.navigating = false; const debugBattleId = this.debugBattleId(); @@ -53,7 +55,7 @@ export class TitleScene extends Phaser.Scene { this.input.once('pointerdown', unlockAudio); this.input.keyboard?.once('keydown', unlockAudio); - this.input.keyboard?.once('keydown-ENTER', () => this.startGame()); + this.input.keyboard?.once('keydown-ENTER', () => this.requestStartGame()); } private shouldOpenDebugSortiePrep() { @@ -210,7 +212,7 @@ export class TitleScene extends Phaser.Scene { this.add.rectangle(menuX, menuY - plateHeight / 2, 186, 2, palette.gold, 0.7); this.add.rectangle(menuX, menuY + plateHeight / 2, 186, 2, palette.gold, 0.36); - this.createMenuButton(menuX, menuY - 70, '새 게임', true, () => this.startGame()); + this.createMenuButton(menuX, menuY - 70, '새 게임', true, () => this.requestStartGame()); this.createMenuButton(menuX, menuY, isEndingComplete ? '엔딩 보기' : '이어하기', canContinue, () => this.continueGame()); this.createMenuButton(menuX, menuY + 70, '설정', true, () => this.openSettingsPanel(menuX, menuY)); @@ -340,6 +342,7 @@ export class TitleScene extends Phaser.Scene { } soundDirector.playSelect(); + this.closeNewGameConfirmPanel(); const panel = this.add.container(x, y + 238); const backdrop = this.add.rectangle(0, 0, 286, 188, 0x0e151d, 0.9); @@ -398,6 +401,76 @@ export class TitleScene extends Phaser.Scene { this.settingsPanel = undefined; } + private requestStartGame() { + if (!hasCampaignSave()) { + this.startGame(); + return; + } + + const { width, height } = this.scale; + const compact = width < 720; + const menuX = compact ? width / 2 : width - 318; + const menuY = height * (compact ? 0.36 : 0.43); + this.openNewGameConfirmPanel(menuX, menuY); + } + + private openNewGameConfirmPanel(x: number, y: number) { + if (this.newGameConfirmPanel) { + this.closeNewGameConfirmPanel(); + return; + } + + soundDirector.playSelect(); + this.closeSettingsPanel(); + + const panel = this.add.container(x, y + 240); + const backdrop = this.add.rectangle(0, 0, 286, 174, 0x0e151d, 0.94); + backdrop.setStrokeStyle(1, palette.gold, 0.58); + + const title = this.add.text(0, -58, '새로 시작', { + fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif', + fontSize: '23px', + color: '#f1e3c2', + fontStyle: '700', + fixedWidth: 220, + align: 'center' + }); + title.setOrigin(0.5); + + const message = this.add.text(0, -20, '현재 저장을 덮고\n처음부터 시작합니다.', { + fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif', + fontSize: '15px', + color: '#bfc8d3', + fixedWidth: 236, + align: 'center', + lineSpacing: 4 + }); + message.setOrigin(0.5); + + const confirm = this.createSettingsButton(0, 30, '새 게임 시작'); + confirm.setColor('#f1e3c2'); + confirm.on('pointerdown', () => { + this.closeNewGameConfirmPanel(); + this.startGame(); + }); + + const cancel = this.createSettingsButton(0, 74, '취소'); + cancel.on('pointerdown', () => { + soundDirector.playSelect(); + this.closeNewGameConfirmPanel(); + }); + + panel.add([backdrop, title, message, confirm, cancel]); + panel.setAlpha(0); + this.newGameConfirmPanel = panel; + this.tweens.add({ targets: panel, alpha: 1, y: y + 230, duration: 160, ease: 'Sine.easeOut' }); + } + + private closeNewGameConfirmPanel() { + this.newGameConfirmPanel?.destroy(); + this.newGameConfirmPanel = undefined; + } + private startGame() { soundDirector.start(); soundDirector.resume();