Add Wuzhang finale and lazy unit loading
This commit is contained in:
127
src/game/data/unitAssets.ts
Normal file
127
src/game/data/unitAssets.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import Phaser from 'phaser';
|
||||
|
||||
export type UnitDirection = 'south' | 'east' | 'north' | 'west';
|
||||
|
||||
const unitWalkFrameCount = 4;
|
||||
export const unitSheetFrameSize = 313;
|
||||
const unitWalkFrameRate = 8;
|
||||
const unitIdleFrameRate = 4;
|
||||
|
||||
const unitSheetRows: Record<UnitDirection, number> = {
|
||||
south: 0,
|
||||
east: 1,
|
||||
north: 2,
|
||||
west: 3
|
||||
};
|
||||
|
||||
type UnitSheetAsset = {
|
||||
key: string;
|
||||
url: string;
|
||||
actionKey: string;
|
||||
actionUrl: string;
|
||||
};
|
||||
|
||||
const unitSheetModules = import.meta.glob('../../assets/images/units/unit-*.png', {
|
||||
eager: true,
|
||||
import: 'default'
|
||||
}) as Record<string, string>;
|
||||
|
||||
function textureKeyFromPath(path: string) {
|
||||
const fileName = path.split('/').pop() ?? path;
|
||||
return fileName.replace(/\.png$/i, '');
|
||||
}
|
||||
|
||||
const unitSheetUrls = Object.fromEntries(
|
||||
Object.entries(unitSheetModules).map(([path, url]) => [textureKeyFromPath(path), url])
|
||||
);
|
||||
|
||||
const unitSheets = Object.entries(unitSheetUrls)
|
||||
.filter(([key]) => !key.endsWith('-actions'))
|
||||
.map(([key, url]) => ({
|
||||
key,
|
||||
url,
|
||||
actionKey: `${key}-actions`,
|
||||
actionUrl: unitSheetUrls[`${key}-actions`]
|
||||
}))
|
||||
.filter((sheet): sheet is UnitSheetAsset => Boolean(sheet.actionUrl))
|
||||
.sort((left, right) => left.key.localeCompare(right.key));
|
||||
|
||||
const unitSheetAssetsByKey = new Map(unitSheets.map((sheet) => [sheet.key, sheet]));
|
||||
|
||||
export function unitTextureVariantKeys(baseKey: string) {
|
||||
const prefix = `${baseKey}-`;
|
||||
const keys = unitSheets
|
||||
.map((sheet) => sheet.key)
|
||||
.filter((key) => key === baseKey || key.startsWith(prefix))
|
||||
.sort();
|
||||
|
||||
return keys.length > 0 ? keys : [baseKey];
|
||||
}
|
||||
|
||||
export function loadUnitSheets(scene: Phaser.Scene, keys: Iterable<string>, onReady: () => void) {
|
||||
const uniqueKeys = Array.from(new Set(keys));
|
||||
const missingSheets = uniqueKeys
|
||||
.filter((key) => !scene.textures.exists(key) || !scene.textures.exists(`${key}-actions`))
|
||||
.map((key) => unitSheetAssetsByKey.get(key) ?? missingUnitSheet(key));
|
||||
|
||||
if (missingSheets.length <= 0) {
|
||||
onReady();
|
||||
return;
|
||||
}
|
||||
|
||||
scene.load.once('complete', onReady);
|
||||
missingSheets.forEach(({ key, url, actionKey, actionUrl }) => {
|
||||
if (!scene.textures.exists(key)) {
|
||||
scene.load.spritesheet(key, url, {
|
||||
frameWidth: unitSheetFrameSize,
|
||||
frameHeight: unitSheetFrameSize
|
||||
});
|
||||
}
|
||||
if (!scene.textures.exists(actionKey)) {
|
||||
scene.load.spritesheet(actionKey, actionUrl, {
|
||||
frameWidth: unitSheetFrameSize,
|
||||
frameHeight: unitSheetFrameSize
|
||||
});
|
||||
}
|
||||
});
|
||||
scene.load.start();
|
||||
}
|
||||
|
||||
export function ensureUnitAnimations(scene: Phaser.Scene, keys: Iterable<string>) {
|
||||
Array.from(new Set(keys)).forEach((key) => {
|
||||
if (!scene.textures.exists(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(['south', 'east', 'north', 'west'] as UnitDirection[]).forEach((direction) => {
|
||||
const frames = Array.from({ length: unitWalkFrameCount }, (_, frameIndex) => ({
|
||||
key,
|
||||
frame: unitSheetRows[direction] * unitWalkFrameCount + frameIndex
|
||||
}));
|
||||
const walkAnimationKey = `${key}-walk-${direction}`;
|
||||
const idleAnimationKey = `${key}-idle-${direction}`;
|
||||
|
||||
if (!scene.anims.exists(walkAnimationKey)) {
|
||||
scene.anims.create({
|
||||
key: walkAnimationKey,
|
||||
frames,
|
||||
frameRate: unitWalkFrameRate,
|
||||
repeat: -1
|
||||
});
|
||||
}
|
||||
|
||||
if (!scene.anims.exists(idleAnimationKey)) {
|
||||
scene.anims.create({
|
||||
key: idleAnimationKey,
|
||||
frames,
|
||||
frameRate: unitIdleFrameRate,
|
||||
repeat: -1
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function missingUnitSheet(key: string): never {
|
||||
throw new Error(`Missing unit sheet asset for ${key}`);
|
||||
}
|
||||
Reference in New Issue
Block a user