dynamic-loader-plugin
Version:
Dynamic asset loader for Phaser 3 with priority-based loading
134 lines (133 loc) • 5.88 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SceneLoader = void 0;
const phaser_1 = __importDefault(require("phaser"));
class SceneLoader extends phaser_1.default.Events.EventEmitter {
constructor(scene, options) {
super();
this.loadedPriorities = new Set();
this.totalAssetsToLoad = 0;
this.loadedAssetCount = 0;
this.sceneAssetCounts = new Map();
this.sceneLoadedCounts = new Map();
this.handleFileComplete = (key) => {
this.loadedAssetCount++;
const sceneName = this.findSceneForKey(key);
if (sceneName) {
const loaded = (this.sceneLoadedCounts.get(sceneName) || 0) + 1;
const total = this.sceneAssetCounts.get(sceneName) || 1;
this.sceneLoadedCounts.set(sceneName, loaded);
const sceneProgress = Math.floor((loaded / total) * 100);
this.emit("scene-progress", { scene: sceneName, progress: sceneProgress });
if (loaded === total) {
this.emit("scene-complete", sceneName);
}
}
const overallProgress = Math.floor((this.loadedAssetCount / this.totalAssetsToLoad) * 100);
this.emit("overall-progress", overallProgress);
};
this.scene = scene;
this.basePath = options.assetBasePath || ""; // e.g., "assets/"
this.manifestPath = options.manifestPath;
}
/** Must be called before any loading happens */
init() {
return __awaiter(this, void 0, void 0, function* () {
this.manifest = yield this.loadManifest(this.manifestPath);
});
}
loadManifest(manifestPath) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield fetch(manifestPath);
if (!response.ok) {
throw new Error(`Failed to fetch manifest from ${manifestPath}`);
}
return yield response.json();
});
}
loadAssetsByPriority(priority, onComplete) {
if (!this.manifest) {
console.error("Manifest not loaded. Call await loader.init() first.");
return;
}
if (this.loadedPriorities.has(priority)) {
console.warn(`Priority ${priority} already loaded.`);
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
return;
}
const assetsByScene = {};
for (const [sceneName, sceneData] of Object.entries(this.manifest.scenes)) {
if (sceneData.priority === priority) {
assetsByScene[sceneName] = sceneData.assets;
}
}
const allAssets = Object.values(assetsByScene).flat();
if (allAssets.length === 0) {
console.warn(`No assets found for priority ${priority}`);
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
return;
}
this.totalAssetsToLoad = allAssets.length;
this.loadedAssetCount = 0;
this.sceneAssetCounts.clear();
this.sceneLoadedCounts.clear();
for (const sceneName in assetsByScene) {
this.sceneAssetCounts.set(sceneName, assetsByScene[sceneName].length);
this.sceneLoadedCounts.set(sceneName, 0);
}
this.scene.load.on("filecomplete", this.handleFileComplete);
this.scene.load.on("complete", () => {
this.scene.load.off("filecomplete", this.handleFileComplete);
this.loadedPriorities.add(priority);
this.emit("overall-progress", 100);
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
});
for (const asset of allAssets) {
this.loadAsset(asset);
}
this.scene.load.start();
}
findSceneForKey(key) {
for (const [sceneName, sceneData] of Object.entries(this.manifest.scenes)) {
if (sceneData.assets.some(a => a.key === key)) {
return sceneName;
}
}
return null;
}
loadAsset(asset) {
const key = asset.key;
switch (asset.type) {
case "image":
case "audio":
case "json":
this.scene.load[asset.type](key, `${this.basePath}/${asset.path}`);
break;
case "spritesheet":
if (!asset.frameConfig) {
throw new Error(`Missing frameConfig for spritesheet: ${key}`);
}
this.scene.load.spritesheet(key, `${this.basePath}/${asset.path}`, asset.frameConfig);
break;
case "atlas":
this.scene.load.atlas(key, `${this.basePath}/${asset.imagePath}`, `${this.basePath}/${asset.jsonPath}`);
break;
default:
const neverAsset = asset;
console.warn("Unhandled asset type:", neverAsset);
}
}
}
exports.SceneLoader = SceneLoader;