constructor(x, y, settings) {
		// call the super constructor
		super(x, y, 0, 0);

		/**
		 * @type {boolean}
		 * @default false
		 */
		this.animationpause = false;

		/**
		 * animation cycling speed (delay between frame in ms)
		 * @type {number}
		 * @default 100
		 */
		this.animationspeed = 100;

		/**
		 * global offset for the position to draw from on the source image.
		 * @type {Vector2d}
		 * @default <0.0,0.0>
		 */
		this.offset = vector2dPool.get(0, 0);

		/**
		 * true if this is a video sprite (e.g. a HTMLVideoElement was passed as as source)
		 * @type {boolean}
		 * @default false
		 */
		this.isVideo = false;

		/**
		 * a callback fired when the end of a video or current animation was reached
		 * @type {Function}
		 * @default undefined
		 */
		// this.onended;

		/**
		 * The source texture object this sprite object is using
		 * @type {TextureAtlas}
		 */
		this.source = null;

		// hold all defined animation
		this.anim = {};

		// a flag to reset animation
		this.resetAnim = undefined;

		// current frame information
		// (reusing current, any better/cleaner place?)
		this.current = {
			// the current animation name
			name: undefined,
			// length of the current animation name
			length: 0,
			//current frame texture offset
			offset: vector2dPool.get(0, 0),
			// current frame size
			width: 0,
			height: 0,
			// Source rotation angle for pre-rotating the source image
			angle: 0,
			// current frame index
			idx: 0,
		};

		// animation frame delta
		this.dt = 0;

		/**
		 * flicker settings
		 * @ignore
		 */
		this._flicker = {
			isFlickering: false,
			duration: 0,
			callback: null,
			state: false,
		};

		// set the proper image/texture to use
		if (settings.image instanceof TextureAtlas) {
			this.source = settings.image;
			this.image = this.source.getTexture();
			this.textureAtlas = settings.image;
			// check for defined region
			if (typeof settings.region !== "undefined") {
				// use a texture atlas
				const region = this.source.getRegion(settings.region);
				if (region) {
					// set the sprite region within the texture
					this.setRegion(region);
				} else {
					// throw an error
					throw new Error(
						"Texture - region for " + settings.region + " not found",
					);
				}
			}
		} else {
			// HTMLImageElement/HTMLVideoElementCanvas or {string}
			this.image =
				typeof settings.image === "object"
					? settings.image
					: getImage(settings.image);
			// throw an error if image ends up being null/undefined
			if (!this.image) {
				throw new Error(
					"me.Sprite: '" + settings.image + "' image/texture not found!",
				);
			}

			this.isVideo =
				globalThis.HTMLVideoElement &&
				this.image instanceof globalThis.HTMLVideoElement;

			if (this.isVideo) {
				this.width =
					this.current.width =
					settings.framewidth =
						settings.framewidth || this.image.videoWidth;
				this.height =
					this.current.height =
					settings.frameheight =
						settings.frameheight || this.image.videoHeight;
				// video specific parameter
				this.animationpause = this.image.autoplay !== true;
				if (this.animationpause) {
					this.image.pause();
				}

				/**
				 * pause the video when losing focus
				 * @ignore
				 */
				this.removeStatePauseListener = eventEmitter.addListener(
					"statePause",
					() => {
						this.image.pause();
					},
				);

				// call the onended when the video has ended
				this.image.onended = () => {
					if (typeof this.onended === "function") {
						// prevent the video from restarting if video.loop is false
						if (!this.image.loop) {
							this.animationpause = true;
						}
						this.onended();
					}
				};
			} else {
				// update the default "current" frame size
				this.width =
					this.current.width =
					settings.framewidth =
						settings.framewidth || this.image.width;
				this.height =
					this.current.height =
					settings.frameheight =
						settings.frameheight || this.image.height;
				this.source = renderer.cache.get(this.image, settings);
				this.textureAtlas = this.source.getAtlas();
			}
		}

		// store/reset the current atlas information if specified
		if (typeof settings.atlas !== "undefined") {
			this.textureAtlas = settings.atlas;
			this.atlasIndices = settings.atlasIndices;
		}

		// apply flip flags if specified
		if (typeof settings.flipX !== "undefined") {
			this.flipX(!!settings.flipX);
		}
		if (typeof settings.flipY !== "undefined") {
			this.flipY(!!settings.flipY);
		}

		// set the default rotation angle is defined in the settings
		// * WARNING: rotating sprites decreases performance with Canvas Renderer
		if (typeof settings.rotation !== "undefined") {
			this.rotate(settings.rotation);
		}

		// update anchorPoint
		if (settings.anchorPoint) {
			this.anchorPoint.set(settings.anchorPoint.x, settings.anchorPoint.y);
		}

		if (typeof settings.tint !== "undefined") {
			if (settings.tint instanceof Color) {
				this.tint.copy(settings.tint);
			} else {
				// string (#RGB, #ARGB, #RRGGBB, #AARRGGBB)
				this.tint.parseCSS(settings.tint);
			}
		}

		// set the sprite name if specified
		if (typeof settings.name === "string") {
			this.name = settings.name;
		}

		// displaying order
		if (typeof settings.z !== "undefined") {
			this.pos.z = settings.z;
		}

		// add predefined animations if defined (e.g. aseprite)
		if (typeof settings.anims !== "undefined") {
			for (const anim in settings.anims) {
				this.addAnimation(
					settings.anims[anim].name,
					settings.anims[anim].index,
					settings.anims[anim].speed,
				);
			}
		}

		// addAnimation will return 0 if no texture atlas is defined
		if (!this.isVideo && this.addAnimation("default", null) !== 0) {
			// set as default
			this.setCurrentAnimation("default");
		}
	}
@param {number} x - the x coordinates of the sprite object
@param {number} y - the y coordinates of the sprite object
@param {object} settings - Configuration parameters for the Sprite object
@param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|TextureAtlas|string} settings.image - reference to spritesheet image, a texture atlas, a video element, or to a texture atlas
@param {string} [settings.name=""] - name of this object
@param {string} [settings.region] - region name of a specific region to use when using a texture atlas, see {@link TextureAtlas}
@param {number} [settings.framewidth] - Width of a single frame within the spritesheet
@param {number} [settings.frameheight] - Height of a single frame within the spritesheet
@param {string|Color} [settings.tint] - a tint to be applied to this sprite
@param {number} [settings.flipX] - flip the sprite on the horizontal axis
@param {number} [settings.flipY] - flip the sprite on the vertical axis
@param {Vector2d} [settings.anchorPoint={x:0.5, y:0.5}] - Anchor point to draw the frame at (defaults to the center of the frame).
@example
// create a single sprite from a standalone image, with anchor in the center
let sprite = new me.Sprite(0, 0, {
    image : "PlayerTexture",
    framewidth : 64,
    frameheight : 64,
    anchorPoint : new me.Vector2d(0.5, 0.5)
});

// create a single sprite from a packed texture
mytexture = new me.TextureAtlas(
    me.loader.getJSON("texture"),
    me.loader.getImage("texture")
);
let sprite = new me.Sprite(0, 0, {
    image : mytexture,
    region : "npc2.png",
});

// create a video sprite
let videoSprite = new me.Sprite(0, 0, {
    image : me.loader.getVideo("bigbunny"),
    anchorPoint : new me.Vector2d(0.5, 0.5)
});
// scale the video sprite
videoSprite.currentTransform.scale(2);
// start playing the video (if video is preloaded with `autoplay` set to false)
videoSprite.play();