Expand campaign visual assets

This commit is contained in:
2026-06-25 10:52:16 +09:00
parent 30291fe0fa
commit 03ca89e03f
18 changed files with 254 additions and 300 deletions

View File

@@ -1,29 +1,10 @@
import Phaser from 'phaser';
import { soundDirector } from '../audio/SoundDirector';
import { storyBackgroundAssets } from '../data/storyAssets';
import { portraitKeyForSpeaker, portraitTextureKey } from '../data/portraitAssets';
import { storyBackgroundAssets, storyBackgroundKeysFor } from '../data/storyAssets';
import { prologuePages, type PortraitKey, type StoryPage } from '../data/scenario';
import { palette } from '../ui/palette';
const portraitKeys: Record<PortraitKey, string> = {
liuBei: 'portrait-liu-bei',
guanYu: 'portrait-guan-yu',
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;
type StorySceneData = {
@@ -69,8 +50,9 @@ export class StoryScene extends Phaser.Scene {
pageIndex: this.pageIndex,
totalPages: this.pages.length,
currentPageId: page?.id,
background: page?.background,
backgroundReady: page ? this.textures.exists(page.background) : false,
requestedBackground: page?.background,
background: page ? this.pageBackgroundKey(page) : undefined,
backgroundReady: page ? this.textures.exists(this.pageBackgroundKey(page)) : false,
activeTexture: this.background?.texture.key ?? null,
portraitKey: page ? this.pagePortraitKey(page) ?? null : null,
portraitTextureKey: this.portrait?.visible ? this.portrait.texture.key : null
@@ -93,7 +75,7 @@ export class StoryScene extends Phaser.Scene {
this.ensureStoryBackgroundsLoaded(() => {
this.loadingText?.destroy();
this.loadingText = undefined;
this.background = this.add.image(width / 2, height / 2, this.resolveBackgroundKey(this.pages[0].background));
this.background = this.add.image(width / 2, height / 2, this.resolveBackgroundKey(this.pageBackgroundKey(this.pages[0])));
this.drawSceneShade(width, height);
this.drawDialogPanel(width, height);
this.showPage(0, true);
@@ -105,7 +87,8 @@ export class StoryScene extends Phaser.Scene {
}
private ensureStoryBackgroundsLoaded(onReady: () => void) {
const missingKeys = Array.from(new Set(this.pages.map((page) => page.background))).filter((key) => !this.textures.exists(key));
const requestedKeys = this.pages.flatMap((page) => storyBackgroundKeysFor(page.background));
const missingKeys = Array.from(new Set(requestedKeys)).filter((key) => !this.textures.exists(key));
const loadableKeys = missingKeys.filter((key) => storyBackgroundAssets[key]);
missingKeys
@@ -252,16 +235,17 @@ export class StoryScene extends Phaser.Scene {
private applyPage(page: StoryPage) {
soundDirector.playMusic(page.bgm);
this.applyBackground(page.background);
this.applyBackground(page);
this.chapterText?.setText(page.chapter);
const portraitKey = this.pagePortraitKey(page);
const textureKey = portraitKey ? portraitTextureKey(portraitKey) : undefined;
if (portraitKey) {
if (textureKey && this.textures.exists(textureKey)) {
this.portraitFrame?.setVisible(true);
this.portrait?.setVisible(true);
this.portraitDivider?.setVisible(true);
this.portrait?.setTexture(portraitKeys[portraitKey]);
this.portrait?.setTexture(textureKey);
this.portrait?.setDisplaySize(128, 128);
this.nameText?.setPosition(270, this.scale.height - 210);
this.bodyText?.setPosition(270, this.scale.height - 160);
@@ -281,16 +265,25 @@ export class StoryScene extends Phaser.Scene {
}
private pagePortraitKey(page: StoryPage) {
return page.portrait ?? (page.speaker ? portraitBySpeaker[page.speaker] : undefined);
return page.portrait ?? portraitKeyForSpeaker(page.speaker);
}
private applyBackground(textureKey: string) {
private pageBackgroundKey(page: StoryPage) {
const keys = storyBackgroundKeysFor(page.background).filter((key) => this.textures.exists(key));
if (keys.length <= 1) {
return keys[0] ?? page.background;
}
return keys[this.hashString(page.id) % keys.length];
}
private applyBackground(page: StoryPage) {
if (!this.background) {
return;
}
const { width, height } = this.scale;
const safeTextureKey = this.resolveBackgroundKey(textureKey);
const safeTextureKey = this.resolveBackgroundKey(this.pageBackgroundKey(page));
const source = this.textures.get(safeTextureKey).getSourceImage();
const imageWidth = source.width;
const imageHeight = source.height;
@@ -318,6 +311,14 @@ export class StoryScene extends Phaser.Scene {
return this.textures.exists(textureKey) ? textureKey : 'story-fallback';
}
private hashString(value: string) {
let hash = 0;
for (let index = 0; index < value.length; index += 1) {
hash = (hash * 31 + value.charCodeAt(index)) >>> 0;
}
return hash;
}
private advance() {
if (this.transitioning) {
return;