constructor(x, y, width, height) {
		// parent constructor
		super(x, y, width, height);

		/**
		 * Position of the Renderable relative to its parent container
		 * @public
		 * @type {ObservableVector3d}
		 */
		this.pos = new ObservableVector3d(x, y, 0, () => {
			this.updateBounds();
			this.isDirty = true;
		});

		/**
		 * The anchor point is used for attachment behavior, and/or when applying transformations.<br>
		 * The coordinate system places the origin at the top left corner of the frame (0, 0) and (1, 1) means the bottom-right corner<br>
		 * <img src="images/anchor_point.png"/><br>
		 * a Renderable's anchor point defaults to (0.5,0.5), which corresponds to the center position.<br>
		 * <br>
		 * <i><b>Note:</b> Object created through Tiled will have their anchorPoint set to (0, 0) to match Tiled Level editor implementation.
		 * To specify a value through Tiled, use a json expression like `json:{"x":0.5,"y":0.5}`. </i>
		 * @type {ObservablePoint}
		 * @default <0.5,0.5>
		 */
		this.anchorPoint = new ObservablePoint(0.5, 0.5, () => {
			this.updateBounds();
			this.isDirty = true;
		});

		if (typeof this.currentTransform === "undefined") {
			/**
			 * the renderable default transformation matrix
			 * @type {Matrix2d}
			 */
			this.currentTransform = matrix2dPool.get();
		}
		this.currentTransform.identity();

		/**
		 * the renderable physic body
		 * @type {Body}
		 * @example
		 *  // define a new Player Class
		 *  class PlayerEntity extends me.Sprite {
		 *      // constructor
		 *      constructor(x, y, settings) {
		 *          // call the parent constructor
		 *          super(x, y , settings);
		 *
		 *          // define a basic walking animation
		 *          this.addAnimation("walk",  [...]);
		 *          // define a standing animation (using the first frame)
		 *          this.addAnimation("stand",  [...]);
		 *          // set the standing animation as default
		 *          this.setCurrentAnimation("stand");
		 *
		 *          // add a physic body
		 *          this.body = new me.Body(this);
		 *          // add a default collision shape
		 *          this.body.addShape(new me.Rect(0, 0, this.width, this.height));
		 *          // configure max speed, friction, and initial force to be applied
		 *          this.body.setMaxVelocity(3, 15);
		 *          this.body.setFriction(0.4, 0);
		 *          this.body.force.set(3, 0);
		 *          this.isKinematic = false;
		 *
		 *          // set the display to follow our position on both axis
		 *          me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);
		 *      }
		 *
		 *      ...
		 *
		 * }
		 */
		this.body = undefined;

		/**
		 * (G)ame (U)nique (Id)entifier" <br>
		 * a GUID will be allocated for any renderable object added <br>
		 * to an object container (including the `me.game.world` container)
		 * @type {string}
		 */
		this.GUID = undefined;

		/**
		 * an event handler that is called when the renderable leave or enter a camera viewport
		 * @type {Function}
		 * @default undefined
		 * @example
		 * this.onVisibilityChange = function(inViewport) {
		 *     if (inViewport === true) {
		 *         console.log("object has entered the in a camera viewport!");
		 *     }
		 * };
		 */
		this.onVisibilityChange = undefined;

		/**
		 * Whether the renderable object will always update, even when outside of the viewport<br>
		 * @type {boolean}
		 * @default false
		 */
		this.alwaysUpdate = false;

		/**
		 * Whether to update this object when the game is paused.
		 * @type {boolean}
		 * @default false
		 */
		this.updateWhenPaused = false;

		/**
		 * make the renderable object persistent over level changes<br>
		 * @type {boolean}
		 * @default false
		 */
		this.isPersistent = false;

		/**
		 * If true, this renderable will be rendered using screen coordinates,
		 * as opposed to world coordinates. Use this, for example, to define UI elements.
		 * @type {boolean}
		 * @default false
		 */
		this.floating = false;

		/**
		 * When enabled, an object container will automatically apply
		 * any defined transformation before calling the child draw method.
		 * @type {boolean}
		 * @default true
		 * @example
		 * // enable "automatic" transformation when the object is activated
		 * onActivateEvent: function () {
		 *     // reset the transformation matrix
		 *     this.currentTransform.identity();
		 *     // ensure the anchor point is the renderable center
		 *     this.anchorPoint.set(0.5, 0.5);
		 *     // enable auto transform
		 *     this.autoTransform = true;
		 *     ....
		 * }
		 */
		this.autoTransform = true;

		/**
		 * Define the renderable opacity<br>
		 * Set to zero if you do not wish an object to be drawn
		 * @see Renderable#setOpacity
		 * @see Renderable#getOpacity
		 * @type {number}
		 * @default 1.0
		 */
		this.alpha = 1.0;

		/**
		 * a reference to the parent object that contains this renderable
		 * @type {Container|Entity}
		 * @default undefined
		 */
		this.ancestor = undefined;

		/**
		 * A mask limits rendering elements to the shape and position of the given mask object.
		 * So, if the renderable is larger than the mask, only the intersecting part of the renderable will be visible.
		 * @type {Rect|RoundRect|Polygon|Line|Ellipse}
		 * @default undefined
		 * @example
		 * // apply a mask in the shape of a Star
		 * myNPCSprite.mask = new me.Polygon(myNPCSprite.width / 2, 0, [
		 *    // draw a star
		 *    {x: 0, y: 0},
		 *    {x: 14, y: 30},
		 *    {x: 47, y: 35},
		 *    {x: 23, y: 57},
		 *    {x: 44, y: 90},
		 *    {x: 0, y: 62},
		 *    {x: -44, y: 90},
		 *    {x: -23, y: 57},
		 *    {x: -47, y: 35},
		 *    {x: -14, y: 30}
		 * ]);
		 */
		this.mask = undefined;

		/**
		 * (Experimental) an optional shader, to be used instead of the default built-in one, when drawing this renderable (WebGL only)
		 * @type {GLShader}
		 * @default undefined
		 */
		this.shader = undefined;

		/**
		 * the blend mode to be applied to this renderable (see renderer setBlendMode for available blend mode)
		 * @type {string}
		 * @default "normal"
		 * @see CanvasRenderer#setBlendMode
		 * @see WebGLRenderer#setBlendMode
		 */
		this.blendMode = "normal";

		/**
		 * The name of the renderable
		 * @type {string}
		 * @default ""
		 */
		this.name = "";

		/**
		 * to identify the object as a renderable object
		 * @ignore
		 */
		this.isRenderable = true;

		/**
		 * If true then physic collision and input events will not impact this renderable
		 * @type {boolean}
		 * @default true
		 */
		this.isKinematic = true;

		/**
		 * when true the renderable will be redrawn during the next update cycle
		 * @type {boolean}
		 * @default true
		 */
		this.isDirty = true;

		/**
		 * cache the absolute position of the renderable
		 * @ignore
		 */
		this._absPos = undefined;

		/**
		 * keep track of when we flip
		 * @ignore
		 */
		this._flip = {
			x: false,
			y: false,
		};

		/**
		 * viewport flag
		 * @ignore
		 */
		this._inViewport = false;

		/**
		 * cache value for the parentApp
		 * @ignore
		 */
		this._parentApp = undefined;

		/**
		 * renderable cache tint value used by the getter/setter
		 * @ignore
		 */
		this._tint = colorPool.get(255, 255, 255, 1.0);

		// ensure it's fully opaque by default
		this.setOpacity(1.0);
	}
@param {number} x - position of the renderable object (accessible through inherited pos.x property)
@param {number} y - position of the renderable object (accessible through inherited pos.y property)
@param {number} width - object width
@param {number} height - object height