Finalize title screen name
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# Heros Web Roadmap
|
# 삼국지: 세 형제의 맹세 Roadmap
|
||||||
|
|
||||||
## Initial Goal
|
## Initial Goal
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Heros Web</title>
|
<title>삼국지: 세 형제의 맹세</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="game"></div>
|
<div id="game"></div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class SoundDirector {
|
|||||||
private master?: GainNode;
|
private master?: GainNode;
|
||||||
private musicGain?: GainNode;
|
private musicGain?: GainNode;
|
||||||
private started = false;
|
private started = false;
|
||||||
|
private muted = false;
|
||||||
private sequenceTimer?: number;
|
private sequenceTimer?: number;
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
@@ -17,7 +18,7 @@ class SoundDirector {
|
|||||||
|
|
||||||
this.context = new AudioContextCtor();
|
this.context = new AudioContextCtor();
|
||||||
this.master = this.context.createGain();
|
this.master = this.context.createGain();
|
||||||
this.master.gain.value = 0.34;
|
this.master.gain.value = this.muted ? 0 : 0.34;
|
||||||
this.master.connect(this.context.destination);
|
this.master.connect(this.context.destination);
|
||||||
|
|
||||||
this.musicGain = this.context.createGain();
|
this.musicGain = this.context.createGain();
|
||||||
@@ -34,6 +35,21 @@ class SoundDirector {
|
|||||||
void this.context?.resume();
|
void this.context?.resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMuted(muted: boolean) {
|
||||||
|
this.muted = muted;
|
||||||
|
|
||||||
|
if (!this.context || !this.master) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.master.gain.cancelScheduledValues(this.context.currentTime);
|
||||||
|
this.master.gain.linearRampToValueAtTime(muted ? 0 : 0.34, this.context.currentTime + 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
isMuted() {
|
||||||
|
return this.muted;
|
||||||
|
}
|
||||||
|
|
||||||
playHover() {
|
playHover() {
|
||||||
this.playTone(660, 0.035, 0.04, 'sine');
|
this.playTone(660, 0.035, 0.04, 'sine');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { palette } from '../ui/palette';
|
|||||||
|
|
||||||
export class TitleScene extends Phaser.Scene {
|
export class TitleScene extends Phaser.Scene {
|
||||||
private focusedButton?: Phaser.GameObjects.Text;
|
private focusedButton?: Phaser.GameObjects.Text;
|
||||||
|
private settingsPanel?: Phaser.GameObjects.Container;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('TitleScene');
|
super('TitleScene');
|
||||||
@@ -117,21 +118,29 @@ export class TitleScene extends Phaser.Scene {
|
|||||||
private drawTitleMark(width: number, height: number) {
|
private drawTitleMark(width: number, height: number) {
|
||||||
const compact = width < 720;
|
const compact = width < 720;
|
||||||
const titleX = compact ? width / 2 : 92;
|
const titleX = compact ? width / 2 : 92;
|
||||||
const title = this.add.text(titleX, height - (compact ? 168 : 172), '桃園結義', {
|
const title = this.add.text(titleX, height - (compact ? 190 : 204), '삼국지', {
|
||||||
fontSize: compact ? '48px' : '56px',
|
fontFamily: '"Malgun Gothic", "Noto Sans KR", serif',
|
||||||
|
fontSize: compact ? '50px' : '64px',
|
||||||
color: '#f1e3c2',
|
color: '#f1e3c2',
|
||||||
fontStyle: '700',
|
fontStyle: '700',
|
||||||
|
padding: { top: 8, bottom: 8 },
|
||||||
shadow: { offsetX: 0, offsetY: 4, color: '#080a0e', blur: 10, fill: true }
|
shadow: { offsetX: 0, offsetY: 4, color: '#080a0e', blur: 10, fill: true }
|
||||||
});
|
});
|
||||||
title.setOrigin(compact ? 0.5 : 0, 0);
|
title.setOrigin(compact ? 0.5 : 0, 0);
|
||||||
|
|
||||||
const subtitle = this.add.text(compact ? width / 2 : 96, height - 98, 'Heros Web', {
|
const subtitle = this.add.text(compact ? width / 2 : 96, height - (compact ? 112 : 118), '세 형제의 맹세', {
|
||||||
fontSize: '24px',
|
fontFamily: '"Malgun Gothic", "Noto Sans KR", serif',
|
||||||
|
fontSize: compact ? '26px' : '34px',
|
||||||
color: '#d8b15f',
|
color: '#d8b15f',
|
||||||
fontStyle: '600',
|
fontStyle: '700',
|
||||||
|
padding: { top: 10, bottom: 8 },
|
||||||
shadow: { offsetX: 0, offsetY: 2, color: '#080a0e', blur: 6, fill: true }
|
shadow: { offsetX: 0, offsetY: 2, color: '#080a0e', blur: 6, fill: true }
|
||||||
});
|
});
|
||||||
subtitle.setOrigin(compact ? 0.5 : 0, 0);
|
subtitle.setOrigin(compact ? 0.5 : 0, 0);
|
||||||
|
|
||||||
|
const lineX = compact ? width / 2 - 110 : 98;
|
||||||
|
const lineY = height - (compact ? 76 : 70);
|
||||||
|
this.add.rectangle(lineX, lineY, compact ? 220 : 310, 2, palette.gold, 0.68).setOrigin(0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private drawMenu(width: number, height: number) {
|
private drawMenu(width: number, height: number) {
|
||||||
@@ -146,10 +155,7 @@ export class TitleScene extends Phaser.Scene {
|
|||||||
|
|
||||||
this.createMenuButton(menuX, menuY - 70, '새 게임', true, () => this.startGame());
|
this.createMenuButton(menuX, menuY - 70, '새 게임', true, () => this.startGame());
|
||||||
this.createMenuButton(menuX, menuY, '이어하기', false, () => undefined);
|
this.createMenuButton(menuX, menuY, '이어하기', false, () => undefined);
|
||||||
this.createMenuButton(menuX, menuY + 70, '설정', true, () => {
|
this.createMenuButton(menuX, menuY + 70, '설정', true, () => this.openSettingsPanel(menuX, menuY));
|
||||||
soundDirector.playSelect();
|
|
||||||
this.flashButtonText('설정은 다음 단계에서 열립니다.');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private createMenuButton(
|
private createMenuButton(
|
||||||
@@ -203,22 +209,69 @@ export class TitleScene extends Phaser.Scene {
|
|||||||
text.setBackgroundColor('rgba(0,0,0,0)');
|
text.setBackgroundColor('rgba(0,0,0,0)');
|
||||||
}
|
}
|
||||||
|
|
||||||
private flashButtonText(message: string) {
|
private openSettingsPanel(x: number, y: number) {
|
||||||
const toast = this.add.text(this.scale.width - 318, this.scale.height * 0.43 + 138, message, {
|
if (this.settingsPanel) {
|
||||||
fontSize: '16px',
|
this.closeSettingsPanel();
|
||||||
color: '#d8b15f',
|
return;
|
||||||
fixedWidth: 250,
|
}
|
||||||
|
|
||||||
|
soundDirector.playSelect();
|
||||||
|
|
||||||
|
const panel = this.add.container(x, y + 238);
|
||||||
|
const backdrop = this.add.rectangle(0, 0, 286, 188, 0x0e151d, 0.9);
|
||||||
|
backdrop.setStrokeStyle(1, palette.gold, 0.52);
|
||||||
|
|
||||||
|
const title = this.add.text(0, -66, '설정', {
|
||||||
|
fontSize: '24px',
|
||||||
|
color: '#f1e3c2',
|
||||||
|
fontStyle: '700',
|
||||||
|
fixedWidth: 210,
|
||||||
align: 'center'
|
align: 'center'
|
||||||
});
|
});
|
||||||
toast.setOrigin(0.5);
|
title.setOrigin(0.5);
|
||||||
this.tweens.add({
|
|
||||||
targets: toast,
|
const soundText = this.createSettingsButton(0, -10, this.soundLabel());
|
||||||
alpha: 0,
|
soundText.on('pointerdown', () => {
|
||||||
y: toast.y + 12,
|
soundDirector.setMuted(!soundDirector.isMuted());
|
||||||
duration: 1200,
|
soundText.setText(this.soundLabel());
|
||||||
ease: 'Sine.easeOut',
|
soundDirector.playSelect();
|
||||||
onComplete: () => toast.destroy()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const close = this.createSettingsButton(0, 48, '닫기');
|
||||||
|
close.on('pointerdown', () => {
|
||||||
|
soundDirector.playSelect();
|
||||||
|
this.closeSettingsPanel();
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.add([backdrop, title, soundText, close]);
|
||||||
|
panel.setAlpha(0);
|
||||||
|
this.settingsPanel = panel;
|
||||||
|
this.tweens.add({ targets: panel, alpha: 1, y: y + 228, duration: 160, ease: 'Sine.easeOut' });
|
||||||
|
}
|
||||||
|
|
||||||
|
private createSettingsButton(x: number, y: number, label: string) {
|
||||||
|
const text = this.add.text(x, y, label, {
|
||||||
|
fontSize: '20px',
|
||||||
|
color: '#d8b15f',
|
||||||
|
fixedWidth: 210,
|
||||||
|
align: 'center',
|
||||||
|
padding: { top: 8, bottom: 8 }
|
||||||
|
});
|
||||||
|
text.setOrigin(0.5);
|
||||||
|
text.setInteractive({ useHandCursor: true });
|
||||||
|
text.on('pointerover', () => text.setColor('#f1e3c2'));
|
||||||
|
text.on('pointerout', () => text.setColor('#d8b15f'));
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private soundLabel() {
|
||||||
|
return `음향: ${soundDirector.isMuted() ? '꺼짐' : '켜짐'}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private closeSettingsPanel() {
|
||||||
|
this.settingsPanel?.destroy();
|
||||||
|
this.settingsPanel = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private startGame() {
|
private startGame() {
|
||||||
|
|||||||
Reference in New Issue
Block a user