Add late campaign character portraits

This commit is contained in:
2026-06-24 19:49:19 +09:00
parent 40078eabe3
commit cc70d1b665
10 changed files with 64 additions and 12 deletions

View File

@@ -1,7 +1,7 @@
import type { TerrainType, UnitClassKey } from './battleRules';
import type { EquipmentSet } from './battleItems';
export type PortraitKey = 'liuBei' | 'guanYu' | 'zhangFei';
export type PortraitKey = 'liuBei' | 'guanYu' | 'zhangFei' | 'zhugeLiang' | 'zhaoYun' | 'jiangWei' | 'simaYi';
export type StoryPage = {
id: string;

View File

@@ -7231,6 +7231,18 @@ export class BattleScene extends Phaser.Scene {
if (unit.id === 'zhang-fei') {
return 'portrait-zhang-fei';
}
if (unit.id === 'zhuge-liang') {
return 'portrait-zhuge-liang';
}
if (unit.id === 'zhao-yun') {
return 'portrait-zhao-yun';
}
if (unit.id === 'jiang-wei') {
return 'portrait-jiang-wei';
}
if (unit.id.includes('sima-yi') || unit.name === '사마의') {
return 'portrait-sima-yi';
}
return undefined;
}
@@ -9277,6 +9289,7 @@ export class BattleScene extends Phaser.Scene {
classKey: unit.classKey,
textureBase: this.unitViews.get(unit.id)?.textureBase ?? this.unitTextureKey(unit),
actionTexture: this.unitActionTexture(unit),
combatPortraitKey: this.combatPortraitKey(unit) ?? null,
ai: unit.faction === 'enemy' ? this.enemyBehavior(unit) : null,
attackRange: this.attackRange(unit),
level: unit.level,

View File

@@ -1,7 +1,11 @@
import Phaser from 'phaser';
import guanYuPortraitUrl from '../../assets/images/portraits/guan-yu.png';
import jiangWeiPortraitUrl from '../../assets/images/portraits/jiang-wei.png';
import liuBeiPortraitUrl from '../../assets/images/portraits/liu-bei.png';
import simaYiPortraitUrl from '../../assets/images/portraits/sima-yi.png';
import zhaoYunPortraitUrl from '../../assets/images/portraits/zhao-yun.png';
import zhangFeiPortraitUrl from '../../assets/images/portraits/zhang-fei.png';
import zhugeLiangPortraitUrl from '../../assets/images/portraits/zhuge-liang.png';
import titleBackgroundUrl from '../../assets/images/taoyuan-oath-title.png';
import guanYuActionSheetUrl from '../../assets/images/units/unit-guan-yu-actions.png';
import guanYuUnitSheetUrl from '../../assets/images/units/unit-guan-yu.png';
@@ -77,6 +81,10 @@ export class BootScene extends Phaser.Scene {
this.load.image('portrait-liu-bei', liuBeiPortraitUrl);
this.load.image('portrait-guan-yu', guanYuPortraitUrl);
this.load.image('portrait-zhang-fei', zhangFeiPortraitUrl);
this.load.image('portrait-zhuge-liang', zhugeLiangPortraitUrl);
this.load.image('portrait-zhao-yun', zhaoYunPortraitUrl);
this.load.image('portrait-jiang-wei', jiangWeiPortraitUrl);
this.load.image('portrait-sima-yi', simaYiPortraitUrl);
sourceUnitSheets.forEach(({ key, url, actionKey, actionUrl }) => {
this.load.spritesheet(key, url, {

View File

@@ -255,13 +255,20 @@ type CampaignTimelineChapter = {
const portraitKeys: Record<PortraitKey, string> = {
liuBei: 'portrait-liu-bei',
guanYu: 'portrait-guan-yu',
zhangFei: 'portrait-zhang-fei'
zhangFei: 'portrait-zhang-fei',
zhugeLiang: 'portrait-zhuge-liang',
zhaoYun: 'portrait-zhao-yun',
jiangWei: 'portrait-jiang-wei',
simaYi: 'portrait-sima-yi'
};
const portraitByUnitId: Record<string, PortraitKey> = {
'liu-bei': 'liuBei',
'guan-yu': 'guanYu',
'zhang-fei': 'zhangFei'
'zhang-fei': 'zhangFei',
'zhuge-liang': 'zhugeLiang',
'zhao-yun': 'zhaoYun',
'jiang-wei': 'jiangWei'
};
const campSupplies: CampSupplyDefinition[] = [

View File

@@ -7,7 +7,21 @@ import { palette } from '../ui/palette';
const portraitKeys: Record<PortraitKey, string> = {
liuBei: 'portrait-liu-bei',
guanYu: 'portrait-guan-yu',
zhangFei: 'portrait-zhang-fei'
zhangFei: 'portrait-zhang-fei',
zhugeLiang: 'portrait-zhuge-liang',
zhaoYun: 'portrait-zhao-yun',
jiangWei: 'portrait-jiang-wei',
simaYi: 'portrait-sima-yi'
};
const portraitBySpeaker: Record<string, PortraitKey> = {
: 'liuBei',
: 'guanYu',
: 'zhangFei',
: 'zhugeLiang',
: 'zhaoYun',
: 'jiangWei',
: 'simaYi'
};
type AlphaObject = Phaser.GameObjects.Image | Phaser.GameObjects.Rectangle | Phaser.GameObjects.Text;
@@ -57,7 +71,9 @@ export class StoryScene extends Phaser.Scene {
currentPageId: page?.id,
background: page?.background,
backgroundReady: page ? this.textures.exists(page.background) : false,
activeTexture: this.background?.texture.key ?? null
activeTexture: this.background?.texture.key ?? null,
portraitKey: page ? this.pagePortraitKey(page) ?? null : null,
portraitTextureKey: this.portrait?.visible ? this.portrait.texture.key : null
};
}
@@ -239,11 +255,13 @@ export class StoryScene extends Phaser.Scene {
this.applyBackground(page.background);
this.chapterText?.setText(page.chapter);
if (page.portrait) {
const portraitKey = this.pagePortraitKey(page);
if (portraitKey) {
this.portraitFrame?.setVisible(true);
this.portrait?.setVisible(true);
this.portraitDivider?.setVisible(true);
this.portrait?.setTexture(portraitKeys[page.portrait]);
this.portrait?.setTexture(portraitKeys[portraitKey]);
this.portrait?.setDisplaySize(128, 128);
this.nameText?.setPosition(270, this.scale.height - 210);
this.bodyText?.setPosition(270, this.scale.height - 160);
@@ -262,6 +280,10 @@ export class StoryScene extends Phaser.Scene {
this.progressText?.setText(`${this.pageIndex + 1} / ${this.pages.length} SPACE / ENTER`);
}
private pagePortraitKey(page: StoryPage) {
return page.portrait ?? (page.speaker ? portraitBySpeaker[page.speaker] : undefined);
}
private applyBackground(textureKey: string) {
if (!this.background) {
return;