diff --git a/src/events/gameMaster/assetManager/sprite/update.ts b/src/events/gameMaster/assetManager/sprite/update.ts index 7b3b319..4829b84 100644 --- a/src/events/gameMaster/assetManager/sprite/update.ts +++ b/src/events/gameMaster/assetManager/sprite/update.ts @@ -71,12 +71,43 @@ export default class SpriteUpdateEvent extends BaseEvent { await this.spriteRepository.getEntityManager().removeAndFlush(existingAction) } - // Process each action + // First pass: find the global maximum dimensions across all actions + let globalMaxWidth = 0 + let globalMaxHeight = 0 + + // Extract all image metadata to find global maximums for (const actionData of actionsData) { if (actionData.sprites.length === 0) continue - // Generate and save the sprite sheet - const frameDimensions = await this.generateAndSaveSpriteSheet(actionData.sprites, sprite.getId(), actionData.action) + const imagesData = await Promise.all( + actionData.sprites.map(async (sprite) => { + const base64Data = sprite.url.split(';base64,').pop() + if (!base64Data) throw new Error('Invalid base64 image') + const buffer = Buffer.from(base64Data, 'base64') + const metadata = await sharp(buffer).metadata() + + return { + width: metadata.width || 0, + height: metadata.height || 0 + } + }) + ) + + // Update global maximums with this action's maximums + const actionMaxWidth = Math.max(...imagesData.map((data) => data.width), 0) + const actionMaxHeight = Math.max(...imagesData.map((data) => data.height), 0) + + globalMaxWidth = Math.max(globalMaxWidth, actionMaxWidth) + globalMaxHeight = Math.max(globalMaxHeight, actionMaxHeight) + } + + // Process each action using the global maximum dimensions + for (const actionData of actionsData) { + if (actionData.sprites.length === 0) continue + + // Generate and save the sprite sheet using global dimensions + const frameDimensions = await this.generateAndSaveSpriteSheet(actionData.sprites, sprite.getId(), actionData.action, globalMaxWidth, globalMaxHeight) + if (!frameDimensions) return false // Create and save sprite action @@ -103,11 +134,11 @@ export default class SpriteUpdateEvent extends BaseEvent { } } - private async generateAndSaveSpriteSheet(sprites: SpriteImage[], spriteId: string, action: string): Promise<{ frameWidth: number; frameHeight: number } | null> { + private async generateAndSaveSpriteSheet(sprites: SpriteImage[], spriteId: string, action: string, maxWidth: number, maxHeight: number): Promise<{ frameWidth: number; frameHeight: number } | null> { try { if (sprites.length === 0) return { frameWidth: 0, frameHeight: 0 } - // Extract image data and get image metadata + // Extract image data const imagesData = await Promise.all( sprites.map(async (sprite) => { const base64Data = sprite.url.split(';base64,').pop() @@ -129,10 +160,6 @@ export default class SpriteUpdateEvent extends BaseEvent { return null } - // Calculate the maximum width and height to use for all frames - const maxWidth = Math.max(...imagesData.map((data) => data.width)) - const maxHeight = Math.max(...imagesData.map((data) => data.height)) - // Create frames of uniform size with the original sprites centered const uniformFrames = await Promise.all( imagesData.map(async (imageData) => { @@ -185,7 +212,7 @@ export default class SpriteUpdateEvent extends BaseEvent { await fs.promises.mkdir(dir, { recursive: true }) await fs.promises.writeFile(`${dir}/${action}.png`, spriteSheet) - // Return the uniform frame dimensions + // Return the uniform frame dimensions (now global maximum dimensions) return { frameWidth: maxWidth, frameHeight: maxHeight