Last active
October 5, 2024 02:52
-
-
Save jmschrack/54dc70fda8a8821d555b2907a5837e51 to your computer and use it in GitHub Desktop.
EZSpritesheet handler for PIXI.JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Assets, Spritesheet } from 'pixi.js' | |
| /** | |
| * | |
| * @param {EZAtlasData} EZAtlasData | |
| * @returns {SpritesheetDataExt} | |
| */ | |
| export function ConvertEZDataToPIXIData(EZAtlasData) { | |
| /**@type {SpritesheetDataExt} */ | |
| const atlasData = { | |
| frames: {}, | |
| meta: { | |
| image: EZAtlasData.sheet[0].source, | |
| format: 'RGBA8888', | |
| size: { | |
| w: EZAtlasData.sheet[0].width, | |
| h: EZAtlasData.sheet[0].height | |
| }, | |
| scale: 1 | |
| }, | |
| animations: {} | |
| }; | |
| EZAtlasData.animation.forEach(a => { | |
| atlasData.animations[a.name] = a.frame.map(f => `${a.name}_${f.index}`); | |
| a.frame.forEach(f => { | |
| atlasData.frames[`${a.name}_${f.index}`] = { | |
| frame: { x: f.x, y: f.y, w: f.w, h: f.h }, | |
| sourceSize: { w: f.w, h: f.h }, | |
| spriteSourceSize: { x: 0 - f.ox, y: 0 - f.oy, w: f.w, h: f.h }, | |
| time: f.ms | |
| } | |
| }) | |
| }) | |
| return atlasData; | |
| } | |
| /** | |
| * | |
| * @param {Spritesheet} spritesheet | |
| * @param {string} animationName | |
| * @returns {import('pixi.js').FrameObject[]} | |
| */ | |
| export function GetFrameObjects(spritesheet, animationName) { | |
| /**@type {SpritesheetDataExt} */ | |
| const atlasData = spritesheet.data; | |
| return atlasData.animations[animationName].map(f => ({ texture: spritesheet.textures[f], time: atlasData.frames[f].time })); | |
| } | |
| /** | |
| * @example | |
| * const atlasData=await (await fetch('spritesheet.json')).json(); | |
| * const spritesheet = new EZSpritesheet(atlasData); | |
| * await spritesheet.loadTextures(); | |
| * await spritesheet.parse(); | |
| * | |
| * const animatedSprite = new AnimatedSprite(spritesheet.getAnimation("animationName")); | |
| */ | |
| export class EZSpritesheet { | |
| /** | |
| * | |
| * @param {EZAtlasData} atlasData The json file data from the z64me/EzSpriteSheet tool | |
| * @param {string?} [hostname=''] The hostname to prepend to the source paths, | |
| * | |
| */ | |
| constructor(atlasData, hostname = '') { | |
| this.data = atlasData; | |
| this.hostname = hostname; | |
| this._textures = [] | |
| /**@type {SpritesheetDataExt[]} */ | |
| this._atlases = [] | |
| } | |
| /** | |
| * Loads all textures referenced by the atlasData | |
| */ | |
| async loadTextures() { | |
| this._textures = await Promise.all(this.data.sheet.map(async s => { | |
| const t = await Assets.load(`${this.hostname}${s.source}`); | |
| return t; | |
| })); | |
| } | |
| /** | |
| * Parses the atlasData into PIXI SpritesheetData and Spritesheet objects | |
| */ | |
| async parse() { | |
| if(this._textures.length===0) await this.loadTextures(); | |
| this._atlases = this.data.sheet.map(s => ({ | |
| frames: {}, | |
| meta: { | |
| image: s.source, | |
| format: 'RGBA8888', | |
| size: { w: s.width, h: s.height }, | |
| scale: 1 | |
| }, | |
| animations: {} | |
| })) | |
| this.data.animation.forEach((anim, i) => { | |
| anim.frame.forEach((f, j) => { | |
| this._atlases[f.sheet].frames[`${anim.name}_${j}`] = { frame: { x: f.x, y: f.y, w: f.w, h: f.h }, sourceSize: { w: f.w, h: f.h }, spriteSourceSize: { x: 0 - f.ox, y: 0 - f.oy, w: f.w, h: f.h } } | |
| }) | |
| }) | |
| this._spritesheets = this._atlases.map((a, i) => new Spritesheet(this._textures[i], a)) | |
| await Promise.all(this._spritesheets.map(async s => await s.parse())) | |
| } | |
| /** | |
| * Returns an array of FrameObjects for the given animation name to be used to create an AnimatedSprite | |
| * @param {string} name | |
| * @returns {import('pixi.js').FrameObject[]} | |
| * | |
| * @example | |
| * const animatedSprite = new AnimatedSprite(spritesheet.getAnimation("animationName")); | |
| */ | |
| getAnimation(name) { | |
| const animData = this.data.animation.find(a => a.name === name); | |
| return animData.frame.map((f, i) => ({ texture: this._spritesheets[f.sheet].textures[`${name}_${i}`], time: f.ms })) | |
| } | |
| } | |
| /** | |
| * @typedef {import('pixi.js').SpritesheetData} SpritesheetDataPixi | |
| * | |
| * @typedef {import('pixi.js').SpritesheetData} SpritesheetFrameDataPixi | |
| */ | |
| /** | |
| * @typedef {Object} EZAtlasData | |
| * @property {number} sheets | |
| * @property {number} animations | |
| * @property {Sheet[]} sheet | |
| * @property {EZAnimation[]} animation | |
| */ | |
| /** | |
| * @typedef {Object} Sheet | |
| * @property {number} index | |
| * @property {number} width | |
| * @property {number} height | |
| * @property {string} source | |
| */ | |
| /** | |
| * @typedef {Object} EZAnimation | |
| * @property {string} name | |
| * @property {number} frames | |
| * @property {number} ms | |
| * @property {Frame[]} frame | |
| */ | |
| /** | |
| * @typedef {Object} Frame | |
| * @property {number} index | |
| * @property {number} sheet | |
| * @property {number} x | |
| * @property {number} y | |
| * @property {number} w | |
| * @property {number} h | |
| * @property {number} ox | |
| * @property {number} oy | |
| * @property {number} ms | |
| * @property {number} rot | |
| */ | |
| /** | |
| * @typedef {Object} SpritesheetDataExt | |
| * @extends SpritesheetDataPixi | |
| * @property {Dict<SpritesheetFrameDataExt>} frames | |
| */ | |
| /** | |
| * @typedef {SpritesheetFrameDataPixi} SpritesheetFrameDataExt | |
| * @property {number} time | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment