Skip to content

Instantly share code, notes, and snippets.

@connorjclark
Last active January 9, 2024 19:16
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save connorjclark/270558f27130a37747eeccb015232691 to your computer and use it in GitHub Desktop.
pixi.js import aseprite data
import * as PIXI from 'pixi.js';
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST
const app = new PIXI.Application();
app.renderer.backgroundColor = 0xaaaaaa;
document.body.appendChild(app.view);
class MultiAnimatedSprite extends PIXI.Container {
private currentAnimation: string;
private spritesheet: PIXI.Spritesheet;
private sprite: PIXI.AnimatedSprite;
constructor(spritesheet: PIXI.Spritesheet) {
super();
this.spritesheet = spritesheet;
this.scale.x = this.scale.y = 2;
const defaultAnimation = Object.keys(spritesheet.animations)[0];
this.setAnimation(defaultAnimation);
}
setAnimation(name: string) {
if (this.currentAnimation === name) return;
const textures = this.spritesheet.animations[name];
if (!this.sprite) {
this.sprite = new PIXI.AnimatedSprite(textures);
this.addChild(this.sprite);
} else {
this.sprite.textures = textures;
}
this.sprite.animationSpeed = 1;
this.sprite.play();
this.currentAnimation = name;
}
}
const state = {
keys: {},
maid: null,
}
document.body.onkeydown = (e) => {
state.keys[e.code] = true;
};
document.body.onkeyup = (e) => {
delete state.keys[e.code];
};
function tick() {
if (state.keys['Space']) {
state.maid.setAnimation('Attack');
} else {
state.maid.setAnimation('Idle');
}
}
app.loader
.use((resource, next) => {
if (resource.extension === 'json' && resource.data.meta.app === 'http://www.aseprite.org/') {
for (const tag of resource.data.meta.frameTags) {
const frames = [];
for (let i = tag.from; i < tag.to; i++) {
frames.push({ texture: resource.textures[i], time: resource.data.frames[i].duration });
}
if (tag.direction === 'pingpong') {
for (let i = tag.to; i >= tag.from; i--) {
frames.push({ texture: resource.textures[i], time: resource.data.frames[i].duration });
}
}
resource.spritesheet.animations[tag.name] = frames;
}
}
next();
})
.add('maid', 'gfx/maid.json').load((loader, resources) => {
const maid = state.maid = new MultiAnimatedSprite(resources.maid.spritesheet);
maid.x = app.renderer.width / 2;
maid.y = app.renderer.height / 2;
app.stage.addChild(maid);
app.ticker.add(tick);
});
@KashubaK
Copy link

KashubaK commented Jun 5, 2022

Thank you for writing the animation parser!

If anyone finds this from the Asperite forums, here's an improved loader middleware that fixes a bug with pingpong animations:

export function parseAsperiteAnimationSheet(resource: PIXI.LoaderResource, next: () => void) {
  if (resource.extension === 'json' && resource.data.meta.app === 'https://www.aseprite.org/') {
    if (!resource.spritesheet) {
      throw new Error('Imported resource is not a spritesheet');
    }

    if (!resource.textures) {
      throw new Error('Sprite sheet does not contain textures');
    }

    if (!(resource.data.frames instanceof Array)) {
      console.warn('Cannot parse animations unless spritesheet frames are exported as an Array, not a Hash')
      next();
      return;
    }

    for (const tag of resource.data.meta.frameTags) {
      const frames: any[] = [];

      for (let i = tag.from; i < tag.to; i++) {
        frames.push({ texture: resource.textures[i], time: resource.data.frames[i].duration });
      }

      if (tag.direction === 'pingpong') {
        for (let i = tag.to; i > tag.from; i--) {
          frames.push({ texture: resource.textures[i], time: resource.data.frames[i].duration });
        }
      }

      resource.spritesheet.animations[tag.name] = frames;
    }
  }

  next();
}

The bug was in this for loop:

for (let i = tag.to; i >= tag.from; i--)

It was duplicating the first frame of the animation. The bug is fixed by changing i >= tag.from to i > tag.from as the first loop already adds the first frame.

Also, the latest version of Asperite uses https in the meta.app property.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment