fertig-classic-games/src/services/assetLoader.js

66 lines
2.7 KiB
JavaScript

import { resolveGameAssets } from '../data/assetManifest.js';
// Lazy per-game asset loading. PreloadScene only loads shared assets at
// startup; each game's own art (see data/assetManifest.js) is loaded here,
// from GameRoomScene, the first time the user enters that game.
function isLoaded(scene, d) {
if (d.type === 'audio') return scene.cache.audio.exists(d.key);
if (d.type === 'json') return scene.cache.json.exists(d.key);
// Video lives in its own cache, not the texture manager.
if (d.type === 'video') return !!scene.cache.video?.exists(d.key);
return scene.textures.exists(d.key);
}
export function missingGameAssets(scene, slug) {
return resolveGameAssets(scene, slug).filter((d) => !isLoaded(scene, d));
}
function queueDescriptor(scene, d) {
if (d.type === 'spritesheet') {
scene.load.spritesheet(d.key, d.path, { frameWidth: d.frameWidth, frameHeight: d.frameHeight });
} else if (d.type === 'audio') {
scene.load.audio(d.key, d.path);
} else if (d.type === 'json') {
scene.load.json(d.key, d.path);
} else if (d.type === 'video') {
// noAudio: true — these are ambient portrait loops. It also lets them
// autoplay, which browsers refuse for anything with an audio track.
scene.load.video(d.key, d.path, true);
} else {
scene.load.image(d.key, d.path);
}
}
// Queue every missing asset for `slug` on the scene's loader without waiting
// for the load to finish. For use from a Scene's own preload() — a level
// editor booting straight out of PreloadScene, say — where Phaser starts the
// queued load automatically once preload() returns, so there's no need for
// the completion Promise below.
export function queueGameAssets(scene, slug) {
missingGameAssets(scene, slug).forEach((d) => queueDescriptor(scene, d));
}
// Queue and load every missing asset for `slug` on the scene's loader. Call
// from create() only (the loader is idle there). Resolves once the load pass
// completes; a failed file logs a warning and the game's usual
// textures.exists fallback applies.
export function ensureGameAssets(scene, slug, { onProgress } = {}) {
const missing = missingGameAssets(scene, slug);
if (missing.length === 0) return Promise.resolve(false);
for (const d of missing) queueDescriptor(scene, d);
return new Promise((resolve) => {
const onError = (file) => console.warn(`[assets] failed to load ${file.key} (${file.src})`);
if (onProgress) scene.load.on('progress', onProgress);
scene.load.on('loaderror', onError);
scene.load.once('complete', () => {
if (onProgress) scene.load.off('progress', onProgress);
scene.load.off('loaderror', onError);
resolve(true);
});
scene.load.start();
});
}