Polish story cutscene tactical UI
This commit is contained in:
@@ -40,14 +40,19 @@ const storyUnitFrameRows: Record<UnitDirection, number> = {
|
||||
const cutsceneUiColors = {
|
||||
veil: 0x020304,
|
||||
ink: 0x070809,
|
||||
lacquer: 0x100806,
|
||||
lacquerLight: 0x24120b,
|
||||
silk: 0x17100d,
|
||||
silkDeep: 0x0d0a08,
|
||||
woodDark: 0x160d07,
|
||||
woodMid: 0x2d1b0f,
|
||||
woodLight: 0x5f3d20,
|
||||
parchment: 0x715638,
|
||||
parchmentLight: 0x947345,
|
||||
parchmentDark: 0x2d1a0e
|
||||
parchment: 0x594832,
|
||||
parchmentLight: 0x7e6542,
|
||||
parchmentDark: 0x2d1a0e,
|
||||
paperEdge: 0xa67f4f,
|
||||
mapInk: 0x302113,
|
||||
sealRed: 0x8f3023
|
||||
} as const;
|
||||
|
||||
type CutsceneStageBounds = {
|
||||
@@ -206,12 +211,17 @@ export class StoryScene extends Phaser.Scene {
|
||||
private drawSceneShade(width: number, height: number) {
|
||||
const shade = this.add.graphics();
|
||||
shade.setDepth(sceneShadeDepth);
|
||||
shade.fillStyle(0x040608, 0.22);
|
||||
shade.fillStyle(0x030405, 0.34);
|
||||
shade.fillRect(0, 0, width, height);
|
||||
shade.fillStyle(0x040608, 0.5);
|
||||
shade.fillRect(0, height - 270, width, 270);
|
||||
shade.fillStyle(0x040608, 0.26);
|
||||
shade.fillRect(0, 0, width, 96);
|
||||
shade.fillStyle(0x030405, 0.5);
|
||||
shade.fillRect(0, height - 286, width, 286);
|
||||
shade.fillStyle(0x030405, 0.34);
|
||||
shade.fillRect(0, 0, width, 118);
|
||||
shade.fillStyle(0x030405, 0.2);
|
||||
shade.fillRect(0, 94, width, 388);
|
||||
shade.fillStyle(0x030405, 0.28);
|
||||
shade.fillRect(0, 0, 120, height);
|
||||
shade.fillRect(width - 120, 0, 120, height);
|
||||
}
|
||||
|
||||
private drawDialogPanel(width: number, height: number) {
|
||||
@@ -222,20 +232,26 @@ export class StoryScene extends Phaser.Scene {
|
||||
|
||||
const panel = this.add.graphics();
|
||||
panel.setDepth(dialogDepth);
|
||||
panel.fillStyle(cutsceneUiColors.veil, 0.52);
|
||||
panel.fillRoundedRect(panelX - 10, panelY + 10, panelW + 20, panelH + 18, 10);
|
||||
panel.fillStyle(cutsceneUiColors.woodDark, 0.94);
|
||||
panel.fillRoundedRect(panelX, panelY, panelW, panelH, 8);
|
||||
panel.fillStyle(cutsceneUiColors.silk, 0.82);
|
||||
panel.fillRoundedRect(panelX + 10, panelY + 10, panelW - 20, panelH - 20, 6);
|
||||
panel.lineStyle(2, palette.gold, 0.42);
|
||||
panel.strokeRoundedRect(panelX, panelY, panelW, panelH, 8);
|
||||
panel.lineStyle(1, 0xf0d08a, 0.22);
|
||||
panel.strokeRoundedRect(panelX + 10, panelY + 10, panelW - 20, panelH - 20, 6);
|
||||
panel.lineStyle(1, cutsceneUiColors.woodLight, 0.18);
|
||||
for (let index = 0; index < 5; index += 1) {
|
||||
const y = panelY + 24 + index * 28;
|
||||
panel.lineBetween(panelX + 188, y, panelX + panelW - 28, y + 4);
|
||||
panel.fillStyle(cutsceneUiColors.veil, 0.62);
|
||||
panel.fillRoundedRect(panelX - 12, panelY + 12, panelW + 24, panelH + 18, 12);
|
||||
panel.fillStyle(cutsceneUiColors.woodDark, 0.96);
|
||||
panel.fillRoundedRect(panelX, panelY, panelW, panelH, 10);
|
||||
panel.fillStyle(cutsceneUiColors.lacquer, 0.9);
|
||||
panel.fillRoundedRect(panelX + 12, panelY + 14, panelW - 24, panelH - 28, 8);
|
||||
panel.fillStyle(cutsceneUiColors.silk, 0.52);
|
||||
panel.fillRoundedRect(panelX + 22, panelY + 24, panelW - 44, panelH - 48, 6);
|
||||
panel.fillStyle(cutsceneUiColors.woodLight, 0.48);
|
||||
panel.fillRoundedRect(panelX + 20, panelY - 6, panelW - 40, 14, 7);
|
||||
panel.fillRoundedRect(panelX + 20, panelY + panelH - 8, panelW - 40, 14, 7);
|
||||
panel.lineStyle(2, palette.gold, 0.28);
|
||||
panel.strokeRoundedRect(panelX + 10, panelY + 10, panelW - 20, panelH - 20, 8);
|
||||
panel.lineStyle(1, 0xf0d08a, 0.12);
|
||||
panel.lineBetween(panelX + 198, panelY + 24, panelX + panelW - 30, panelY + 18);
|
||||
panel.lineBetween(panelX + 198, panelY + panelH - 26, panelX + panelW - 30, panelY + panelH - 18);
|
||||
panel.lineStyle(1, cutsceneUiColors.woodLight, 0.14);
|
||||
for (let index = 0; index < 4; index += 1) {
|
||||
const y = panelY + 40 + index * 24;
|
||||
panel.lineBetween(panelX + 198, y, panelX + panelW - 36, y + (index % 2 === 0 ? 3 : -3));
|
||||
}
|
||||
|
||||
this.chapterText = this.add.text(panelX, panelY - 42, '', {
|
||||
@@ -249,14 +265,14 @@ export class StoryScene extends Phaser.Scene {
|
||||
this.chapterText.setDepth(dialogDepth + 2);
|
||||
|
||||
this.portraitFrame = this.add.rectangle(panelX + 86, panelY + 86, 136, 136, cutsceneUiColors.ink, 0.92);
|
||||
this.portraitFrame.setStrokeStyle(2, palette.gold, 0.48);
|
||||
this.portraitFrame.setStrokeStyle(2, palette.gold, 0.34);
|
||||
this.portraitFrame.setDepth(dialogDepth + 2);
|
||||
|
||||
this.portrait = this.add.image(panelX + 86, panelY + 86, this.pagePortraitTextureKey(this.pages[0]) ?? 'story-fallback');
|
||||
this.portrait.setDisplaySize(128, 128);
|
||||
this.portrait.setDepth(dialogDepth + 3);
|
||||
|
||||
this.portraitDivider = this.add.rectangle(panelX + 166, panelY + 28, 1, panelH - 56, palette.gold, 0.16).setOrigin(0);
|
||||
this.portraitDivider = this.add.rectangle(panelX + 170, panelY + 30, 1, panelH - 60, palette.gold, 0.12).setOrigin(0);
|
||||
this.portraitDivider.setDepth(dialogDepth + 2);
|
||||
|
||||
this.nameText = this.add.text(panelX + 198, panelY + 28, '', {
|
||||
@@ -448,23 +464,33 @@ export class StoryScene extends Phaser.Scene {
|
||||
const { x: stageX, y: stageY, width: stageW, height: stageH } = this.cutsceneStageBounds();
|
||||
const accent = cutscene.kind === 'victory' ? palette.green : cutscene.kind === 'operation' ? palette.blue : palette.gold;
|
||||
const stage = this.add.graphics();
|
||||
stage.fillStyle(cutsceneUiColors.veil, 0.58);
|
||||
stage.fillRoundedRect(stageX - 18, stageY - 14, stageW + 36, stageH + 28, 12);
|
||||
stage.fillStyle(cutsceneUiColors.veil, 0.62);
|
||||
stage.fillRoundedRect(stageX - 18, stageY - 14, stageW + 36, stageH + 28, 14);
|
||||
stage.fillStyle(cutsceneUiColors.woodDark, 0.98);
|
||||
stage.fillRoundedRect(stageX, stageY, stageW, stageH, 10);
|
||||
stage.fillStyle(cutsceneUiColors.woodMid, 0.86);
|
||||
stage.fillRoundedRect(stageX + 13, stageY + 13, stageW - 26, stageH - 26, 7);
|
||||
stage.fillStyle(cutsceneUiColors.silkDeep, 0.62);
|
||||
stage.fillRoundedRect(stageX + 24, stageY + 74, stageW - 48, stageH - 108, 7);
|
||||
stage.lineStyle(2, accent, 0.42);
|
||||
stage.strokeRoundedRect(stageX, stageY, stageW, stageH, 10);
|
||||
stage.lineStyle(1, 0xf0d08a, 0.18);
|
||||
stage.strokeRoundedRect(stageX + 13, stageY + 13, stageW - 26, stageH - 26, 7);
|
||||
stage.lineStyle(1, cutsceneUiColors.woodLight, 0.2);
|
||||
for (let index = 0; index < 9; index += 1) {
|
||||
const y = stageY + 30 + index * 31;
|
||||
stage.lineBetween(stageX + 28, y, stageX + stageW - 28, y + (index % 2 === 0 ? 5 : -4));
|
||||
stage.fillRoundedRect(stageX, stageY, stageW, stageH, 12);
|
||||
stage.fillStyle(cutsceneUiColors.woodMid, 0.9);
|
||||
stage.fillRoundedRect(stageX + 12, stageY + 12, stageW - 24, stageH - 24, 9);
|
||||
stage.fillStyle(cutsceneUiColors.lacquer, 0.68);
|
||||
stage.fillRoundedRect(stageX + 26, stageY + 76, stageW - 52, stageH - 112, 8);
|
||||
stage.fillStyle(cutsceneUiColors.woodLight, 0.2);
|
||||
stage.fillRoundedRect(stageX + 18, stageY + 14, stageW - 36, 16, 8);
|
||||
stage.fillStyle(cutsceneUiColors.woodDark, 0.36);
|
||||
stage.fillRoundedRect(stageX + 18, stageY + stageH - 28, stageW - 36, 12, 6);
|
||||
stage.lineStyle(1, accent, 0.28);
|
||||
stage.strokeRoundedRect(stageX + 11, stageY + 11, stageW - 22, stageH - 22, 9);
|
||||
stage.lineStyle(1, 0xf0d08a, 0.1);
|
||||
stage.lineBetween(stageX + 30, stageY + 70, stageX + stageW - 30, stageY + 68);
|
||||
stage.lineBetween(stageX + 30, stageY + stageH - 52, stageX + stageW - 30, stageY + stageH - 46);
|
||||
stage.lineStyle(1, cutsceneUiColors.woodLight, 0.16);
|
||||
for (let index = 0; index < 12; index += 1) {
|
||||
const y = stageY + 28 + index * 24;
|
||||
stage.lineBetween(stageX + 28, y, stageX + stageW - 28, y + (index % 2 === 0 ? 4 : -3));
|
||||
}
|
||||
stage.fillStyle(0x0a0504, 0.38);
|
||||
stage.fillCircle(stageX + 28, stageY + 28, 4);
|
||||
stage.fillCircle(stageX + stageW - 28, stageY + 28, 4);
|
||||
stage.fillCircle(stageX + 28, stageY + stageH - 28, 4);
|
||||
stage.fillCircle(stageX + stageW - 28, stageY + stageH - 28, 4);
|
||||
|
||||
const foldingScreen = this.add.graphics();
|
||||
foldingScreen.lineStyle(1, 0xd0b16e, 0.1);
|
||||
@@ -477,12 +503,15 @@ export class StoryScene extends Phaser.Scene {
|
||||
|
||||
const tableShadow = this.add.ellipse(stageX + stageW * 0.62, stageY + stageH - 34, stageW * 0.6, 38, 0x030405, 0.34);
|
||||
const titlePlate = this.add.graphics();
|
||||
titlePlate.fillStyle(cutsceneUiColors.ink, 0.8);
|
||||
titlePlate.fillRoundedRect(stageX + 22, stageY + 18, 366, 48, 7);
|
||||
titlePlate.lineStyle(1, accent, 0.36);
|
||||
titlePlate.strokeRoundedRect(stageX + 22, stageY + 18, 366, 48, 7);
|
||||
titlePlate.lineStyle(1, 0xf0d08a, 0.14);
|
||||
titlePlate.lineBetween(stageX + 34, stageY + 60, stageX + 374, stageY + 60);
|
||||
titlePlate.fillStyle(cutsceneUiColors.lacquer, 0.88);
|
||||
titlePlate.fillRoundedRect(stageX + 22, stageY + 18, 366, 48, 8);
|
||||
titlePlate.fillStyle(accent, 0.14);
|
||||
titlePlate.fillRoundedRect(stageX + 30, stageY + 25, 34, 34, 5);
|
||||
titlePlate.lineStyle(1, accent, 0.3);
|
||||
titlePlate.lineBetween(stageX + 74, stageY + 25, stageX + 374, stageY + 25);
|
||||
titlePlate.lineBetween(stageX + 74, stageY + 60, stageX + 374, stageY + 60);
|
||||
titlePlate.lineStyle(1, 0xf0d08a, 0.12);
|
||||
titlePlate.strokeRoundedRect(stageX + 22, stageY + 18, 366, 48, 8);
|
||||
|
||||
const title = this.add.text(stageX + 34, stageY + 18, cutscene.title, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", serif',
|
||||
@@ -508,55 +537,81 @@ export class StoryScene extends Phaser.Scene {
|
||||
const boardH = stage.height - 118;
|
||||
const board: CutsceneBoardBounds = { x: boardX, y: boardY, width: boardW, height: boardH };
|
||||
const parchment = this.add.graphics();
|
||||
parchment.fillStyle(cutsceneUiColors.veil, 0.28);
|
||||
parchment.fillRoundedRect(boardX + 10, boardY + 10, boardW, boardH, 8);
|
||||
parchment.fillStyle(cutsceneUiColors.parchmentDark, 0.96);
|
||||
parchment.fillRoundedRect(boardX, boardY, boardW, boardH, 8);
|
||||
parchment.fillStyle(cutsceneUiColors.parchment, 0.98);
|
||||
parchment.fillRoundedRect(boardX + 5, boardY + 5, boardW - 10, boardH - 10, 6);
|
||||
parchment.fillStyle(cutsceneUiColors.parchmentLight, 0.12);
|
||||
parchment.fillRoundedRect(boardX + 18, boardY + 18, boardW - 36, boardH - 36, 5);
|
||||
parchment.lineStyle(3, 0x3a2110, 0.78);
|
||||
parchment.strokeRoundedRect(boardX, boardY, boardW, boardH, 8);
|
||||
parchment.lineStyle(1, 0xf0d08a, 0.22);
|
||||
parchment.strokeRoundedRect(boardX + 10, boardY + 10, boardW - 20, boardH - 20, 5);
|
||||
parchment.lineStyle(1, 0x5b3a1e, 0.18);
|
||||
for (let index = 0; index < 18; index += 1) {
|
||||
const y = boardY + 28 + index * 10;
|
||||
const xOffset = index % 3 === 0 ? 18 : index % 3 === 1 ? 34 : 26;
|
||||
parchment.lineBetween(boardX + xOffset, y, boardX + boardW - 24, y + (index % 2 === 0 ? 2 : -2));
|
||||
parchment.fillStyle(cutsceneUiColors.veil, 0.34);
|
||||
parchment.fillEllipse(boardX + boardW * 0.52, boardY + boardH + 12, boardW * 0.9, 34);
|
||||
parchment.fillStyle(cutsceneUiColors.woodDark, 0.92);
|
||||
parchment.fillRoundedRect(boardX + 10, boardY - 10, boardW - 20, 20, 10);
|
||||
parchment.fillRoundedRect(boardX + 8, boardY + boardH - 10, boardW - 16, 20, 10);
|
||||
parchment.fillStyle(cutsceneUiColors.woodLight, 0.35);
|
||||
parchment.fillRoundedRect(boardX + 22, boardY - 5, boardW - 44, 5, 3);
|
||||
parchment.fillRoundedRect(boardX + 22, boardY + boardH - 5, boardW - 44, 5, 3);
|
||||
parchment.fillStyle(cutsceneUiColors.parchmentDark, 0.94);
|
||||
parchment.fillRoundedRect(boardX + 3, boardY + 4, boardW - 6, boardH - 8, 5);
|
||||
parchment.fillStyle(cutsceneUiColors.parchment, 0.92);
|
||||
parchment.fillRoundedRect(boardX + 10, boardY + 12, boardW - 20, boardH - 24, 4);
|
||||
parchment.fillStyle(cutsceneUiColors.parchmentLight, 0.08);
|
||||
parchment.fillEllipse(boardX + boardW * 0.5, boardY + boardH * 0.48, boardW * 0.82, boardH * 0.66);
|
||||
parchment.fillStyle(cutsceneUiColors.paperEdge, 0.12);
|
||||
parchment.fillRoundedRect(boardX + 10, boardY + 12, boardW - 20, 10, 4);
|
||||
parchment.fillRoundedRect(boardX + 10, boardY + boardH - 22, boardW - 20, 10, 4);
|
||||
parchment.fillStyle(0x23140c, 0.1);
|
||||
parchment.fillEllipse(boardX + boardW * 0.5, boardY + boardH * 0.62, boardW * 0.72, boardH * 0.34);
|
||||
parchment.lineStyle(1, cutsceneUiColors.mapInk, 0.24);
|
||||
parchment.strokeRoundedRect(boardX + 8, boardY + 10, boardW - 16, boardH - 20, 5);
|
||||
parchment.lineStyle(1, 0xf0d08a, 0.1);
|
||||
parchment.lineBetween(boardX + 24, boardY + 20, boardX + boardW - 28, boardY + 16);
|
||||
parchment.lineBetween(boardX + 26, boardY + boardH - 20, boardX + boardW - 24, boardY + boardH - 24);
|
||||
parchment.fillStyle(0x3d2413, 0.16);
|
||||
parchment.beginPath();
|
||||
parchment.moveTo(boardX + boardW - 54, boardY + 12);
|
||||
parchment.lineTo(boardX + boardW - 12, boardY + 12);
|
||||
parchment.lineTo(boardX + boardW - 12, boardY + 52);
|
||||
parchment.closePath();
|
||||
parchment.fillPath();
|
||||
parchment.lineStyle(1, 0x3d2413, 0.1);
|
||||
for (let index = 0; index < 11; index += 1) {
|
||||
const y = boardY + 38 + index * 14;
|
||||
const xOffset = index % 3 === 0 ? 26 : index % 3 === 1 ? 38 : 31;
|
||||
parchment.lineBetween(boardX + xOffset, y, boardX + boardW - 30, y + (index % 2 === 0 ? 2 : -2));
|
||||
}
|
||||
for (let index = 0; index < 28; index += 1) {
|
||||
const x = boardX + 30 + ((index * 47) % Math.max(60, boardW - 58));
|
||||
const y = boardY + 34 + ((index * 29) % Math.max(60, boardH - 62));
|
||||
parchment.fillStyle(index % 2 === 0 ? 0x6a4726 : 0xd2b172, 0.12);
|
||||
parchment.fillCircle(x, y, index % 3 === 0 ? 1.5 : 1);
|
||||
for (let index = 0; index < 30; index += 1) {
|
||||
const x = boardX + 30 + ((index * 47) % Math.max(60, boardW - 62));
|
||||
const y = boardY + 34 + ((index * 29) % Math.max(60, boardH - 66));
|
||||
parchment.fillStyle(index % 2 === 0 ? 0x4f3219 : 0xd2b172, 0.1);
|
||||
parchment.fillCircle(x, y, index % 3 === 0 ? 1.4 : 0.9);
|
||||
}
|
||||
layer.add(parchment);
|
||||
|
||||
const map = this.add.graphics();
|
||||
map.lineStyle(1, 0x3e2614, 0.14);
|
||||
map.lineStyle(1, cutsceneUiColors.mapInk, 0.08);
|
||||
for (let index = 1; index < 7; index += 1) {
|
||||
const x = boardX + (boardW / 7) * index;
|
||||
map.lineBetween(x, boardY + 16, x, boardY + boardH - 16);
|
||||
map.lineBetween(x, boardY + 24, x, boardY + boardH - 24);
|
||||
}
|
||||
for (let index = 1; index < 4; index += 1) {
|
||||
const y = boardY + (boardH / 4) * index;
|
||||
map.lineBetween(boardX + 16, y, boardX + boardW - 16, y);
|
||||
map.lineBetween(boardX + 24, y, boardX + boardW - 24, y);
|
||||
}
|
||||
map.fillStyle(0x37563b, 0.24);
|
||||
map.fillEllipse(boardX + boardW * 0.36, boardY + boardH * 0.58, boardW * 0.38, boardH * 0.52);
|
||||
map.fillStyle(0x3d5161, 0.18);
|
||||
map.fillEllipse(boardX + boardW * 0.72, boardY + boardH * 0.36, boardW * 0.26, boardH * 0.3);
|
||||
map.lineStyle(6, 0x6b4826, 0.3);
|
||||
map.fillStyle(0x365238, 0.18);
|
||||
map.fillEllipse(boardX + boardW * 0.35, boardY + boardH * 0.58, boardW * 0.42, boardH * 0.46);
|
||||
map.fillStyle(0x36465b, 0.14);
|
||||
map.fillEllipse(boardX + boardW * 0.72, boardY + boardH * 0.36, boardW * 0.28, boardH * 0.28);
|
||||
map.lineStyle(8, 0x6b4826, 0.18);
|
||||
map.beginPath();
|
||||
map.moveTo(boardX + boardW * 0.16, boardY + boardH * 0.74);
|
||||
map.lineTo(boardX + boardW * 0.38, boardY + boardH * 0.54);
|
||||
map.lineTo(boardX + boardW * 0.66, boardY + boardH * 0.36);
|
||||
map.lineTo(boardX + boardW * 0.83, boardY + boardH * 0.24);
|
||||
map.strokePath();
|
||||
map.lineStyle(2, 0x2b2114, 0.32);
|
||||
map.strokeRoundedRect(boardX + 24, boardY + 24, boardW - 48, boardH - 48, 4);
|
||||
map.lineStyle(2, cutsceneUiColors.mapInk, 0.22);
|
||||
map.beginPath();
|
||||
map.moveTo(boardX + boardW * 0.16, boardY + boardH * 0.74);
|
||||
map.lineTo(boardX + boardW * 0.38, boardY + boardH * 0.54);
|
||||
map.lineTo(boardX + boardW * 0.66, boardY + boardH * 0.36);
|
||||
map.lineTo(boardX + boardW * 0.83, boardY + boardH * 0.24);
|
||||
map.strokePath();
|
||||
map.lineStyle(1, cutsceneUiColors.mapInk, 0.18);
|
||||
map.strokeRoundedRect(boardX + 26, boardY + 28, boardW - 52, boardH - 56, 4);
|
||||
layer.add(map);
|
||||
|
||||
this.renderBoardLegend(layer, cutscene, board);
|
||||
@@ -569,14 +624,16 @@ export class StoryScene extends Phaser.Scene {
|
||||
private renderBoardLegend(layer: Phaser.GameObjects.Container, cutscene: StoryCutscene, board: CutsceneBoardBounds) {
|
||||
const label = cutscene.kind === 'victory' ? 'RESULT MAP' : cutscene.kind === 'operation' ? 'TACTICAL MAP' : 'SORTIE BOARD';
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(cutsceneUiColors.silkDeep, 0.72);
|
||||
bg.fillRoundedRect(board.x + 18, board.y + 16, 128, 24, 5);
|
||||
bg.lineStyle(1, 0xe3c271, 0.26);
|
||||
bg.strokeRoundedRect(board.x + 18, board.y + 16, 128, 24, 5);
|
||||
const text = this.add.text(board.x + 32, board.y + 21, label, {
|
||||
bg.fillStyle(cutsceneUiColors.mapInk, 0.18);
|
||||
bg.fillRoundedRect(board.x + 24, board.y + 24, 126, 22, 4);
|
||||
bg.lineStyle(1, cutsceneUiColors.mapInk, 0.18);
|
||||
bg.lineBetween(board.x + 32, board.y + 43, board.x + 140, board.y + 43);
|
||||
bg.fillStyle(cutsceneUiColors.sealRed, 0.22);
|
||||
bg.fillCircle(board.x + 134, board.y + 35, 8);
|
||||
const text = this.add.text(board.x + 34, board.y + 28, label, {
|
||||
fontFamily: '"Segoe UI", sans-serif',
|
||||
fontSize: '12px',
|
||||
color: '#f2e3bf',
|
||||
color: '#ead6aa',
|
||||
fontStyle: '700'
|
||||
});
|
||||
layer.add([bg, text]);
|
||||
@@ -624,27 +681,38 @@ export class StoryScene extends Phaser.Scene {
|
||||
|
||||
const card = this.add.graphics();
|
||||
card.fillStyle(cutsceneUiColors.veil, 0.34);
|
||||
card.fillRoundedRect(x + 5, y + 6, width, height, 7);
|
||||
card.fillRoundedRect(x + 5, y + 7, width, height, 8);
|
||||
card.fillStyle(cutsceneUiColors.woodDark, 0.94);
|
||||
card.fillRoundedRect(x, y, width, height, 7);
|
||||
card.fillStyle(cutsceneUiColors.silk, 0.78);
|
||||
card.fillRoundedRect(x + 7, y + 7, width - 14, height - 14, 5);
|
||||
card.fillStyle(profile.color, 0.72);
|
||||
card.fillRoundedRect(x + 8, y + 9, 4, height - 18, 3);
|
||||
card.lineStyle(1, profile.color, 0.42);
|
||||
card.strokeRoundedRect(x, y, width, height, 7);
|
||||
card.lineStyle(1, 0xf0d08a, 0.12);
|
||||
card.lineBetween(x + 20, y + height - 9, x + width - 20, y + height - 9);
|
||||
card.fillRoundedRect(x, y, width, height, 8);
|
||||
card.fillStyle(cutsceneUiColors.lacquerLight, 0.46);
|
||||
card.fillRoundedRect(x + 7, y + 7, width - 14, height - 14, 6);
|
||||
card.fillStyle(cutsceneUiColors.lacquer, 0.42);
|
||||
card.fillRoundedRect(x + 72, y + 9, width - 88, height - 18, 5);
|
||||
card.fillStyle(profile.color, 0.42);
|
||||
card.fillRoundedRect(x + 11, y + 10, 4, height - 20, 2);
|
||||
card.fillStyle(cutsceneUiColors.paperEdge, 0.16);
|
||||
card.fillRoundedRect(x + height + 4, y + 9, Math.min(130, width - height - 52), 24, 4);
|
||||
card.lineStyle(1, 0xf0d08a, 0.14);
|
||||
card.lineBetween(x + 22, y + 9, x + width - 24, y + 9);
|
||||
card.lineBetween(x + 22, y + height - 9, x + width - 24, y + height - 9);
|
||||
card.lineStyle(1, profile.color, 0.24);
|
||||
card.lineBetween(x + 18, y + 15, x + 18, y + height - 15);
|
||||
card.fillStyle(profile.color, 0.18);
|
||||
card.fillCircle(x + width - 24, y + height / 2, 12);
|
||||
card.fillStyle(cutsceneUiColors.sealRed, 0.18);
|
||||
card.fillCircle(x + width - 24, y + height / 2, 7);
|
||||
layer.add(card);
|
||||
|
||||
const portraitTexture = this.actorPortraitTextureKey(actor, index);
|
||||
const portraitX = x + 38;
|
||||
const portraitY = y + height / 2;
|
||||
const portraitFrame = this.add.graphics();
|
||||
portraitFrame.fillStyle(cutsceneUiColors.ink, 0.9);
|
||||
portraitFrame.fillRoundedRect(portraitX - (height - 12) / 2, portraitY - (height - 12) / 2, height - 12, height - 12, 5);
|
||||
portraitFrame.lineStyle(1, profile.color, 0.44);
|
||||
portraitFrame.strokeRoundedRect(portraitX - (height - 12) / 2, portraitY - (height - 12) / 2, height - 12, height - 12, 5);
|
||||
portraitFrame.fillStyle(cutsceneUiColors.ink, 0.92);
|
||||
portraitFrame.fillRoundedRect(portraitX - (height - 14) / 2, portraitY - (height - 14) / 2, height - 14, height - 14, 5);
|
||||
portraitFrame.lineStyle(1, profile.color, 0.34);
|
||||
portraitFrame.strokeRoundedRect(portraitX - (height - 14) / 2, portraitY - (height - 14) / 2, height - 14, height - 14, 5);
|
||||
portraitFrame.lineStyle(1, 0xf0d08a, 0.1);
|
||||
portraitFrame.strokeRoundedRect(portraitX - (height - 24) / 2, portraitY - (height - 24) / 2, height - 24, height - 24, 3);
|
||||
layer.add(portraitFrame);
|
||||
|
||||
if (portraitTexture) {
|
||||
@@ -657,18 +725,16 @@ export class StoryScene extends Phaser.Scene {
|
||||
layer.add(sprite);
|
||||
}
|
||||
|
||||
const name = this.add.text(x + height + 10, y + 10, actor.label ?? profile.name, {
|
||||
const name = this.add.text(x + height + 14, y + 11, actor.label ?? profile.name, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '16px',
|
||||
color: '#f5e6c8',
|
||||
fontStyle: '700'
|
||||
});
|
||||
const roleBg = this.add.graphics();
|
||||
roleBg.fillStyle(cutsceneUiColors.parchmentDark, 0.5);
|
||||
roleBg.fillRoundedRect(x + height + 8, y + 34, Math.min(108, width - height - 22), 20, 4);
|
||||
roleBg.lineStyle(1, 0xf0d08a, 0.16);
|
||||
roleBg.strokeRoundedRect(x + height + 8, y + 34, Math.min(108, width - height - 22), 20, 4);
|
||||
const role = this.add.text(x + height + 18, y + 37, profile.roleLabel, {
|
||||
roleBg.lineStyle(1, profile.color, 0.26);
|
||||
roleBg.lineBetween(x + height + 14, y + 38, x + height + Math.min(128, width - height - 34), y + 38);
|
||||
const role = this.add.text(x + height + 14, y + 42, profile.roleLabel, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '12px',
|
||||
color: '#ddc99f'
|
||||
@@ -676,11 +742,11 @@ export class StoryScene extends Phaser.Scene {
|
||||
layer.add([roleBg, name, role]);
|
||||
|
||||
if (actor.line && height >= 66) {
|
||||
const line = this.add.text(x + 138, y + 50, actor.line, {
|
||||
const line = this.add.text(x + 144, y + 50, actor.line, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '11px',
|
||||
color: '#d8cbb2',
|
||||
wordWrap: { width: width - 152, useAdvancedWrap: true }
|
||||
wordWrap: { width: width - 166, useAdvancedWrap: true }
|
||||
});
|
||||
layer.add(line);
|
||||
}
|
||||
@@ -700,16 +766,16 @@ export class StoryScene extends Phaser.Scene {
|
||||
const y = board.y + board.height * Phaser.Math.Clamp(normalizedY, 0.18, 0.82);
|
||||
const sideColor = actor.unitId === 'rebel-leader' ? 0xd46a4c : profile.color;
|
||||
const token = this.add.container(x, y);
|
||||
const shadow = this.add.ellipse(2, 13, 42, 14, 0x05070a, 0.3);
|
||||
const base = this.add.ellipse(0, 5, 34, 24, cutsceneUiColors.silkDeep, 0.86);
|
||||
base.setStrokeStyle(2, sideColor, 0.62);
|
||||
const pin = this.add.circle(0, 5, 4, sideColor, 0.92);
|
||||
pin.setStrokeStyle(1, 0x05070a, 0.7);
|
||||
const shadow = this.add.ellipse(2, 12, 38, 12, 0x05070a, 0.28);
|
||||
const base = this.add.ellipse(0, 6, 30, 18, cutsceneUiColors.woodDark, 0.78);
|
||||
base.setStrokeStyle(1, sideColor, 0.46);
|
||||
const pin = this.add.circle(0, 6, 3, sideColor, 0.86);
|
||||
pin.setStrokeStyle(1, 0x05070a, 0.62);
|
||||
token.add([shadow, base, pin]);
|
||||
|
||||
if (this.textures.exists(profile.unitTextureKey)) {
|
||||
const sprite = this.add.sprite(0, -8, profile.unitTextureKey, this.storyUnitFrameIndex(actor.direction ?? 'south'));
|
||||
sprite.setDisplaySize(36, 36);
|
||||
sprite.setDisplaySize(34, 34);
|
||||
token.add(sprite);
|
||||
} else {
|
||||
const fallback = this.add.rectangle(0, -8, 22, 24, sideColor, 0.9);
|
||||
@@ -720,7 +786,7 @@ export class StoryScene extends Phaser.Scene {
|
||||
const label = this.add.text(0, 14, actor.label ?? profile.name, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '9px',
|
||||
color: '#f2e3bf',
|
||||
color: '#ead9b8',
|
||||
stroke: '#05070a',
|
||||
strokeThickness: 2
|
||||
});
|
||||
@@ -738,11 +804,14 @@ export class StoryScene extends Phaser.Scene {
|
||||
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(cutsceneUiColors.veil, 0.28);
|
||||
bg.fillRoundedRect(x + 4, y + 5, width, height, 7);
|
||||
bg.fillStyle(cutsceneUiColors.silkDeep, 0.78);
|
||||
bg.fillRoundedRect(x, y, width, height, 7);
|
||||
bg.lineStyle(1, palette.gold, 0.3);
|
||||
bg.strokeRoundedRect(x, y, width, height, 7);
|
||||
bg.fillRoundedRect(x + 4, y + 5, width, height, 8);
|
||||
bg.fillStyle(cutsceneUiColors.lacquer, 0.68);
|
||||
bg.fillRoundedRect(x, y, width, height, 8);
|
||||
bg.fillStyle(cutsceneUiColors.paperEdge, 0.08);
|
||||
bg.fillRoundedRect(x + 10, y + 10, width - 20, height - 20, 6);
|
||||
bg.lineStyle(1, palette.gold, 0.18);
|
||||
bg.lineBetween(x + 16, y + 13, x + width - 16, y + 13);
|
||||
bg.lineBetween(x + 16, y + height - 13, x + width - 16, y + height - 13);
|
||||
const title = this.add.text(x + 18, y + 16, cutscene.briefing?.title ?? '전황', {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '18px',
|
||||
@@ -806,9 +875,10 @@ export class StoryScene extends Phaser.Scene {
|
||||
const color = marker.side === 'ally' ? palette.blue : marker.side === 'enemy' ? 0xd46a4c : palette.gold;
|
||||
const x = boardX + boardW * marker.x;
|
||||
const y = boardY + boardH * marker.y;
|
||||
const halo = this.add.circle(x, y, 12, color, 0.12);
|
||||
const dot = this.add.circle(x, y, 5, color, 0.9);
|
||||
dot.setStrokeStyle(1, 0x05070a, 0.82);
|
||||
const halo = this.add.circle(x, y, 9, color, 0.1);
|
||||
const dot = this.add.circle(x, y, 4, color, 0.86);
|
||||
dot.setStrokeStyle(1, cutsceneUiColors.mapInk, 0.72);
|
||||
const stem = this.add.rectangle(x - 0.5, y + 4, 1, 13, color, 0.42).setOrigin(0, 0);
|
||||
const labelX = marker.side === 'objective' ? x - 8 : x + 11;
|
||||
const labelY = marker.side === 'objective' ? y - 27 : y - 10;
|
||||
const label = this.add.text(labelX, labelY, marker.label, {
|
||||
@@ -821,7 +891,7 @@ export class StoryScene extends Phaser.Scene {
|
||||
if (marker.side === 'objective') {
|
||||
label.setOrigin(0.5, 0);
|
||||
}
|
||||
layer.add([halo, dot, label]);
|
||||
layer.add([halo, stem, dot, label]);
|
||||
}
|
||||
|
||||
private renderCutsceneActor(layer: Phaser.GameObjects.Container, actor: StoryCutsceneActor, index: number) {
|
||||
@@ -890,31 +960,39 @@ export class StoryScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
const stage = this.cutsceneStageBounds();
|
||||
const startX = stage.x + 28;
|
||||
const gap = 12;
|
||||
const maxItems = Math.min(4, rewards.length);
|
||||
const itemW = Math.floor((stage.width - 56 - gap * (maxItems - 1)) / maxItems);
|
||||
const y = stage.y + stage.height - 44;
|
||||
const stripX = stage.x + 28;
|
||||
const stripY = stage.y + stage.height - 44;
|
||||
const stripW = stage.width - 56;
|
||||
const itemW = Math.floor(stripW / maxItems);
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(cutsceneUiColors.veil, 0.22);
|
||||
bg.fillRoundedRect(stripX + 4, stripY + 5, stripW, 34, 6);
|
||||
bg.fillStyle(cutsceneUiColors.lacquer, 0.72);
|
||||
bg.fillRoundedRect(stripX, stripY, stripW, 34, 6);
|
||||
bg.lineStyle(1, palette.gold, 0.18);
|
||||
bg.lineBetween(stripX + 12, stripY + 6, stripX + stripW - 12, stripY + 6);
|
||||
bg.lineBetween(stripX + 12, stripY + 28, stripX + stripW - 12, stripY + 28);
|
||||
layer.add(bg);
|
||||
|
||||
rewards.slice(0, maxItems).forEach((reward, index) => {
|
||||
const toneColor = reward.tone === 'next' ? palette.blue : reward.tone === 'bond' ? palette.green : palette.gold;
|
||||
const x = startX + index * (itemW + gap);
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(cutsceneUiColors.veil, 0.24);
|
||||
bg.fillRoundedRect(x + 3, y + 4, itemW, 34, 6);
|
||||
bg.fillStyle(cutsceneUiColors.silkDeep, 0.78);
|
||||
bg.fillRoundedRect(x, y, itemW, 34, 6);
|
||||
bg.fillStyle(toneColor, 0.14);
|
||||
bg.fillRoundedRect(x + 5, y + 5, itemW - 10, 24, 4);
|
||||
bg.lineStyle(1, toneColor, 0.34);
|
||||
bg.strokeRoundedRect(x, y, itemW, 34, 6);
|
||||
const text = this.add.text(x + 14, y + 8, reward.label, {
|
||||
const x = stripX + index * itemW;
|
||||
const item = this.add.graphics();
|
||||
item.fillStyle(toneColor, 0.16);
|
||||
item.fillCircle(x + 17, stripY + 17, 5);
|
||||
item.lineStyle(1, toneColor, 0.22);
|
||||
if (index > 0) {
|
||||
item.lineBetween(x, stripY + 9, x, stripY + 25);
|
||||
}
|
||||
const text = this.add.text(x + 30, stripY + 8, reward.label, {
|
||||
fontFamily: '"Malgun Gothic", "Noto Sans KR", sans-serif',
|
||||
fontSize: '13px',
|
||||
color: '#f2e3bf',
|
||||
fontStyle: '700',
|
||||
wordWrap: { width: itemW - 26, useAdvancedWrap: true }
|
||||
wordWrap: { width: itemW - 40, useAdvancedWrap: true }
|
||||
});
|
||||
layer.add([bg, text]);
|
||||
layer.add([item, text]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user