excaliburjs/excalibur-aseprite

Add a way to get a new spritesheet/animation reference from resource

mattjennings opened this issue · 3 comments

Context

Consider a scenario in which you are reusing an animation from the same Aseprite resource on multiple actors. The animation returned from getAnimation() is shared, so the playback state is also shared across all actors using the same Aseprite resource.

https://codesandbox.io/s/excalibur-aseprite-shared-animation-reference-wjhuo8?file=/index.js

In the above example, there are 2 actors that should start on different frames of the same animation. Without the commented workaround, they share the animation state.

Proposal

Accept a parameter in resource.getAnimation() or getSpritesheet() that returns a new instance of the spritesheet or animation.

resource.getAnimation('abc', true)
resource.getSpriteSheet(true).getAnimation('abc')

I prefer the former, but I think having both would be good if you ever need the actual spritesheet reference too.

I'm happy to make a PR for this. I'm just unsure what to call the parameter. new is a keyword so probably not that. recreate?

@mattjennings Good find! This could definitely be a problem.

As a workaround you should be able to call ex.Animation.clone() to make a new copy. Unfortunately I don't think ex.SpriteSheet has a clone method (yet, but I'd also support adding one there).

I'd support a PR for a feature like this, I think supporting both getting a new copy of an ex.Animation or ex.SpriteSheeet would be good too 👍

Perhaps the optional parameter could be called clone, copy or maybe newInstance?

oh! I didn't know there was a clone method on animations. In which case, since getAnimation().clone() would suffice, I think just adding the same method to ex.SpriteSheet would make more sense. And possibly also on the Aseprite resource itself?

ehh, it might get a little hacky trying to add clone() to AsepriteResource. This works, but is probably a bit forceful:

    public clone() {
        const clone = new AsepriteResource(this._resource.path, this.bustCache);        
        clone.data = this.data.clone(); // => AsepriteSpriteSheet.clone()
        clone.rawAseprite = this.rawAseprite;
        clone.image = this.image;

        return clone
    }