setCurrentAnimation(name, resetAnim, preserve_dt = false) {
		if (typeof this.anim[name] !== "undefined") {
			if (!this.isCurrentAnimation(name)) {
				this.current.name = name;
				this.current.length = this.anim[this.current.name].length;
				if (typeof resetAnim === "string") {
					this.resetAnim = this.setCurrentAnimation.bind(
						this,
						resetAnim,
						null,
						true,
					);
				} else if (typeof resetAnim === "function") {
					this.resetAnim = resetAnim;
				} else {
					this.resetAnim = undefined;
				}
				this.setAnimationFrame(0);
				if (!preserve_dt) {
					this.dt = 0;
				}
				this.isDirty = true;
			}
		} else {
			throw new Error("animation id '" + name + "' not defined");
		}
		return this;
	}
set the current animation
this will always change the animation & set the frame to zero
@param {string} name - animation id
@param {string|Function} [resetAnim] - animation id to switch to when complete, or callback
@param {boolean} [preserve_dt=false] - if false will reset the elapsed time counter since last frame
@returns {Sprite} Reference to this object for method chaining
@example
// set "walk" animation
this.setCurrentAnimation("walk");

// set "walk" animation if it is not the current animation
if (this.isCurrentAnimation("walk")) {
    this.setCurrentAnimation("walk");
}

// set "eat" animation, and switch to "walk" when complete
this.setCurrentAnimation("eat", "walk");

// set "die" animation, and remove the object when finished
this.setCurrentAnimation("die", () => {
   world.removeChild(this);
   return false; // do not reset to first frame
});

// set "attack" animation, and pause for a short duration
this.setCurrentAnimation("die", () => {
   this.animationpause = true;

   // back to "standing" animation after 1 second
   setTimeout(function () {
       this.setCurrentAnimation("standing");
   }, 1000);

   return false; // do not reset to first frame
});