constructor(ancestor, shapes, onBodyUpdate) {
		/**
		 * a reference to the parent object that contains this body,
		 * or undefined if it has not been added to one.
		 * @public
		 * @type {Renderable|Container|Entity|Sprite|NineSliceSprite}
		 * @default undefined
		 */
		this.ancestor = ancestor;

		if (typeof this.bounds === "undefined") {
			/**
			 * The AABB bounds box reprensenting this body
			 * @public
			 * @type {Bounds}
			 */
			this.bounds = boundsPool.get();
		}

		if (typeof this.shapes === "undefined") {
			/**
			 * The collision shapes of the body
			 * @ignore
			 * @type {Polygon[]|Line[]|Ellipse[]|Point|Point[]}
			 */
			this.shapes = [];
		}

		/**
		 * The body collision mask, that defines what should collide with what.<br>
		 * (by default will collide with all entities)
		 * @ignore
		 * @type {number}
		 * @default collision.types.ALL_OBJECT
		 * @see collision.types
		 */
		this.collisionMask = collision.types.ALL_OBJECT;

		/**
		 * define the collision type of the body for collision filtering
		 * @public
		 * @type {number}
		 * @default collision.types.ENEMY_OBJECT
		 * @see collision.types
		 * @example
		 * // set the body collision type
		 * body.collisionType = me.collision.types.PLAYER_OBJECT;
		 */
		this.collisionType = collision.types.ENEMY_OBJECT;

		if (typeof this.vel === "undefined") {
			/**
			 * The current velocity of the body.
			 * See to apply a force if you need to modify a body velocity
			 * @see Body.force
			 * @public
			 * @type {Vector2d}
			 * @default <0,0>
			 */
			this.vel = vector2dPool.get();
		}
		this.vel.set(0, 0);

		if (typeof this.force === "undefined") {
			/**
			 * body force to apply to this the body in the current step.
			 * (any positive or negative force will be cancelled after every world/body update cycle)
			 * @public
			 * @type {Vector2d}
			 * @default <0,0>
			 * @see Body.setMaxVelocity
			 * @example
			 * // define a default maximum acceleration, initial force and friction
			 * this.body.force.set(1, 0);
			 * this.body.friction.set(0.4, 0);
			 * this.body.setMaxVelocity(3, 15);
			 *
			 * // apply a postive or negative force when pressing left of right key
			 * update(dt) {
			 *     if (me.input.isKeyPressed("left"))    {
			 *          this.body.force.x = -this.body.maxVel.x;
			 *      } else if (me.input.isKeyPressed("right")) {
			 *         this.body.force.x = this.body.maxVel.x;
			 *     }
			 * }
			 */
			this.force = vector2dPool.get();
		}
		this.force.set(0, 0);

		if (typeof this.friction === "undefined") {
			/**
			 * body friction
			 * @public
			 * @type {Vector2d}
			 * @default <0,0>
			 */
			this.friction = vector2dPool.get();
		}
		this.friction.set(0, 0);

		/**
		 * the body bouciness level when colliding with other solid bodies :
		 * a value of 0 will not bounce, a value of 1 will fully rebound.
		 * @public
		 * @type {number}
		 * @default 0
		 */
		this.bounce = 0;

		/**
		 * the body mass
		 * @public
		 * @type {number}
		 * @default 1
		 */
		this.mass = 1;

		if (typeof this.maxVel === "undefined") {
			/**
			 * max velocity (to limit body velocity)
			 * @public
			 * @type {Vector2d}
			 * @default <490,490>
			 */
			this.maxVel = vector2dPool.get();
		}
		// cap by default to half the default gravity force
		this.maxVel.set(490, 490);

		/**
		 * Either this body is a static body or not.
		 * A static body is completely fixed and can never change position or angle.
		 * @readonly
		 * @public
		 * @type {boolean}
		 * @default false
		 */
		this.isStatic = false;

		/**
		 * The degree to which this body is affected by the world gravity
		 * @public
		 * @see {@link World.gravity}
		 * @type {number}
		 * @default 1.0
		 */
		this.gravityScale = 1.0;

		/**
		 * If true this body won't be affected by the world gravity
		 * @public
		 * @see {@link World.gravity}
		 * @type {boolean}
		 * @default false
		 */
		this.ignoreGravity = false;

		/**
		 * falling state of the body<br>
		 * true if the object is falling<br>
		 * false if the object is standing on something<br>
		 * @readonly
		 * @public
		 * @type {boolean}
		 * @default false
		 */
		this.falling = false;

		/**
		 * jumping state of the body<br>
		 * equal true if the body is jumping<br>
		 * @readonly
		 * @public
		 * @type {boolean}
		 * @default false
		 */
		this.jumping = false;

		if (typeof onBodyUpdate === "function") {
			this.onBodyUpdate = onBodyUpdate;
		}

		this.bounds.clear();

		// parses the given shapes array and add them
		if (typeof shapes !== "undefined") {
			if (Array.isArray(shapes)) {
				for (let s = 0; s < shapes.length; s++) {
					this.addShape(shapes[s]);
				}
			} else {
				this.addShape(shapes);
			}
		}

		// automatically enable physic when a body is added to a renderable
		this.ancestor.isKinematic = false;
	}
@param {Renderable|Container|Entity|Sprite|NineSliceSprite} ancestor - the parent object this body is attached to
@param {Rect|Rect[]|Polygon|Polygon[]|Line|Line[]|Ellipse|Ellipse[]|Point|Point[]|Bounds|Bounds[]|object} [shapes] - a initial shape, list of shapes, or JSON object defining the body
@param {Function} [onBodyUpdate] - callback for when the body is updated (e.g. add/remove shapes)