Improvements
This commit is contained in:
parent
5ca41cfd38
commit
36c9522e8a
@ -76,12 +76,8 @@ export default class SpriteUpdateEvent extends BaseEvent {
|
|||||||
if (actionData.sprites.length === 0) continue
|
if (actionData.sprites.length === 0) continue
|
||||||
|
|
||||||
// Generate and save the sprite sheet
|
// Generate and save the sprite sheet
|
||||||
const frameSize = await this.generateAndSaveSpriteSheet(
|
const frameDimensions = await this.generateAndSaveSpriteSheet(actionData.sprites, sprite.getId(), actionData.action)
|
||||||
actionData.sprites,
|
if (!frameDimensions) return false
|
||||||
sprite.getId(),
|
|
||||||
actionData.action
|
|
||||||
)
|
|
||||||
if (!frameSize) return false
|
|
||||||
|
|
||||||
// Create and save sprite action
|
// Create and save sprite action
|
||||||
const spriteAction = new SpriteAction()
|
const spriteAction = new SpriteAction()
|
||||||
@ -89,13 +85,13 @@ export default class SpriteUpdateEvent extends BaseEvent {
|
|||||||
sprite.getSpriteActions().add(spriteAction)
|
sprite.getSpriteActions().add(spriteAction)
|
||||||
|
|
||||||
spriteAction
|
spriteAction
|
||||||
.setAction(actionData.action)
|
.setAction(actionData.action)
|
||||||
.setSprites(actionData.sprites)
|
.setSprites(actionData.sprites)
|
||||||
.setOriginX(actionData.originX)
|
.setOriginX(actionData.originX)
|
||||||
.setOriginY(actionData.originY)
|
.setOriginY(actionData.originY)
|
||||||
.setFrameWidth(frameSize.width)
|
.setFrameWidth(frameDimensions.frameWidth)
|
||||||
.setFrameHeight(frameSize.height)
|
.setFrameHeight(frameDimensions.frameHeight)
|
||||||
.setFrameRate(actionData.frameRate)
|
.setFrameRate(actionData.frameRate)
|
||||||
|
|
||||||
await this.spriteRepository.getEntityManager().persistAndFlush(spriteAction)
|
await this.spriteRepository.getEntityManager().persistAndFlush(spriteAction)
|
||||||
}
|
}
|
||||||
@ -107,77 +103,93 @@ export default class SpriteUpdateEvent extends BaseEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateAndSaveSpriteSheet(
|
private async generateAndSaveSpriteSheet(sprites: SpriteImage[], spriteId: string, action: string): Promise<{ frameWidth: number; frameHeight: number } | null> {
|
||||||
sprites: SpriteImage[],
|
|
||||||
spriteId: string,
|
|
||||||
action: string
|
|
||||||
): Promise<{ width: number, height: number } | null> {
|
|
||||||
try {
|
try {
|
||||||
if (sprites.length === 0) return { width: 0, height: 0 }
|
if (sprites.length === 0) return { frameWidth: 0, frameHeight: 0 }
|
||||||
|
|
||||||
// Extract image data from sprites
|
// Extract image data and get image metadata
|
||||||
const imageBuffers = await Promise.all(
|
const imagesData = await Promise.all(
|
||||||
sprites.map(sprite => {
|
sprites.map(async (sprite) => {
|
||||||
const base64Data = sprite.url.split(';base64,').pop()
|
const base64Data = sprite.url.split(';base64,').pop()
|
||||||
if (!base64Data) throw new Error('Invalid base64 image')
|
if (!base64Data) throw new Error('Invalid base64 image')
|
||||||
return Buffer.from(base64Data, 'base64')
|
const buffer = Buffer.from(base64Data, 'base64')
|
||||||
})
|
const metadata = await sharp(buffer).metadata()
|
||||||
|
|
||||||
|
return {
|
||||||
|
buffer,
|
||||||
|
width: metadata.width || 0,
|
||||||
|
height: metadata.height || 0
|
||||||
|
}
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get metadata for all images to find the maximum dimensions
|
// Skip creation if any image has invalid dimensions
|
||||||
const metadataList = await Promise.all(
|
if (imagesData.some((data) => data.width === 0 || data.height === 0)) {
|
||||||
imageBuffers.map(buffer => sharp(buffer).metadata())
|
console.error('One or more sprites have invalid dimensions')
|
||||||
)
|
|
||||||
|
|
||||||
// Calculate the maximum width and height across all frames
|
|
||||||
const maxWidth = Math.max(...metadataList.map(meta => meta.width || 0))
|
|
||||||
const maxHeight = Math.max(...metadataList.map(meta => meta.height || 0))
|
|
||||||
|
|
||||||
// Skip creation if we couldn't determine dimensions
|
|
||||||
if (maxWidth === 0 || maxHeight === 0) {
|
|
||||||
console.error('Could not determine sprite dimensions')
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize all frames to the same dimensions
|
// Calculate the maximum width and height to use for all frames
|
||||||
const resizedFrames = await Promise.all(
|
const maxWidth = Math.max(...imagesData.map((data) => data.width))
|
||||||
imageBuffers.map(async (buffer) => {
|
const maxHeight = Math.max(...imagesData.map((data) => data.height))
|
||||||
return sharp(buffer)
|
|
||||||
.resize({
|
// Create frames of uniform size with the original sprites centered
|
||||||
width: maxWidth,
|
const uniformFrames = await Promise.all(
|
||||||
height: maxHeight,
|
imagesData.map(async (imageData) => {
|
||||||
fit: 'contain',
|
// Calculate centering offsets to position the sprite in the middle of the frame
|
||||||
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
const xOffset = Math.floor((maxWidth - imageData.width) / 2)
|
||||||
})
|
const yOffset = Math.floor((maxHeight - imageData.height) / 2)
|
||||||
.toBuffer()
|
|
||||||
|
// Create a uniform-sized frame with the sprite centered
|
||||||
|
return sharp({
|
||||||
|
create: {
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
channels: 4,
|
||||||
|
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
.composite([
|
||||||
|
{
|
||||||
|
input: imageData.buffer,
|
||||||
|
left: xOffset,
|
||||||
|
top: yOffset
|
||||||
|
}
|
||||||
|
])
|
||||||
|
.png()
|
||||||
|
.toBuffer()
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create sprite sheet with uniformly sized frames
|
// Create the sprite sheet with uniform frames
|
||||||
const spriteSheet = await sharp({
|
const spriteSheet = await sharp({
|
||||||
create: {
|
create: {
|
||||||
width: maxWidth * resizedFrames.length,
|
width: maxWidth * uniformFrames.length,
|
||||||
height: maxHeight,
|
height: maxHeight,
|
||||||
channels: 4,
|
channels: 4,
|
||||||
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.composite(
|
.composite(
|
||||||
resizedFrames.map((buffer, index) => ({
|
uniformFrames.map((buffer, index) => ({
|
||||||
input: buffer,
|
input: buffer,
|
||||||
left: index * maxWidth,
|
left: index * maxWidth,
|
||||||
top: 0
|
top: 0
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
.png()
|
.png()
|
||||||
.toBuffer()
|
.toBuffer()
|
||||||
|
|
||||||
// Save sprite sheet
|
// Save sprite sheet
|
||||||
const dir = `public/sprites/${spriteId}`
|
const dir = `public/sprites/${spriteId}`
|
||||||
await fs.promises.mkdir(dir, { recursive: true })
|
await fs.promises.mkdir(dir, { recursive: true })
|
||||||
await fs.promises.writeFile(`${dir}/${action}.png`, spriteSheet)
|
await fs.promises.writeFile(`${dir}/${action}.png`, spriteSheet)
|
||||||
|
|
||||||
return { width: maxWidth, height: maxHeight }
|
// Return the uniform frame dimensions
|
||||||
|
return {
|
||||||
|
frameWidth: maxWidth,
|
||||||
|
frameHeight: maxHeight
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error generating sprite sheet:', error)
|
console.error('Error generating sprite sheet:', error)
|
||||||
return null
|
return null
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import serverConfig from '@/application/config'
|
import serverConfig from '@/application/config'
|
||||||
import { Migrator } from '@mikro-orm/migrations'
|
import { Migrator } from '@mikro-orm/migrations'
|
||||||
// import { defineConfig, MariaDbDriver } from '@mikro-orm/mariadb'
|
import { defineConfig, MariaDbDriver } from '@mikro-orm/mariadb'
|
||||||
import { defineConfig, MySqlDriver } from '@mikro-orm/mysql'
|
// import { defineConfig, MySqlDriver } from '@mikro-orm/mysql'
|
||||||
import { TsMorphMetadataProvider } from '@mikro-orm/reflection'
|
import { TsMorphMetadataProvider } from '@mikro-orm/reflection'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@ -9,7 +9,7 @@ export default defineConfig({
|
|||||||
metadataProvider: TsMorphMetadataProvider,
|
metadataProvider: TsMorphMetadataProvider,
|
||||||
entities: ['./src/entities/*.ts'],
|
entities: ['./src/entities/*.ts'],
|
||||||
entitiesTs: ['./src/entities/*.ts'],
|
entitiesTs: ['./src/entities/*.ts'],
|
||||||
driver: MySqlDriver,
|
driver: MariaDbDriver,
|
||||||
host: serverConfig.DB_HOST,
|
host: serverConfig.DB_HOST,
|
||||||
port: serverConfig.DB_PORT,
|
port: serverConfig.DB_PORT,
|
||||||
user: serverConfig.DB_USER,
|
user: serverConfig.DB_USER,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user