Optimize initial loading performance

This commit is contained in:
2026-06-27 07:49:38 +09:00
parent 88207c3b6f
commit b74332973b
14 changed files with 552 additions and 533 deletions

View File

@@ -1,9 +1,10 @@
import Phaser from 'phaser';
import { soundDirector } from '../audio/SoundDirector';
import { portraitKeyForSpeaker, portraitTextureKeysForKey } from '../data/portraitAssets';
import { portraitAssetEntriesForKey, portraitKeyForSpeaker, type PortraitAssetEntry } from '../data/portraitAssets';
import { storyBackgroundAssets, storyBackgroundKeysFor } from '../data/storyAssets';
import { prologuePages, type PortraitKey, type StoryPage } from '../data/scenario';
import { palette } from '../ui/palette';
import { startGameScene } from './lazyScenes';
type AlphaObject = Phaser.GameObjects.Image | Phaser.GameObjects.Rectangle | Phaser.GameObjects.Text;
@@ -72,7 +73,7 @@ export class StoryScene extends Phaser.Scene {
});
this.loadingText.setOrigin(0.5);
this.ensureStoryBackgroundsLoaded(() => {
this.ensureStoryAssetsLoaded(() => {
this.loadingText?.destroy();
this.loadingText = undefined;
this.background = this.add.image(width / 2, height / 2, this.resolveBackgroundKey(this.pageBackgroundKey(this.pages[0])));
@@ -86,16 +87,23 @@ export class StoryScene extends Phaser.Scene {
});
}
private ensureStoryBackgroundsLoaded(onReady: () => void) {
private ensureStoryAssetsLoaded(onReady: () => void) {
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]);
const missingPortraits = this.pages
.flatMap((page) => {
const entry = this.pagePortraitAssetEntry(page);
return entry ? [entry] : [];
})
.filter((entry, index, entries) => entries.findIndex((candidate) => candidate.textureKey === entry.textureKey) === index)
.filter((entry) => !this.textures.exists(entry.textureKey));
missingKeys
.filter((key) => !storyBackgroundAssets[key])
.forEach((key) => console.warn(`Missing story background asset for ${key}`));
if (loadableKeys.length === 0) {
if (loadableKeys.length === 0 && missingPortraits.length === 0) {
onReady();
return;
}
@@ -105,6 +113,7 @@ export class StoryScene extends Phaser.Scene {
console.warn(`Failed to load story background ${file.key}`);
});
loadableKeys.forEach((key) => this.load.image(key, storyBackgroundAssets[key]));
missingPortraits.forEach(({ textureKey, url }) => this.load.image(textureKey, url));
this.load.start();
}
@@ -159,7 +168,7 @@ export class StoryScene extends Phaser.Scene {
this.portraitFrame = this.add.rectangle(panelX + 86, panelY + 86, 136, 136, 0x090d12, 0.88);
this.portraitFrame.setStrokeStyle(2, palette.gold, 0.58);
this.portrait = this.add.image(panelX + 86, panelY + 86, 'portrait-liu-bei');
this.portrait = this.add.image(panelX + 86, panelY + 86, this.pagePortraitTextureKey(this.pages[0]) ?? 'story-fallback');
this.portrait.setDisplaySize(128, 128);
this.portraitDivider = this.add.rectangle(panelX + 166, panelY + 28, 1, panelH - 56, palette.gold, 0.22).setOrigin(0);
@@ -268,17 +277,22 @@ export class StoryScene extends Phaser.Scene {
}
private pagePortraitTextureKey(page: StoryPage) {
const entry = this.pagePortraitAssetEntry(page);
return entry && this.textures.exists(entry.textureKey) ? entry.textureKey : undefined;
}
private pagePortraitAssetEntry(page: StoryPage): PortraitAssetEntry | undefined {
const portraitKey = this.pagePortraitKey(page);
if (!portraitKey) {
return undefined;
}
const keys = portraitTextureKeysForKey(portraitKey).filter((key) => this.textures.exists(key));
if (keys.length <= 1) {
return keys[0];
const entries = portraitAssetEntriesForKey(portraitKey);
if (entries.length === 0) {
return undefined;
}
return keys[this.hashString(page.id) % keys.length];
return entries[this.hashString(page.id) % entries.length];
}
private pageBackgroundKey(page: StoryPage) {
@@ -338,7 +352,11 @@ export class StoryScene extends Phaser.Scene {
}
if (this.pageIndex >= this.pages.length - 1) {
this.scene.start(this.nextScene, this.nextSceneData);
this.transitioning = true;
void startGameScene(this, this.nextScene, this.nextSceneData).catch((error) => {
console.error(`Failed to start ${this.nextScene}`, error);
this.transitioning = false;
});
return;
}