diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3119f18..f8a2e11 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,39 @@
+## 0.19.0 (2023-02-16)
+
+See the release [readme](https://github.com/liabru/matter-js/blob/0.19.0/README.md) for further information.
+
+* added readme note about vue watchers ([035481c](https://github.com/liabru/matter-js/commit/035481c))
+* added readonly body.deltaTime ([0784a5b](https://github.com/liabru/matter-js/commit/0784a5b))
+* added speed setters to Body.set ([3ff6ff4](https://github.com/liabru/matter-js/commit/3ff6ff4))
+* added support for Matter.Runner and Matter.Render in tests ([7d7bad0](https://github.com/liabru/matter-js/commit/7d7bad0))
+* added updateVelocity argument to Body.setPosition, Body.setAngle, Body.translate, Body.rotate ([db8b73f](https://github.com/liabru/matter-js/commit/db8b73f))
+* changed engine collisionStart event to trigger after resolving and after updating body velocities ([70600a8](https://github.com/liabru/matter-js/commit/70600a8))
+* changed examples to be delta independent ([d7e4f58](https://github.com/liabru/matter-js/commit/d7e4f58))
+* deprecated render.controller property ([04d229e](https://github.com/liabru/matter-js/commit/04d229e))
+* derived velocity from position in setters ([b6de9ed](https://github.com/liabru/matter-js/commit/b6de9ed))
+* fixed issues with engine event.delta ([6f5af77](https://github.com/liabru/matter-js/commit/6f5af77))
+* handle null constraint points in Constraint.pointAWorld and Constraint.pointBWorld ([e414464](https://github.com/liabru/matter-js/commit/e414464))
+* improved Body.applyForce docs ([3a8264c](https://github.com/liabru/matter-js/commit/3a8264c))
+* improved delta factors in resolver and constraint stiffness ([9dc6be7](https://github.com/liabru/matter-js/commit/9dc6be7))
+* improved Matter.Body docs for functions and properties including readonly ([85a9eb2](https://github.com/liabru/matter-js/commit/85a9eb2))
+* improved Matter.Engine docs ([50fc8f2](https://github.com/liabru/matter-js/commit/50fc8f2))
+* improved slingshot example constraint ([c6a1a6d](https://github.com/liabru/matter-js/commit/c6a1a6d))
+* improved delta consistency ([87af8a1](https://github.com/liabru/matter-js/commit/87af8a1))
+* improved Example.newtonsCradle ([b2bd492](https://github.com/liabru/matter-js/commit/b2bd492))
+* removed render element warning ([459425b](https://github.com/liabru/matter-js/commit/459425b))
+* removed unused delta params ([a572968](https://github.com/liabru/matter-js/commit/a572968))
+* updated body docs ([6bb2855](https://github.com/liabru/matter-js/commit/6bb2855))
+* updated body velocity properties after resolving ([d52f7e6](https://github.com/liabru/matter-js/commit/d52f7e6))
+* updated Example.manipulation ([5ddac71](https://github.com/liabru/matter-js/commit/5ddac71))
+* updated Example.ragdoll ([ec38638](https://github.com/liabru/matter-js/commit/ec38638))
+* updated Example.staticFriction and Example.timeScale ([11d5e73](https://github.com/liabru/matter-js/commit/11d5e73))
+* updated Matter.Body docs ([db780c3](https://github.com/liabru/matter-js/commit/db780c3))
+* updated timing improvements ([10a2a07](https://github.com/liabru/matter-js/commit/10a2a07))
+* used Body.getVelocity in Matter.Render ([bf90bdd](https://github.com/liabru/matter-js/commit/bf90bdd))
+* used speed getter in Matter.Sleeping and Matter.Render ([6579dfd](https://github.com/liabru/matter-js/commit/6579dfd))
+
+
+
## 0.18.0 (2021-12-15)
* added test capture sort to improve comparison ([ea3c11b](https://github.com/liabru/matter-js/commit/ea3c11b))
diff --git a/RELEASE.md b/RELEASE.md
index 069318a..818faed 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,3 +1,56 @@
+## ▲.● matter.js `0.19.0`
+
+Release notes for `0.19.0`. See the release [readme](https://github.com/liabru/matter-js/blob/0.19.0/README.md) for further information.
+
+### Highlights ✺
+
+- Changed `Body.setAngularVelocity` and `Body.setVelocity` to be timestep independent
+- Improved similarity of results between different timesteps based on `60hz` as a baseline
+- Added timestep independent `Body.setSpeed`, `Body.setAngularSpeed`, `Body.getSpeed`, `Body.getVelocity`, `Body.getAngularVelocity`
+- Added optional `updateVelocity` argument to `Body.setPosition`, `Body.setAngle`, `Body.translate`, `Body.rotate`
+- Added extended documentation for `Body.applyForce`
+- Moved time correction feature from `Engine.update` to be built-in to `Matter.Body`
+- Improved [documentation](https://brm.io/matter-js/docs/) pages
+
+### Changes ✲
+
+See the release [compare page](https://github.com/liabru/matter-js/compare/0.18.0...0.19.0) and the [changelog](https://github.com/liabru/matter-js/blob/0.19.0/CHANGELOG.md) for a more detailed list of changes.
+
+### Migration ⌲
+
+See [PR #777](https://github.com/liabru/matter-js/pull/777#issue-487893963) for related changes and notes useful for migration.
+
+### Comparison ⎄
+
+For more information see [comparison method](https://github.com/liabru/matter-js/pull/794).
+
+```ocaml
+Output comparison of 43 examples at 60hz against previous release matter-js@0.18.0
+
+Behaviour 100.00% Similarity 100.00% Overlap +0.00%
+Performance -0.80% Memory +0.05% Filesize +1.67% 78.97 KB
+
+airFriction · · avalanche · · ballPool · · bridge · · car · · catapult · ·
+chains · · circleStack · · cloth · · collisionFiltering · · compositeManipulation · ·
+compound · · compoundStack · · concave · · constraints · · doublePendulum · ·
+events · · friction · · gravity · · gyro · · manipulation · ·
+mixed · · newtonsCradle · · pyramid · · ragdoll · · raycasting · ·
+remove · · restitution · · rounded · · sensors · · sleeping · ◆
+slingshot · · softBody · · sprites · · stack · · staticFriction · ·
+stats · · stress · · stress2 · · stress3 · · timescale · ·
+views · · wreckingBall · ·
+
+where · no change ● extrinsics changed ◆ intrinsics changed
+
+▶ code -n -d test/__compare__/examples-build.json test/__compare__/examples-dev.json
+```
+
+### Contributors ♥︎
+
+Many thanks to the [contributors](https://github.com/liabru/matter-js/compare/0.18.0...0.19.0) of this release, [past contributors](https://github.com/liabru/matter-js/graphs/contributors) as well those involved in the [community](https://github.com/liabru/matter-js/issues) for your input and support.
+
+---
+
## ▲.● matter.js `0.18.0`
Release notes for `0.18.0`. See the release [readme](https://github.com/liabru/matter-js/blob/0.18.0/README.md) for further information.
diff --git a/build/matter.js b/build/matter.js
index ae3bc3d..8a80bbb 100644
--- a/build/matter.js
+++ b/build/matter.js
@@ -1,5 +1,5 @@
/*!
- * matter-js 0.18.0 by @liabru
+ * matter-js 0.19.0 by @liabru
* http://brm.io/matter-js/
* License MIT
*
@@ -118,7 +118,7 @@ return /******/ (function(modules) { // webpackBootstrap
/******/
/******/
/******/ // Load entry module and return exports
-/******/ return __webpack_require__(__webpack_require__.s = 21);
+/******/ return __webpack_require__(__webpack_require__.s = 20);
/******/ })
/************************************************************************/
/******/ ([
@@ -137,6 +137,7 @@ module.exports = Common;
(function() {
+ Common._baseDelta = 1000 / 60;
Common._nextId = 0;
Common._seed = 0;
Common._nowStartTime = +(new Date());
@@ -449,7 +450,8 @@ module.exports = Common;
* - 2 = Info
* - 3 = Warn
* - 4 = Error
- * @property Common.logLevel
+ * @static
+ * @property logLevel
* @type {Number}
* @default 1
*/
@@ -1579,6 +1581,1452 @@ var Common = __webpack_require__(0);
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
+/**
+* The `Matter.Body` module contains methods for creating and manipulating rigid bodies.
+* For creating bodies with common configurations such as rectangles, circles and other polygons see the module `Matter.Bodies`.
+*
+* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
+
+* @class Body
+*/
+
+var Body = {};
+
+module.exports = Body;
+
+var Vertices = __webpack_require__(3);
+var Vector = __webpack_require__(2);
+var Sleeping = __webpack_require__(7);
+var Common = __webpack_require__(0);
+var Bounds = __webpack_require__(1);
+var Axes = __webpack_require__(11);
+
+(function() {
+
+ Body._timeCorrection = true;
+ Body._inertiaScale = 4;
+ Body._nextCollidingGroupId = 1;
+ Body._nextNonCollidingGroupId = -1;
+ Body._nextCategory = 0x0001;
+ Body._baseDelta = 1000 / 60;
+
+ /**
+ * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults.
+ * All properties have default values, and many are pre-calculated automatically based on other properties.
+ * Vertices must be specified in clockwise order.
+ * See the properties section below for detailed information on what you can pass via the `options` object.
+ * @method create
+ * @param {} options
+ * @return {body} body
+ */
+ Body.create = function(options) {
+ var defaults = {
+ id: Common.nextId(),
+ type: 'body',
+ label: 'Body',
+ parts: [],
+ plugin: {},
+ angle: 0,
+ vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
+ position: { x: 0, y: 0 },
+ force: { x: 0, y: 0 },
+ torque: 0,
+ positionImpulse: { x: 0, y: 0 },
+ constraintImpulse: { x: 0, y: 0, angle: 0 },
+ totalContacts: 0,
+ speed: 0,
+ angularSpeed: 0,
+ velocity: { x: 0, y: 0 },
+ angularVelocity: 0,
+ isSensor: false,
+ isStatic: false,
+ isSleeping: false,
+ motion: 0,
+ sleepThreshold: 60,
+ density: 0.001,
+ restitution: 0,
+ friction: 0.1,
+ frictionStatic: 0.5,
+ frictionAir: 0.01,
+ collisionFilter: {
+ category: 0x0001,
+ mask: 0xFFFFFFFF,
+ group: 0
+ },
+ slop: 0.05,
+ timeScale: 1,
+ render: {
+ visible: true,
+ opacity: 1,
+ strokeStyle: null,
+ fillStyle: null,
+ lineWidth: null,
+ sprite: {
+ xScale: 1,
+ yScale: 1,
+ xOffset: 0,
+ yOffset: 0
+ }
+ },
+ events: null,
+ bounds: null,
+ chamfer: null,
+ circleRadius: 0,
+ positionPrev: null,
+ anglePrev: 0,
+ parent: null,
+ axes: null,
+ area: 0,
+ mass: 0,
+ inertia: 0,
+ deltaTime: 1000 / 60,
+ _original: null
+ };
+
+ var body = Common.extend(defaults, options);
+
+ _initProperties(body, options);
+
+ return body;
+ };
+
+ /**
+ * Returns the next unique group index for which bodies will collide.
+ * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide.
+ * See `body.collisionFilter` for more information.
+ * @method nextGroup
+ * @param {bool} [isNonColliding=false]
+ * @return {Number} Unique group index
+ */
+ Body.nextGroup = function(isNonColliding) {
+ if (isNonColliding)
+ return Body._nextNonCollidingGroupId--;
+
+ return Body._nextCollidingGroupId++;
+ };
+
+ /**
+ * Returns the next unique category bitfield (starting after the initial default category `0x0001`).
+ * There are 32 available. See `body.collisionFilter` for more information.
+ * @method nextCategory
+ * @return {Number} Unique category bitfield
+ */
+ Body.nextCategory = function() {
+ Body._nextCategory = Body._nextCategory << 1;
+ return Body._nextCategory;
+ };
+
+ /**
+ * Initialises body properties.
+ * @method _initProperties
+ * @private
+ * @param {body} body
+ * @param {} [options]
+ */
+ var _initProperties = function(body, options) {
+ options = options || {};
+
+ // init required properties (order is important)
+ Body.set(body, {
+ bounds: body.bounds || Bounds.create(body.vertices),
+ positionPrev: body.positionPrev || Vector.clone(body.position),
+ anglePrev: body.anglePrev || body.angle,
+ vertices: body.vertices,
+ parts: body.parts || [body],
+ isStatic: body.isStatic,
+ isSleeping: body.isSleeping,
+ parent: body.parent || body
+ });
+
+ Vertices.rotate(body.vertices, body.angle, body.position);
+ Axes.rotate(body.axes, body.angle);
+ Bounds.update(body.bounds, body.vertices, body.velocity);
+
+ // allow options to override the automatically calculated properties
+ Body.set(body, {
+ axes: options.axes || body.axes,
+ area: options.area || body.area,
+ mass: options.mass || body.mass,
+ inertia: options.inertia || body.inertia
+ });
+
+ // render properties
+ var defaultFillStyle = (body.isStatic ? '#14151f' : Common.choose(['#f19648', '#f5d259', '#f55a3c', '#063e7b', '#ececd1'])),
+ defaultStrokeStyle = body.isStatic ? '#555' : '#ccc',
+ defaultLineWidth = body.isStatic && body.render.fillStyle === null ? 1 : 0;
+ body.render.fillStyle = body.render.fillStyle || defaultFillStyle;
+ body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle;
+ body.render.lineWidth = body.render.lineWidth || defaultLineWidth;
+ body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x);
+ body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y);
+ };
+
+ /**
+ * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist.
+ * Prefer to use the actual setter functions in performance critical situations.
+ * @method set
+ * @param {body} body
+ * @param {} settings A property name (or map of properties and values) to set on the body.
+ * @param {} value The value to set if `settings` is a single property name.
+ */
+ Body.set = function(body, settings, value) {
+ var property;
+
+ if (typeof settings === 'string') {
+ property = settings;
+ settings = {};
+ settings[property] = value;
+ }
+
+ for (property in settings) {
+ if (!Object.prototype.hasOwnProperty.call(settings, property))
+ continue;
+
+ value = settings[property];
+ switch (property) {
+
+ case 'isStatic':
+ Body.setStatic(body, value);
+ break;
+ case 'isSleeping':
+ Sleeping.set(body, value);
+ break;
+ case 'mass':
+ Body.setMass(body, value);
+ break;
+ case 'density':
+ Body.setDensity(body, value);
+ break;
+ case 'inertia':
+ Body.setInertia(body, value);
+ break;
+ case 'vertices':
+ Body.setVertices(body, value);
+ break;
+ case 'position':
+ Body.setPosition(body, value);
+ break;
+ case 'angle':
+ Body.setAngle(body, value);
+ break;
+ case 'velocity':
+ Body.setVelocity(body, value);
+ break;
+ case 'angularVelocity':
+ Body.setAngularVelocity(body, value);
+ break;
+ case 'speed':
+ Body.setSpeed(body, value);
+ break;
+ case 'angularSpeed':
+ Body.setAngularSpeed(body, value);
+ break;
+ case 'parts':
+ Body.setParts(body, value);
+ break;
+ case 'centre':
+ Body.setCentre(body, value);
+ break;
+ default:
+ body[property] = value;
+
+ }
+ }
+ };
+
+ /**
+ * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity.
+ * @method setStatic
+ * @param {body} body
+ * @param {bool} isStatic
+ */
+ Body.setStatic = function(body, isStatic) {
+ for (var i = 0; i < body.parts.length; i++) {
+ var part = body.parts[i];
+ part.isStatic = isStatic;
+
+ if (isStatic) {
+ part._original = {
+ restitution: part.restitution,
+ friction: part.friction,
+ mass: part.mass,
+ inertia: part.inertia,
+ density: part.density,
+ inverseMass: part.inverseMass,
+ inverseInertia: part.inverseInertia
+ };
+
+ part.restitution = 0;
+ part.friction = 1;
+ part.mass = part.inertia = part.density = Infinity;
+ part.inverseMass = part.inverseInertia = 0;
+
+ part.positionPrev.x = part.position.x;
+ part.positionPrev.y = part.position.y;
+ part.anglePrev = part.angle;
+ part.angularVelocity = 0;
+ part.speed = 0;
+ part.angularSpeed = 0;
+ part.motion = 0;
+ } else if (part._original) {
+ part.restitution = part._original.restitution;
+ part.friction = part._original.friction;
+ part.mass = part._original.mass;
+ part.inertia = part._original.inertia;
+ part.density = part._original.density;
+ part.inverseMass = part._original.inverseMass;
+ part.inverseInertia = part._original.inverseInertia;
+
+ part._original = null;
+ }
+ }
+ };
+
+ /**
+ * Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change.
+ * @method setMass
+ * @param {body} body
+ * @param {number} mass
+ */
+ Body.setMass = function(body, mass) {
+ var moment = body.inertia / (body.mass / 6);
+ body.inertia = moment * (mass / 6);
+ body.inverseInertia = 1 / body.inertia;
+
+ body.mass = mass;
+ body.inverseMass = 1 / body.mass;
+ body.density = body.mass / body.area;
+ };
+
+ /**
+ * Sets the density of the body. Mass and inertia are automatically updated to reflect the change.
+ * @method setDensity
+ * @param {body} body
+ * @param {number} density
+ */
+ Body.setDensity = function(body, density) {
+ Body.setMass(body, density * body.area);
+ body.density = density;
+ };
+
+ /**
+ * Sets the moment of inertia of the body. This is the second moment of area in two dimensions.
+ * Inverse inertia is automatically updated to reflect the change. Mass is not changed.
+ * @method setInertia
+ * @param {body} body
+ * @param {number} inertia
+ */
+ Body.setInertia = function(body, inertia) {
+ body.inertia = inertia;
+ body.inverseInertia = 1 / body.inertia;
+ };
+
+ /**
+ * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`).
+ * Vertices will be automatically transformed to be orientated around their centre of mass as the origin.
+ * They are then automatically translated to world space based on `body.position`.
+ *
+ * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array).
+ * Vertices must form a convex hull. Concave vertices must be decomposed into convex parts.
+ *
+ * @method setVertices
+ * @param {body} body
+ * @param {vector[]} vertices
+ */
+ Body.setVertices = function(body, vertices) {
+ // change vertices
+ if (vertices[0].body === body) {
+ body.vertices = vertices;
+ } else {
+ body.vertices = Vertices.create(vertices, body);
+ }
+
+ // update properties
+ body.axes = Axes.fromVertices(body.vertices);
+ body.area = Vertices.area(body.vertices);
+ Body.setMass(body, body.density * body.area);
+
+ // orient vertices around the centre of mass at origin (0, 0)
+ var centre = Vertices.centre(body.vertices);
+ Vertices.translate(body.vertices, centre, -1);
+
+ // update inertia while vertices are at origin (0, 0)
+ Body.setInertia(body, Body._inertiaScale * Vertices.inertia(body.vertices, body.mass));
+
+ // update geometry
+ Vertices.translate(body.vertices, body.position);
+ Bounds.update(body.bounds, body.vertices, body.velocity);
+ };
+
+ /**
+ * Sets the parts of the `body` and updates mass, inertia and centroid.
+ * Each part will have its parent set to `body`.
+ * By default the convex hull will be automatically computed and set on `body`, unless `autoHull` is set to `false.`
+ * Note that this method will ensure that the first part in `body.parts` will always be the `body`.
+ * @method setParts
+ * @param {body} body
+ * @param {body[]} parts
+ * @param {bool} [autoHull=true]
+ */
+ Body.setParts = function(body, parts, autoHull) {
+ var i;
+
+ // add all the parts, ensuring that the first part is always the parent body
+ parts = parts.slice(0);
+ body.parts.length = 0;
+ body.parts.push(body);
+ body.parent = body;
+
+ for (i = 0; i < parts.length; i++) {
+ var part = parts[i];
+ if (part !== body) {
+ part.parent = body;
+ body.parts.push(part);
+ }
+ }
+
+ if (body.parts.length === 1)
+ return;
+
+ autoHull = typeof autoHull !== 'undefined' ? autoHull : true;
+
+ // find the convex hull of all parts to set on the parent body
+ if (autoHull) {
+ var vertices = [];
+ for (i = 0; i < parts.length; i++) {
+ vertices = vertices.concat(parts[i].vertices);
+ }
+
+ Vertices.clockwiseSort(vertices);
+
+ var hull = Vertices.hull(vertices),
+ hullCentre = Vertices.centre(hull);
+
+ Body.setVertices(body, hull);
+ Vertices.translate(body.vertices, hullCentre);
+ }
+
+ // sum the properties of all compound parts of the parent body
+ var total = Body._totalProperties(body);
+
+ body.area = total.area;
+ body.parent = body;
+ body.position.x = total.centre.x;
+ body.position.y = total.centre.y;
+ body.positionPrev.x = total.centre.x;
+ body.positionPrev.y = total.centre.y;
+
+ Body.setMass(body, total.mass);
+ Body.setInertia(body, total.inertia);
+ Body.setPosition(body, total.centre);
+ };
+
+ /**
+ * Set the centre of mass of the body.
+ * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation.
+ * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density.
+ * This is equal to moving `body.position` but not the `body.vertices`.
+ * Invalid if the `centre` falls outside the body's convex hull.
+ * @method setCentre
+ * @param {body} body
+ * @param {vector} centre
+ * @param {bool} relative
+ */
+ Body.setCentre = function(body, centre, relative) {
+ if (!relative) {
+ body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x);
+ body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y);
+ body.position.x = centre.x;
+ body.position.y = centre.y;
+ } else {
+ body.positionPrev.x += centre.x;
+ body.positionPrev.y += centre.y;
+ body.position.x += centre.x;
+ body.position.y += centre.y;
+ }
+ };
+
+ /**
+ * Sets the position of the body. By default velocity is unchanged.
+ * If `updateVelocity` is `true` then velocity is inferred from the change in position.
+ * @method setPosition
+ * @param {body} body
+ * @param {vector} position
+ * @param {boolean} [updateVelocity=false]
+ */
+ Body.setPosition = function(body, position, updateVelocity) {
+ var delta = Vector.sub(position, body.position);
+
+ if (updateVelocity) {
+ body.positionPrev.x = body.position.x;
+ body.positionPrev.y = body.position.y;
+ body.velocity.x = delta.x;
+ body.velocity.y = delta.y;
+ body.speed = Vector.magnitude(delta);
+ } else {
+ body.positionPrev.x += delta.x;
+ body.positionPrev.y += delta.y;
+ }
+
+ for (var i = 0; i < body.parts.length; i++) {
+ var part = body.parts[i];
+ part.position.x += delta.x;
+ part.position.y += delta.y;
+ Vertices.translate(part.vertices, delta);
+ Bounds.update(part.bounds, part.vertices, body.velocity);
+ }
+ };
+
+ /**
+ * Sets the angle of the body. By default angular velocity is unchanged.
+ * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle.
+ * @method setAngle
+ * @param {body} body
+ * @param {number} angle
+ * @param {boolean} [updateVelocity=false]
+ */
+ Body.setAngle = function(body, angle, updateVelocity) {
+ var delta = angle - body.angle;
+
+ if (updateVelocity) {
+ body.anglePrev = body.angle;
+ body.angularVelocity = delta;
+ body.angularSpeed = Math.abs(delta);
+ } else {
+ body.anglePrev += delta;
+ }
+
+ for (var i = 0; i < body.parts.length; i++) {
+ var part = body.parts[i];
+ part.angle += delta;
+ Vertices.rotate(part.vertices, delta, body.position);
+ Axes.rotate(part.axes, delta);
+ Bounds.update(part.bounds, part.vertices, body.velocity);
+ if (i > 0) {
+ Vector.rotateAbout(part.position, delta, body.position, part.position);
+ }
+ }
+ };
+
+ /**
+ * Sets the current linear velocity of the body.
+ * Affects body speed.
+ * @method setVelocity
+ * @param {body} body
+ * @param {vector} velocity
+ */
+ Body.setVelocity = function(body, velocity) {
+ var timeScale = body.deltaTime / Body._baseDelta;
+ body.positionPrev.x = body.position.x - velocity.x * timeScale;
+ body.positionPrev.y = body.position.y - velocity.y * timeScale;
+ body.velocity.x = (body.position.x - body.positionPrev.x) / timeScale;
+ body.velocity.y = (body.position.y - body.positionPrev.y) / timeScale;
+ body.speed = Vector.magnitude(body.velocity);
+ };
+
+ /**
+ * Gets the current linear velocity of the body.
+ * @method getVelocity
+ * @param {body} body
+ * @return {vector} velocity
+ */
+ Body.getVelocity = function(body) {
+ var timeScale = Body._baseDelta / body.deltaTime;
+
+ return {
+ x: (body.position.x - body.positionPrev.x) * timeScale,
+ y: (body.position.y - body.positionPrev.y) * timeScale
+ };
+ };
+
+ /**
+ * Gets the current linear speed of the body.
+ * Equivalent to the magnitude of its velocity.
+ * @method getSpeed
+ * @param {body} body
+ * @return {number} speed
+ */
+ Body.getSpeed = function(body) {
+ return Vector.magnitude(Body.getVelocity(body));
+ };
+
+ /**
+ * Sets the current linear speed of the body.
+ * Direction is maintained. Affects body velocity.
+ * @method setSpeed
+ * @param {body} body
+ * @param {number} speed
+ */
+ Body.setSpeed = function(body, speed) {
+ Body.setVelocity(body, Vector.mult(Vector.normalise(Body.getVelocity(body)), speed));
+ };
+
+ /**
+ * Sets the current rotational velocity of the body.
+ * Affects body angular speed.
+ * @method setAngularVelocity
+ * @param {body} body
+ * @param {number} velocity
+ */
+ Body.setAngularVelocity = function(body, velocity) {
+ var timeScale = body.deltaTime / Body._baseDelta;
+ body.anglePrev = body.angle - velocity * timeScale;
+ body.angularVelocity = (body.angle - body.anglePrev) / timeScale;
+ body.angularSpeed = Math.abs(body.angularVelocity);
+ };
+
+ /**
+ * Gets the current rotational velocity of the body.
+ * @method getAngularVelocity
+ * @param {body} body
+ * @return {number} angular velocity
+ */
+ Body.getAngularVelocity = function(body) {
+ return (body.angle - body.anglePrev) * Body._baseDelta / body.deltaTime;
+ };
+
+ /**
+ * Gets the current rotational speed of the body.
+ * Equivalent to the magnitude of its angular velocity.
+ * @method getAngularSpeed
+ * @param {body} body
+ * @return {number} angular speed
+ */
+ Body.getAngularSpeed = function(body) {
+ return Math.abs(Body.getAngularVelocity(body));
+ };
+
+ /**
+ * Sets the current rotational speed of the body.
+ * Direction is maintained. Affects body angular velocity.
+ * @method setAngularSpeed
+ * @param {body} body
+ * @param {number} speed
+ */
+ Body.setAngularSpeed = function(body, speed) {
+ Body.setAngularVelocity(body, Common.sign(Body.getAngularVelocity(body)) * speed);
+ };
+
+ /**
+ * Moves a body by a given vector relative to its current position. By default velocity is unchanged.
+ * If `updateVelocity` is `true` then velocity is inferred from the change in position.
+ * @method translate
+ * @param {body} body
+ * @param {vector} translation
+ * @param {boolean} [updateVelocity=false]
+ */
+ Body.translate = function(body, translation, updateVelocity) {
+ Body.setPosition(body, Vector.add(body.position, translation), updateVelocity);
+ };
+
+ /**
+ * Rotates a body by a given angle relative to its current angle. By default angular velocity is unchanged.
+ * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle.
+ * @method rotate
+ * @param {body} body
+ * @param {number} rotation
+ * @param {vector} [point]
+ * @param {boolean} [updateVelocity=false]
+ */
+ Body.rotate = function(body, rotation, point, updateVelocity) {
+ if (!point) {
+ Body.setAngle(body, body.angle + rotation, updateVelocity);
+ } else {
+ var cos = Math.cos(rotation),
+ sin = Math.sin(rotation),
+ dx = body.position.x - point.x,
+ dy = body.position.y - point.y;
+
+ Body.setPosition(body, {
+ x: point.x + (dx * cos - dy * sin),
+ y: point.y + (dx * sin + dy * cos)
+ }, updateVelocity);
+
+ Body.setAngle(body, body.angle + rotation, updateVelocity);
+ }
+ };
+
+ /**
+ * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre).
+ * @method scale
+ * @param {body} body
+ * @param {number} scaleX
+ * @param {number} scaleY
+ * @param {vector} [point]
+ */
+ Body.scale = function(body, scaleX, scaleY, point) {
+ var totalArea = 0,
+ totalInertia = 0;
+
+ point = point || body.position;
+
+ for (var i = 0; i < body.parts.length; i++) {
+ var part = body.parts[i];
+
+ // scale vertices
+ Vertices.scale(part.vertices, scaleX, scaleY, point);
+
+ // update properties
+ part.axes = Axes.fromVertices(part.vertices);
+ part.area = Vertices.area(part.vertices);
+ Body.setMass(part, body.density * part.area);
+
+ // update inertia (requires vertices to be at origin)
+ Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y });
+ Body.setInertia(part, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass));
+ Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });
+
+ if (i > 0) {
+ totalArea += part.area;
+ totalInertia += part.inertia;
+ }
+
+ // scale position
+ part.position.x = point.x + (part.position.x - point.x) * scaleX;
+ part.position.y = point.y + (part.position.y - point.y) * scaleY;
+
+ // update bounds
+ Bounds.update(part.bounds, part.vertices, body.velocity);
+ }
+
+ // handle parent body
+ if (body.parts.length > 1) {
+ body.area = totalArea;
+
+ if (!body.isStatic) {
+ Body.setMass(body, body.density * totalArea);
+ Body.setInertia(body, totalInertia);
+ }
+ }
+
+ // handle circles
+ if (body.circleRadius) {
+ if (scaleX === scaleY) {
+ body.circleRadius *= scaleX;
+ } else {
+ // body is no longer a circle
+ body.circleRadius = null;
+ }
+ }
+ };
+
+ /**
+ * Performs an update by integrating the equations of motion on the `body`.
+ * This is applied every update by `Matter.Engine` automatically.
+ * @method update
+ * @param {body} body
+ * @param {number} [deltaTime=16.666]
+ */
+ Body.update = function(body, deltaTime) {
+ deltaTime = (typeof deltaTime !== 'undefined' ? deltaTime : (1000 / 60)) * body.timeScale;
+
+ var deltaTimeSquared = deltaTime * deltaTime,
+ correction = Body._timeCorrection ? deltaTime / (body.deltaTime || deltaTime) : 1;
+
+ // from the previous step
+ var frictionAir = 1 - body.frictionAir * (deltaTime / Common._baseDelta),
+ velocityPrevX = (body.position.x - body.positionPrev.x) * correction,
+ velocityPrevY = (body.position.y - body.positionPrev.y) * correction;
+
+ // update velocity with Verlet integration
+ body.velocity.x = (velocityPrevX * frictionAir) + (body.force.x / body.mass) * deltaTimeSquared;
+ body.velocity.y = (velocityPrevY * frictionAir) + (body.force.y / body.mass) * deltaTimeSquared;
+
+ body.positionPrev.x = body.position.x;
+ body.positionPrev.y = body.position.y;
+ body.position.x += body.velocity.x;
+ body.position.y += body.velocity.y;
+ body.deltaTime = deltaTime;
+
+ // update angular velocity with Verlet integration
+ body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;
+ body.anglePrev = body.angle;
+ body.angle += body.angularVelocity;
+
+ // transform the body geometry
+ for (var i = 0; i < body.parts.length; i++) {
+ var part = body.parts[i];
+
+ Vertices.translate(part.vertices, body.velocity);
+
+ if (i > 0) {
+ part.position.x += body.velocity.x;
+ part.position.y += body.velocity.y;
+ }
+
+ if (body.angularVelocity !== 0) {
+ Vertices.rotate(part.vertices, body.angularVelocity, body.position);
+ Axes.rotate(part.axes, body.angularVelocity);
+ if (i > 0) {
+ Vector.rotateAbout(part.position, body.angularVelocity, body.position, part.position);
+ }
+ }
+
+ Bounds.update(part.bounds, part.vertices, body.velocity);
+ }
+ };
+
+ /**
+ * Updates properties `body.velocity`, `body.speed`, `body.angularVelocity` and `body.angularSpeed` which are normalised in relation to `Body._baseDelta`.
+ * @method updateVelocities
+ * @param {body} body
+ */
+ Body.updateVelocities = function(body) {
+ var timeScale = Body._baseDelta / body.deltaTime,
+ bodyVelocity = body.velocity;
+
+ bodyVelocity.x = (body.position.x - body.positionPrev.x) * timeScale;
+ bodyVelocity.y = (body.position.y - body.positionPrev.y) * timeScale;
+ body.speed = Math.sqrt((bodyVelocity.x * bodyVelocity.x) + (bodyVelocity.y * bodyVelocity.y));
+
+ body.angularVelocity = (body.angle - body.anglePrev) * timeScale;
+ body.angularSpeed = Math.abs(body.angularVelocity);
+ };
+
+ /**
+ * Applies the `force` to the `body` from the force origin `position` in world-space, over a single timestep, including applying any resulting angular torque.
+ *
+ * Forces are useful for effects like gravity, wind or rocket thrust, but can be difficult in practice when precise control is needed. In these cases see `Body.setVelocity` and `Body.setPosition` as an alternative.
+ *
+ * The force from this function is only applied once for the duration of a single timestep, in other words the duration depends directly on the current engine update `delta` and the rate of calls to this function.
+ *
+ * Therefore to account for time, you should apply the force constantly over as many engine updates as equivalent to the intended duration.
+ *
+ * If all or part of the force duration is some fraction of a timestep, first multiply the force by `duration / timestep`.
+ *
+ * The force origin `position` in world-space must also be specified. Passing `body.position` will result in zero angular effect as the force origin would be at the centre of mass.
+ *
+ * The `body` will take time to accelerate under a force, the resulting effect depends on duration of the force, the body mass and other forces on the body including friction combined.
+ * @method applyForce
+ * @param {body} body
+ * @param {vector} position The force origin in world-space. Pass `body.position` to avoid angular torque.
+ * @param {vector} force
+ */
+ Body.applyForce = function(body, position, force) {
+ var offset = { x: position.x - body.position.x, y: position.y - body.position.y };
+ body.force.x += force.x;
+ body.force.y += force.y;
+ body.torque += offset.x * force.y - offset.y * force.x;
+ };
+
+ /**
+ * Returns the sums of the properties of all compound parts of the parent body.
+ * @method _totalProperties
+ * @private
+ * @param {body} body
+ * @return {}
+ */
+ Body._totalProperties = function(body) {
+ // from equations at:
+ // https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory
+ // http://output.to/sideway/default.asp?qno=121100087
+
+ var properties = {
+ mass: 0,
+ area: 0,
+ inertia: 0,
+ centre: { x: 0, y: 0 }
+ };
+
+ // sum the properties of all compound parts of the parent body
+ for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
+ var part = body.parts[i],
+ mass = part.mass !== Infinity ? part.mass : 1;
+
+ properties.mass += mass;
+ properties.area += part.area;
+ properties.inertia += part.inertia;
+ properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass));
+ }
+
+ properties.centre = Vector.div(properties.centre, properties.mass);
+
+ return properties;
+ };
+
+ /*
+ *
+ * Events Documentation
+ *
+ */
+
+ /**
+ * Fired when a body starts sleeping (where `this` is the body).
+ *
+ * @event sleepStart
+ * @this {body} The body that has started sleeping
+ * @param {} event An event object
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired when a body ends sleeping (where `this` is the body).
+ *
+ * @event sleepEnd
+ * @this {body} The body that has ended sleeping
+ * @param {} event An event object
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`.
+ *
+ * @property id
+ * @type number
+ */
+
+ /**
+ * _Read only_. Set by `Body.create`.
+ *
+ * A `String` denoting the type of object.
+ *
+ * @readOnly
+ * @property type
+ * @type string
+ * @default "body"
+ */
+
+ /**
+ * An arbitrary `String` name to help the user identify and manage bodies.
+ *
+ * @property label
+ * @type string
+ * @default "Body"
+ */
+
+ /**
+ * _Read only_. Use `Body.setParts` to set.
+ *
+ * An array of bodies that make up this body.
+ * The first body in the array must always be a self reference to the current body instance.
+ * All bodies in the `parts` array together form a single rigid compound body.
+ * Parts are allowed to overlap, have gaps or holes or even form concave bodies.
+ * Parts themselves should never be added to a `World`, only the parent body should be.
+ * Use `Body.setParts` when setting parts to ensure correct updates of all properties.
+ *
+ * @readOnly
+ * @property parts
+ * @type body[]
+ */
+
+ /**
+ * An object reserved for storing plugin-specific properties.
+ *
+ * @property plugin
+ * @type {}
+ */
+
+ /**
+ * _Read only_. Updated by `Body.setParts`.
+ *
+ * A reference to the body that this is a part of. See `body.parts`.
+ * This is a self reference if the body is not a part of another body.
+ *
+ * @readOnly
+ * @property parent
+ * @type body
+ */
+
+ /**
+ * A `Number` specifying the angle of the body, in radians.
+ *
+ * @property angle
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * _Read only_. Use `Body.setVertices` or `Body.setParts` to set. See also `Bodies.fromVertices`.
+ *
+ * An array of `Vector` objects that specify the convex hull of the rigid body.
+ * These should be provided about the origin `(0, 0)`. E.g.
+ *
+ * `[{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]`
+ *
+ * Vertices must always be convex, in clockwise order and must not contain any duplicate points.
+ *
+ * Concave vertices should be decomposed into convex `parts`, see `Bodies.fromVertices` and `Body.setParts`.
+ *
+ * When set the vertices are translated such that `body.position` is at the centre of mass.
+ * Many other body properties are automatically calculated from these vertices when set including `density`, `area` and `inertia`.
+ *
+ * The module `Matter.Vertices` contains useful methods for working with vertices.
+ *
+ * @readOnly
+ * @property vertices
+ * @type vector[]
+ */
+
+ /**
+ * _Read only_. Use `Body.setPosition` to set.
+ *
+ * A `Vector` that specifies the current world-space position of the body.
+ *
+ * @readOnly
+ * @property position
+ * @type vector
+ * @default { x: 0, y: 0 }
+ */
+
+ /**
+ * A `Vector` that accumulates the total force applied to the body for a single update.
+ * Force is zeroed after every `Engine.update`, so constant forces should be applied for every update they are needed. See also `Body.applyForce`.
+ *
+ * @property force
+ * @type vector
+ * @default { x: 0, y: 0 }
+ */
+
+ /**
+ * A `Number` that accumulates the total torque (turning force) applied to the body for a single update. See also `Body.applyForce`.
+ * Torque is zeroed after every `Engine.update`, so constant torques should be applied for every update they are needed.
+ *
+ * Torques result in angular acceleration on every update, which depends on body inertia and the engine update delta.
+ *
+ * @property torque
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * _Read only_. Use `Body.setSpeed` to set.
+ *
+ * See `Body.getSpeed` for details.
+ *
+ * Equivalent to the magnitude of `body.velocity` (always positive).
+ *
+ * @readOnly
+ * @property speed
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * _Read only_. Use `Body.setVelocity` to set.
+ *
+ * See `Body.getVelocity` for details.
+ *
+ * Equivalent to the magnitude of `body.angularVelocity` (always positive).
+ *
+ * @readOnly
+ * @property velocity
+ * @type vector
+ * @default { x: 0, y: 0 }
+ */
+
+ /**
+ * _Read only_. Use `Body.setAngularSpeed` to set.
+ *
+ * See `Body.getAngularSpeed` for details.
+ *
+ *
+ * @readOnly
+ * @property angularSpeed
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * _Read only_. Use `Body.setAngularVelocity` to set.
+ *
+ * See `Body.getAngularVelocity` for details.
+ *
+ *
+ * @readOnly
+ * @property angularVelocity
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * _Read only_. Use `Body.setStatic` to set.
+ *
+ * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed.
+ *
+ * @readOnly
+ * @property isStatic
+ * @type boolean
+ * @default false
+ */
+
+ /**
+ * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically.
+ *
+ * @property isSensor
+ * @type boolean
+ * @default false
+ */
+
+ /**
+ * _Read only_. Use `Sleeping.set` to set.
+ *
+ * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken.
+ *
+ * @readOnly
+ * @property isSleeping
+ * @type boolean
+ * @default false
+ */
+
+ /**
+ * _Read only_. Calculated during engine update only when sleeping is enabled.
+ *
+ * A `Number` that loosely measures the amount of movement a body currently has.
+ *
+ * Derived from `body.speed^2 + body.angularSpeed^2`. See `Sleeping.update`.
+ *
+ * @readOnly
+ * @property motion
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that defines the length of time during which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine).
+ *
+ * @property sleepThreshold
+ * @type number
+ * @default 60
+ */
+
+ /**
+ * _Read only_. Use `Body.setDensity` to set.
+ *
+ * A `Number` that defines the density of the body (mass per unit area).
+ *
+ * Mass will also be updated when set.
+ *
+ * @readOnly
+ * @property density
+ * @type number
+ * @default 0.001
+ */
+
+ /**
+ * _Read only_. Use `Body.setMass` to set.
+ *
+ * A `Number` that defines the mass of the body.
+ *
+ * Density will also be updated when set.
+ *
+ * @readOnly
+ * @property mass
+ * @type number
+ */
+
+ /**
+ * _Read only_. Use `Body.setMass` to set.
+ *
+ * A `Number` that defines the inverse mass of the body (`1 / mass`).
+ *
+ * @readOnly
+ * @property inverseMass
+ * @type number
+ */
+
+ /**
+ * _Read only_. Automatically calculated when vertices, mass or density are set or set through `Body.setInertia`.
+ *
+ * A `Number` that defines the moment of inertia of the body. This is the second moment of area in two dimensions.
+ *
+ * Can be manually set to `Infinity` to prevent rotation of the body. See `Body.setInertia`.
+ *
+ * @readOnly
+ * @property inertia
+ * @type number
+ */
+
+ /**
+ * _Read only_. Automatically calculated when vertices, mass or density are set or calculated by `Body.setInertia`.
+ *
+ * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`).
+ *
+ * @readOnly
+ * @property inverseInertia
+ * @type number
+ */
+
+ /**
+ * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`.
+ * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur.
+ * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy.
+ * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula:
+ *
+ * `Math.max(bodyA.restitution, bodyB.restitution)`
+ *
+ * @property restitution
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`.
+ * A value of `0` means that the body may slide indefinitely.
+ * A value of `1` means the body may come to a stop almost instantly after a force is applied.
+ *
+ * The effects of the value may be non-linear.
+ * High values may be unstable depending on the body.
+ * The engine uses a Coulomb friction model including static and kinetic friction.
+ * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula:
+ *
+ * `Math.min(bodyA.friction, bodyB.friction)`
+ *
+ * @property friction
+ * @type number
+ * @default 0.1
+ */
+
+ /**
+ * A `Number` that defines the static friction of the body (in the Coulomb friction model).
+ * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used.
+ * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary.
+ * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction.
+ *
+ * @property frictionStatic
+ * @type number
+ * @default 0.5
+ */
+
+ /**
+ * A `Number` that defines the air friction of the body (air resistance).
+ * A value of `0` means the body will never slow as it moves through space.
+ * The higher the value, the faster a body slows when moving through space.
+ * The effects of the value are non-linear.
+ *
+ * @property frictionAir
+ * @type number
+ * @default 0.01
+ */
+
+ /**
+ * An `Object` that specifies the collision filtering properties of this body.
+ *
+ * Collisions between two bodies will obey the following rules:
+ * - If the two bodies have the same non-zero value of `collisionFilter.group`,
+ * they will always collide if the value is positive, and they will never collide
+ * if the value is negative.
+ * - If the two bodies have different values of `collisionFilter.group` or if one
+ * (or both) of the bodies has a value of 0, then the category/mask rules apply as follows:
+ *
+ * Each body belongs to a collision category, given by `collisionFilter.category`. This
+ * value is used as a bit field and the category should have only one bit set, meaning that
+ * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32
+ * different collision categories available.
+ *
+ * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies
+ * the categories it collides with (the value is the bitwise AND value of all these categories).
+ *
+ * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's
+ * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0`
+ * are both true.
+ *
+ * @property collisionFilter
+ * @type object
+ */
+
+ /**
+ * An Integer `Number`, that specifies the collision group this body belongs to.
+ * See `body.collisionFilter` for more information.
+ *
+ * @property collisionFilter.group
+ * @type object
+ * @default 0
+ */
+
+ /**
+ * A bit field that specifies the collision category this body belongs to.
+ * The category value should have only one bit set, for example `0x0001`.
+ * This means there are up to 32 unique collision categories available.
+ * See `body.collisionFilter` for more information.
+ *
+ * @property collisionFilter.category
+ * @type object
+ * @default 1
+ */
+
+ /**
+ * A bit mask that specifies the collision categories this body may collide with.
+ * See `body.collisionFilter` for more information.
+ *
+ * @property collisionFilter.mask
+ * @type object
+ * @default -1
+ */
+
+ /**
+ * A `Number` that specifies a thin boundary around the body where it is allowed to slightly sink into other bodies.
+ *
+ * This is required for proper collision response, including friction and restitution effects.
+ *
+ * The default should generally suffice in most cases. You may need to decrease this value for very small bodies that are nearing the default value in scale.
+ *
+ * @property slop
+ * @type number
+ * @default 0.05
+ */
+
+ /**
+ * A `Number` that specifies per-body time scaling.
+ *
+ * @property timeScale
+ * @type number
+ * @default 1
+ */
+
+ /**
+ * _Read only_. Updated during engine update.
+ *
+ * A `Number` that records the last delta time value used to update this body.
+ * Used to calculate speed and velocity.
+ *
+ * @readOnly
+ * @property deltaTime
+ * @type number
+ * @default 1000 / 60
+ */
+
+ /**
+ * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
+ *
+ * @property render
+ * @type object
+ */
+
+ /**
+ * A flag that indicates if the body should be rendered.
+ *
+ * @property render.visible
+ * @type boolean
+ * @default true
+ */
+
+ /**
+ * Sets the opacity to use when rendering.
+ *
+ * @property render.opacity
+ * @type number
+ * @default 1
+ */
+
+ /**
+ * An `Object` that defines the sprite properties to use when rendering, if any.
+ *
+ * @property render.sprite
+ * @type object
+ */
+
+ /**
+ * An `String` that defines the path to the image to use as the sprite texture, if any.
+ *
+ * @property render.sprite.texture
+ * @type string
+ */
+
+ /**
+ * A `Number` that defines the scaling in the x-axis for the sprite, if any.
+ *
+ * @property render.sprite.xScale
+ * @type number
+ * @default 1
+ */
+
+ /**
+ * A `Number` that defines the scaling in the y-axis for the sprite, if any.
+ *
+ * @property render.sprite.yScale
+ * @type number
+ * @default 1
+ */
+
+ /**
+ * A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width).
+ *
+ * @property render.sprite.xOffset
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that defines the offset in the y-axis for the sprite (normalised by texture height).
+ *
+ * @property render.sprite.yOffset
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that defines the line width to use when rendering the body outline (if a sprite is not defined).
+ * A value of `0` means no outline will be rendered.
+ *
+ * @property render.lineWidth
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `String` that defines the fill style to use when rendering the body (if a sprite is not defined).
+ * It is the same as when using a canvas, so it accepts CSS style property values.
+ *
+ * @property render.fillStyle
+ * @type string
+ * @default a random colour
+ */
+
+ /**
+ * A `String` that defines the stroke style to use when rendering the body outline (if a sprite is not defined).
+ * It is the same as when using a canvas, so it accepts CSS style property values.
+ *
+ * @property render.strokeStyle
+ * @type string
+ * @default a random colour
+ */
+
+ /**
+ * _Read only_. Calculated automatically when vertices are set.
+ *
+ * An array of unique axis vectors (edge normals) used for collision detection.
+ * These are automatically calculated when vertices are set.
+ * They are constantly updated by `Body.update` during the simulation.
+ *
+ * @readOnly
+ * @property axes
+ * @type vector[]
+ */
+
+ /**
+ * _Read only_. Calculated automatically when vertices are set.
+ *
+ * A `Number` that measures the area of the body's convex hull.
+ *
+ * @readOnly
+ * @property area
+ * @type string
+ * @default
+ */
+
+ /**
+ * A `Bounds` object that defines the AABB region for the body.
+ * It is automatically calculated when vertices are set and constantly updated by `Body.update` during simulation.
+ *
+ * @property bounds
+ * @type bounds
+ */
+
+})();
+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
/**
* The `Matter.Events` module contains methods to fire and listen to events on other objects.
*
@@ -1694,7 +3142,7 @@ var Common = __webpack_require__(0);
/***/ }),
-/* 5 */
+/* 6 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -1714,10 +3162,10 @@ var Composite = {};
module.exports = Composite;
-var Events = __webpack_require__(4);
+var Events = __webpack_require__(5);
var Common = __webpack_require__(0);
var Bounds = __webpack_require__(1);
-var Body = __webpack_require__(6);
+var Body = __webpack_require__(4);
(function() {
@@ -2421,1247 +3869,6 @@ var Body = __webpack_require__(6);
})();
-/***/ }),
-/* 6 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.Body` module contains methods for creating and manipulating body models.
-* A `Matter.Body` is a rigid body that can be simulated by a `Matter.Engine`.
-* Factories for commonly used body configurations (such as rectangles, circles and other polygons) can be found in the module `Matter.Bodies`.
-*
-* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
-
-* @class Body
-*/
-
-var Body = {};
-
-module.exports = Body;
-
-var Vertices = __webpack_require__(3);
-var Vector = __webpack_require__(2);
-var Sleeping = __webpack_require__(7);
-var Render = __webpack_require__(16);
-var Common = __webpack_require__(0);
-var Bounds = __webpack_require__(1);
-var Axes = __webpack_require__(11);
-
-(function() {
-
- Body._inertiaScale = 4;
- Body._nextCollidingGroupId = 1;
- Body._nextNonCollidingGroupId = -1;
- Body._nextCategory = 0x0001;
-
- /**
- * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults.
- * All properties have default values, and many are pre-calculated automatically based on other properties.
- * Vertices must be specified in clockwise order.
- * See the properties section below for detailed information on what you can pass via the `options` object.
- * @method create
- * @param {} options
- * @return {body} body
- */
- Body.create = function(options) {
- var defaults = {
- id: Common.nextId(),
- type: 'body',
- label: 'Body',
- parts: [],
- plugin: {},
- angle: 0,
- vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
- position: { x: 0, y: 0 },
- force: { x: 0, y: 0 },
- torque: 0,
- positionImpulse: { x: 0, y: 0 },
- constraintImpulse: { x: 0, y: 0, angle: 0 },
- totalContacts: 0,
- speed: 0,
- angularSpeed: 0,
- velocity: { x: 0, y: 0 },
- angularVelocity: 0,
- isSensor: false,
- isStatic: false,
- isSleeping: false,
- motion: 0,
- sleepThreshold: 60,
- density: 0.001,
- restitution: 0,
- friction: 0.1,
- frictionStatic: 0.5,
- frictionAir: 0.01,
- collisionFilter: {
- category: 0x0001,
- mask: 0xFFFFFFFF,
- group: 0
- },
- slop: 0.05,
- timeScale: 1,
- render: {
- visible: true,
- opacity: 1,
- strokeStyle: null,
- fillStyle: null,
- lineWidth: null,
- sprite: {
- xScale: 1,
- yScale: 1,
- xOffset: 0,
- yOffset: 0
- }
- },
- events: null,
- bounds: null,
- chamfer: null,
- circleRadius: 0,
- positionPrev: null,
- anglePrev: 0,
- parent: null,
- axes: null,
- area: 0,
- mass: 0,
- inertia: 0,
- _original: null
- };
-
- var body = Common.extend(defaults, options);
-
- _initProperties(body, options);
-
- return body;
- };
-
- /**
- * Returns the next unique group index for which bodies will collide.
- * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide.
- * See `body.collisionFilter` for more information.
- * @method nextGroup
- * @param {bool} [isNonColliding=false]
- * @return {Number} Unique group index
- */
- Body.nextGroup = function(isNonColliding) {
- if (isNonColliding)
- return Body._nextNonCollidingGroupId--;
-
- return Body._nextCollidingGroupId++;
- };
-
- /**
- * Returns the next unique category bitfield (starting after the initial default category `0x0001`).
- * There are 32 available. See `body.collisionFilter` for more information.
- * @method nextCategory
- * @return {Number} Unique category bitfield
- */
- Body.nextCategory = function() {
- Body._nextCategory = Body._nextCategory << 1;
- return Body._nextCategory;
- };
-
- /**
- * Initialises body properties.
- * @method _initProperties
- * @private
- * @param {body} body
- * @param {} [options]
- */
- var _initProperties = function(body, options) {
- options = options || {};
-
- // init required properties (order is important)
- Body.set(body, {
- bounds: body.bounds || Bounds.create(body.vertices),
- positionPrev: body.positionPrev || Vector.clone(body.position),
- anglePrev: body.anglePrev || body.angle,
- vertices: body.vertices,
- parts: body.parts || [body],
- isStatic: body.isStatic,
- isSleeping: body.isSleeping,
- parent: body.parent || body
- });
-
- Vertices.rotate(body.vertices, body.angle, body.position);
- Axes.rotate(body.axes, body.angle);
- Bounds.update(body.bounds, body.vertices, body.velocity);
-
- // allow options to override the automatically calculated properties
- Body.set(body, {
- axes: options.axes || body.axes,
- area: options.area || body.area,
- mass: options.mass || body.mass,
- inertia: options.inertia || body.inertia
- });
-
- // render properties
- var defaultFillStyle = (body.isStatic ? '#14151f' : Common.choose(['#f19648', '#f5d259', '#f55a3c', '#063e7b', '#ececd1'])),
- defaultStrokeStyle = body.isStatic ? '#555' : '#ccc',
- defaultLineWidth = body.isStatic && body.render.fillStyle === null ? 1 : 0;
- body.render.fillStyle = body.render.fillStyle || defaultFillStyle;
- body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle;
- body.render.lineWidth = body.render.lineWidth || defaultLineWidth;
- body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x);
- body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y);
- };
-
- /**
- * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist.
- * Prefer to use the actual setter functions in performance critical situations.
- * @method set
- * @param {body} body
- * @param {} settings A property name (or map of properties and values) to set on the body.
- * @param {} value The value to set if `settings` is a single property name.
- */
- Body.set = function(body, settings, value) {
- var property;
-
- if (typeof settings === 'string') {
- property = settings;
- settings = {};
- settings[property] = value;
- }
-
- for (property in settings) {
- if (!Object.prototype.hasOwnProperty.call(settings, property))
- continue;
-
- value = settings[property];
- switch (property) {
-
- case 'isStatic':
- Body.setStatic(body, value);
- break;
- case 'isSleeping':
- Sleeping.set(body, value);
- break;
- case 'mass':
- Body.setMass(body, value);
- break;
- case 'density':
- Body.setDensity(body, value);
- break;
- case 'inertia':
- Body.setInertia(body, value);
- break;
- case 'vertices':
- Body.setVertices(body, value);
- break;
- case 'position':
- Body.setPosition(body, value);
- break;
- case 'angle':
- Body.setAngle(body, value);
- break;
- case 'velocity':
- Body.setVelocity(body, value);
- break;
- case 'angularVelocity':
- Body.setAngularVelocity(body, value);
- break;
- case 'parts':
- Body.setParts(body, value);
- break;
- case 'centre':
- Body.setCentre(body, value);
- break;
- default:
- body[property] = value;
-
- }
- }
- };
-
- /**
- * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity.
- * @method setStatic
- * @param {body} body
- * @param {bool} isStatic
- */
- Body.setStatic = function(body, isStatic) {
- for (var i = 0; i < body.parts.length; i++) {
- var part = body.parts[i];
- part.isStatic = isStatic;
-
- if (isStatic) {
- part._original = {
- restitution: part.restitution,
- friction: part.friction,
- mass: part.mass,
- inertia: part.inertia,
- density: part.density,
- inverseMass: part.inverseMass,
- inverseInertia: part.inverseInertia
- };
-
- part.restitution = 0;
- part.friction = 1;
- part.mass = part.inertia = part.density = Infinity;
- part.inverseMass = part.inverseInertia = 0;
-
- part.positionPrev.x = part.position.x;
- part.positionPrev.y = part.position.y;
- part.anglePrev = part.angle;
- part.angularVelocity = 0;
- part.speed = 0;
- part.angularSpeed = 0;
- part.motion = 0;
- } else if (part._original) {
- part.restitution = part._original.restitution;
- part.friction = part._original.friction;
- part.mass = part._original.mass;
- part.inertia = part._original.inertia;
- part.density = part._original.density;
- part.inverseMass = part._original.inverseMass;
- part.inverseInertia = part._original.inverseInertia;
-
- part._original = null;
- }
- }
- };
-
- /**
- * Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change.
- * @method setMass
- * @param {body} body
- * @param {number} mass
- */
- Body.setMass = function(body, mass) {
- var moment = body.inertia / (body.mass / 6);
- body.inertia = moment * (mass / 6);
- body.inverseInertia = 1 / body.inertia;
-
- body.mass = mass;
- body.inverseMass = 1 / body.mass;
- body.density = body.mass / body.area;
- };
-
- /**
- * Sets the density of the body. Mass and inertia are automatically updated to reflect the change.
- * @method setDensity
- * @param {body} body
- * @param {number} density
- */
- Body.setDensity = function(body, density) {
- Body.setMass(body, density * body.area);
- body.density = density;
- };
-
- /**
- * Sets the moment of inertia (i.e. second moment of area) of the body.
- * Inverse inertia is automatically updated to reflect the change. Mass is not changed.
- * @method setInertia
- * @param {body} body
- * @param {number} inertia
- */
- Body.setInertia = function(body, inertia) {
- body.inertia = inertia;
- body.inverseInertia = 1 / body.inertia;
- };
-
- /**
- * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`).
- * Vertices will be automatically transformed to be orientated around their centre of mass as the origin.
- * They are then automatically translated to world space based on `body.position`.
- *
- * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array).
- * Vertices must form a convex hull, concave hulls are not supported.
- *
- * @method setVertices
- * @param {body} body
- * @param {vector[]} vertices
- */
- Body.setVertices = function(body, vertices) {
- // change vertices
- if (vertices[0].body === body) {
- body.vertices = vertices;
- } else {
- body.vertices = Vertices.create(vertices, body);
- }
-
- // update properties
- body.axes = Axes.fromVertices(body.vertices);
- body.area = Vertices.area(body.vertices);
- Body.setMass(body, body.density * body.area);
-
- // orient vertices around the centre of mass at origin (0, 0)
- var centre = Vertices.centre(body.vertices);
- Vertices.translate(body.vertices, centre, -1);
-
- // update inertia while vertices are at origin (0, 0)
- Body.setInertia(body, Body._inertiaScale * Vertices.inertia(body.vertices, body.mass));
-
- // update geometry
- Vertices.translate(body.vertices, body.position);
- Bounds.update(body.bounds, body.vertices, body.velocity);
- };
-
- /**
- * Sets the parts of the `body` and updates mass, inertia and centroid.
- * Each part will have its parent set to `body`.
- * By default the convex hull will be automatically computed and set on `body`, unless `autoHull` is set to `false.`
- * Note that this method will ensure that the first part in `body.parts` will always be the `body`.
- * @method setParts
- * @param {body} body
- * @param [body] parts
- * @param {bool} [autoHull=true]
- */
- Body.setParts = function(body, parts, autoHull) {
- var i;
-
- // add all the parts, ensuring that the first part is always the parent body
- parts = parts.slice(0);
- body.parts.length = 0;
- body.parts.push(body);
- body.parent = body;
-
- for (i = 0; i < parts.length; i++) {
- var part = parts[i];
- if (part !== body) {
- part.parent = body;
- body.parts.push(part);
- }
- }
-
- if (body.parts.length === 1)
- return;
-
- autoHull = typeof autoHull !== 'undefined' ? autoHull : true;
-
- // find the convex hull of all parts to set on the parent body
- if (autoHull) {
- var vertices = [];
- for (i = 0; i < parts.length; i++) {
- vertices = vertices.concat(parts[i].vertices);
- }
-
- Vertices.clockwiseSort(vertices);
-
- var hull = Vertices.hull(vertices),
- hullCentre = Vertices.centre(hull);
-
- Body.setVertices(body, hull);
- Vertices.translate(body.vertices, hullCentre);
- }
-
- // sum the properties of all compound parts of the parent body
- var total = Body._totalProperties(body);
-
- body.area = total.area;
- body.parent = body;
- body.position.x = total.centre.x;
- body.position.y = total.centre.y;
- body.positionPrev.x = total.centre.x;
- body.positionPrev.y = total.centre.y;
-
- Body.setMass(body, total.mass);
- Body.setInertia(body, total.inertia);
- Body.setPosition(body, total.centre);
- };
-
- /**
- * Set the centre of mass of the body.
- * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation.
- * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density.
- * This is equal to moving `body.position` but not the `body.vertices`.
- * Invalid if the `centre` falls outside the body's convex hull.
- * @method setCentre
- * @param {body} body
- * @param {vector} centre
- * @param {bool} relative
- */
- Body.setCentre = function(body, centre, relative) {
- if (!relative) {
- body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x);
- body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y);
- body.position.x = centre.x;
- body.position.y = centre.y;
- } else {
- body.positionPrev.x += centre.x;
- body.positionPrev.y += centre.y;
- body.position.x += centre.x;
- body.position.y += centre.y;
- }
- };
-
- /**
- * Sets the position of the body instantly. Velocity, angle, force etc. are unchanged.
- * @method setPosition
- * @param {body} body
- * @param {vector} position
- */
- Body.setPosition = function(body, position) {
- var delta = Vector.sub(position, body.position);
- body.positionPrev.x += delta.x;
- body.positionPrev.y += delta.y;
-
- for (var i = 0; i < body.parts.length; i++) {
- var part = body.parts[i];
- part.position.x += delta.x;
- part.position.y += delta.y;
- Vertices.translate(part.vertices, delta);
- Bounds.update(part.bounds, part.vertices, body.velocity);
- }
- };
-
- /**
- * Sets the angle of the body instantly. Angular velocity, position, force etc. are unchanged.
- * @method setAngle
- * @param {body} body
- * @param {number} angle
- */
- Body.setAngle = function(body, angle) {
- var delta = angle - body.angle;
- body.anglePrev += delta;
-
- for (var i = 0; i < body.parts.length; i++) {
- var part = body.parts[i];
- part.angle += delta;
- Vertices.rotate(part.vertices, delta, body.position);
- Axes.rotate(part.axes, delta);
- Bounds.update(part.bounds, part.vertices, body.velocity);
- if (i > 0) {
- Vector.rotateAbout(part.position, delta, body.position, part.position);
- }
- }
- };
-
- /**
- * Sets the linear velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`.
- * @method setVelocity
- * @param {body} body
- * @param {vector} velocity
- */
- Body.setVelocity = function(body, velocity) {
- body.positionPrev.x = body.position.x - velocity.x;
- body.positionPrev.y = body.position.y - velocity.y;
- body.velocity.x = velocity.x;
- body.velocity.y = velocity.y;
- body.speed = Vector.magnitude(body.velocity);
- };
-
- /**
- * Sets the angular velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`.
- * @method setAngularVelocity
- * @param {body} body
- * @param {number} velocity
- */
- Body.setAngularVelocity = function(body, velocity) {
- body.anglePrev = body.angle - velocity;
- body.angularVelocity = velocity;
- body.angularSpeed = Math.abs(body.angularVelocity);
- };
-
- /**
- * Moves a body by a given vector relative to its current position, without imparting any velocity.
- * @method translate
- * @param {body} body
- * @param {vector} translation
- */
- Body.translate = function(body, translation) {
- Body.setPosition(body, Vector.add(body.position, translation));
- };
-
- /**
- * Rotates a body by a given angle relative to its current angle, without imparting any angular velocity.
- * @method rotate
- * @param {body} body
- * @param {number} rotation
- * @param {vector} [point]
- */
- Body.rotate = function(body, rotation, point) {
- if (!point) {
- Body.setAngle(body, body.angle + rotation);
- } else {
- var cos = Math.cos(rotation),
- sin = Math.sin(rotation),
- dx = body.position.x - point.x,
- dy = body.position.y - point.y;
-
- Body.setPosition(body, {
- x: point.x + (dx * cos - dy * sin),
- y: point.y + (dx * sin + dy * cos)
- });
-
- Body.setAngle(body, body.angle + rotation);
- }
- };
-
- /**
- * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre).
- * @method scale
- * @param {body} body
- * @param {number} scaleX
- * @param {number} scaleY
- * @param {vector} [point]
- */
- Body.scale = function(body, scaleX, scaleY, point) {
- var totalArea = 0,
- totalInertia = 0;
-
- point = point || body.position;
-
- for (var i = 0; i < body.parts.length; i++) {
- var part = body.parts[i];
-
- // scale vertices
- Vertices.scale(part.vertices, scaleX, scaleY, point);
-
- // update properties
- part.axes = Axes.fromVertices(part.vertices);
- part.area = Vertices.area(part.vertices);
- Body.setMass(part, body.density * part.area);
-
- // update inertia (requires vertices to be at origin)
- Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y });
- Body.setInertia(part, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass));
- Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });
-
- if (i > 0) {
- totalArea += part.area;
- totalInertia += part.inertia;
- }
-
- // scale position
- part.position.x = point.x + (part.position.x - point.x) * scaleX;
- part.position.y = point.y + (part.position.y - point.y) * scaleY;
-
- // update bounds
- Bounds.update(part.bounds, part.vertices, body.velocity);
- }
-
- // handle parent body
- if (body.parts.length > 1) {
- body.area = totalArea;
-
- if (!body.isStatic) {
- Body.setMass(body, body.density * totalArea);
- Body.setInertia(body, totalInertia);
- }
- }
-
- // handle circles
- if (body.circleRadius) {
- if (scaleX === scaleY) {
- body.circleRadius *= scaleX;
- } else {
- // body is no longer a circle
- body.circleRadius = null;
- }
- }
- };
-
- /**
- * Performs a simulation step for the given `body`, including updating position and angle using Verlet integration.
- * @method update
- * @param {body} body
- * @param {number} deltaTime
- * @param {number} timeScale
- * @param {number} correction
- */
- Body.update = function(body, deltaTime, timeScale, correction) {
- var deltaTimeSquared = Math.pow(deltaTime * timeScale * body.timeScale, 2);
-
- // from the previous step
- var frictionAir = 1 - body.frictionAir * timeScale * body.timeScale,
- velocityPrevX = body.position.x - body.positionPrev.x,
- velocityPrevY = body.position.y - body.positionPrev.y;
-
- // update velocity with Verlet integration
- body.velocity.x = (velocityPrevX * frictionAir * correction) + (body.force.x / body.mass) * deltaTimeSquared;
- body.velocity.y = (velocityPrevY * frictionAir * correction) + (body.force.y / body.mass) * deltaTimeSquared;
-
- body.positionPrev.x = body.position.x;
- body.positionPrev.y = body.position.y;
- body.position.x += body.velocity.x;
- body.position.y += body.velocity.y;
-
- // update angular velocity with Verlet integration
- body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;
- body.anglePrev = body.angle;
- body.angle += body.angularVelocity;
-
- // track speed and acceleration
- body.speed = Vector.magnitude(body.velocity);
- body.angularSpeed = Math.abs(body.angularVelocity);
-
- // transform the body geometry
- for (var i = 0; i < body.parts.length; i++) {
- var part = body.parts[i];
-
- Vertices.translate(part.vertices, body.velocity);
-
- if (i > 0) {
- part.position.x += body.velocity.x;
- part.position.y += body.velocity.y;
- }
-
- if (body.angularVelocity !== 0) {
- Vertices.rotate(part.vertices, body.angularVelocity, body.position);
- Axes.rotate(part.axes, body.angularVelocity);
- if (i > 0) {
- Vector.rotateAbout(part.position, body.angularVelocity, body.position, part.position);
- }
- }
-
- Bounds.update(part.bounds, part.vertices, body.velocity);
- }
- };
-
- /**
- * Applies a force to a body from a given world-space position, including resulting torque.
- * @method applyForce
- * @param {body} body
- * @param {vector} position
- * @param {vector} force
- */
- Body.applyForce = function(body, position, force) {
- body.force.x += force.x;
- body.force.y += force.y;
- var offset = { x: position.x - body.position.x, y: position.y - body.position.y };
- body.torque += offset.x * force.y - offset.y * force.x;
- };
-
- /**
- * Returns the sums of the properties of all compound parts of the parent body.
- * @method _totalProperties
- * @private
- * @param {body} body
- * @return {}
- */
- Body._totalProperties = function(body) {
- // from equations at:
- // https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory
- // http://output.to/sideway/default.asp?qno=121100087
-
- var properties = {
- mass: 0,
- area: 0,
- inertia: 0,
- centre: { x: 0, y: 0 }
- };
-
- // sum the properties of all compound parts of the parent body
- for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
- var part = body.parts[i],
- mass = part.mass !== Infinity ? part.mass : 1;
-
- properties.mass += mass;
- properties.area += part.area;
- properties.inertia += part.inertia;
- properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass));
- }
-
- properties.centre = Vector.div(properties.centre, properties.mass);
-
- return properties;
- };
-
- /*
- *
- * Events Documentation
- *
- */
-
- /**
- * Fired when a body starts sleeping (where `this` is the body).
- *
- * @event sleepStart
- * @this {body} The body that has started sleeping
- * @param {} event An event object
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired when a body ends sleeping (where `this` is the body).
- *
- * @event sleepEnd
- * @this {body} The body that has ended sleeping
- * @param {} event An event object
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /*
- *
- * Properties Documentation
- *
- */
-
- /**
- * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`.
- *
- * @property id
- * @type number
- */
-
- /**
- * A `String` denoting the type of object.
- *
- * @property type
- * @type string
- * @default "body"
- * @readOnly
- */
-
- /**
- * An arbitrary `String` name to help the user identify and manage bodies.
- *
- * @property label
- * @type string
- * @default "Body"
- */
-
- /**
- * An array of bodies that make up this body.
- * The first body in the array must always be a self reference to the current body instance.
- * All bodies in the `parts` array together form a single rigid compound body.
- * Parts are allowed to overlap, have gaps or holes or even form concave bodies.
- * Parts themselves should never be added to a `World`, only the parent body should be.
- * Use `Body.setParts` when setting parts to ensure correct updates of all properties.
- *
- * @property parts
- * @type body[]
- */
-
- /**
- * An object reserved for storing plugin-specific properties.
- *
- * @property plugin
- * @type {}
- */
-
- /**
- * A self reference if the body is _not_ a part of another body.
- * Otherwise this is a reference to the body that this is a part of.
- * See `body.parts`.
- *
- * @property parent
- * @type body
- */
-
- /**
- * A `Number` specifying the angle of the body, in radians.
- *
- * @property angle
- * @type number
- * @default 0
- */
-
- /**
- * An array of `Vector` objects that specify the convex hull of the rigid body.
- * These should be provided about the origin `(0, 0)`. E.g.
- *
- * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]
- *
- * When passed via `Body.create`, the vertices are translated relative to `body.position` (i.e. world-space, and constantly updated by `Body.update` during simulation).
- * The `Vector` objects are also augmented with additional properties required for efficient collision detection.
- *
- * Other properties such as `inertia` and `bounds` are automatically calculated from the passed vertices (unless provided via `options`).
- * Concave hulls are not currently supported. The module `Matter.Vertices` contains useful methods for working with vertices.
- *
- * @property vertices
- * @type vector[]
- */
-
- /**
- * A `Vector` that specifies the current world-space position of the body.
- *
- * @property position
- * @type vector
- * @default { x: 0, y: 0 }
- */
-
- /**
- * A `Vector` that specifies the force to apply in the current step. It is zeroed after every `Body.update`. See also `Body.applyForce`.
- *
- * @property force
- * @type vector
- * @default { x: 0, y: 0 }
- */
-
- /**
- * A `Number` that specifies the torque (turning force) to apply in the current step. It is zeroed after every `Body.update`.
- *
- * @property torque
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that _measures_ the current speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.velocity`).
- *
- * @readOnly
- * @property speed
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that _measures_ the current angular speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.angularVelocity`).
- *
- * @readOnly
- * @property angularSpeed
- * @type number
- * @default 0
- */
-
- /**
- * A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only.
- * If you need to modify a body's velocity directly, you should either apply a force or simply change the body's `position` (as the engine uses position-Verlet integration).
- *
- * @readOnly
- * @property velocity
- * @type vector
- * @default { x: 0, y: 0 }
- */
-
- /**
- * A `Number` that _measures_ the current angular velocity of the body after the last `Body.update`. It is read-only.
- * If you need to modify a body's angular velocity directly, you should apply a torque or simply change the body's `angle` (as the engine uses position-Verlet integration).
- *
- * @readOnly
- * @property angularVelocity
- * @type number
- * @default 0
- */
-
- /**
- * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed.
- * If you need to set a body as static after its creation, you should use `Body.setStatic` as this requires more than just setting this flag.
- *
- * @property isStatic
- * @type boolean
- * @default false
- */
-
- /**
- * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically.
- *
- * @property isSensor
- * @type boolean
- * @default false
- */
-
- /**
- * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken.
- * If you need to set a body as sleeping, you should use `Sleeping.set` as this requires more than just setting this flag.
- *
- * @property isSleeping
- * @type boolean
- * @default false
- */
-
- /**
- * A `Number` that _measures_ the amount of movement a body currently has (a combination of `speed` and `angularSpeed`). It is read-only and always positive.
- * It is used and updated by the `Matter.Sleeping` module during simulation to decide if a body has come to rest.
- *
- * @readOnly
- * @property motion
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that defines the number of updates in which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine).
- *
- * @property sleepThreshold
- * @type number
- * @default 60
- */
-
- /**
- * A `Number` that defines the density of the body, that is its mass per unit area.
- * If you pass the density via `Body.create` the `mass` property is automatically calculated for you based on the size (area) of the object.
- * This is generally preferable to simply setting mass and allows for more intuitive definition of materials (e.g. rock has a higher density than wood).
- *
- * @property density
- * @type number
- * @default 0.001
- */
-
- /**
- * A `Number` that defines the mass of the body, although it may be more appropriate to specify the `density` property instead.
- * If you modify this value, you must also modify the `body.inverseMass` property (`1 / mass`).
- *
- * @property mass
- * @type number
- */
-
- /**
- * A `Number` that defines the inverse mass of the body (`1 / mass`).
- * If you modify this value, you must also modify the `body.mass` property.
- *
- * @property inverseMass
- * @type number
- */
-
- /**
- * A `Number` that defines the moment of inertia (i.e. second moment of area) of the body.
- * It is automatically calculated from the given convex hull (`vertices` array) and density in `Body.create`.
- * If you modify this value, you must also modify the `body.inverseInertia` property (`1 / inertia`).
- *
- * @property inertia
- * @type number
- */
-
- /**
- * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`).
- * If you modify this value, you must also modify the `body.inertia` property.
- *
- * @property inverseInertia
- * @type number
- */
-
- /**
- * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`.
- * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur.
- * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy.
- * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula:
- *
- * Math.max(bodyA.restitution, bodyB.restitution)
- *
- * @property restitution
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`.
- * A value of `0` means that the body may slide indefinitely.
- * A value of `1` means the body may come to a stop almost instantly after a force is applied.
- *
- * The effects of the value may be non-linear.
- * High values may be unstable depending on the body.
- * The engine uses a Coulomb friction model including static and kinetic friction.
- * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula:
- *
- * Math.min(bodyA.friction, bodyB.friction)
- *
- * @property friction
- * @type number
- * @default 0.1
- */
-
- /**
- * A `Number` that defines the static friction of the body (in the Coulomb friction model).
- * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used.
- * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary.
- * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction.
- *
- * @property frictionStatic
- * @type number
- * @default 0.5
- */
-
- /**
- * A `Number` that defines the air friction of the body (air resistance).
- * A value of `0` means the body will never slow as it moves through space.
- * The higher the value, the faster a body slows when moving through space.
- * The effects of the value are non-linear.
- *
- * @property frictionAir
- * @type number
- * @default 0.01
- */
-
- /**
- * An `Object` that specifies the collision filtering properties of this body.
- *
- * Collisions between two bodies will obey the following rules:
- * - If the two bodies have the same non-zero value of `collisionFilter.group`,
- * they will always collide if the value is positive, and they will never collide
- * if the value is negative.
- * - If the two bodies have different values of `collisionFilter.group` or if one
- * (or both) of the bodies has a value of 0, then the category/mask rules apply as follows:
- *
- * Each body belongs to a collision category, given by `collisionFilter.category`. This
- * value is used as a bit field and the category should have only one bit set, meaning that
- * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32
- * different collision categories available.
- *
- * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies
- * the categories it collides with (the value is the bitwise AND value of all these categories).
- *
- * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's
- * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0`
- * are both true.
- *
- * @property collisionFilter
- * @type object
- */
-
- /**
- * An Integer `Number`, that specifies the collision group this body belongs to.
- * See `body.collisionFilter` for more information.
- *
- * @property collisionFilter.group
- * @type object
- * @default 0
- */
-
- /**
- * A bit field that specifies the collision category this body belongs to.
- * The category value should have only one bit set, for example `0x0001`.
- * This means there are up to 32 unique collision categories available.
- * See `body.collisionFilter` for more information.
- *
- * @property collisionFilter.category
- * @type object
- * @default 1
- */
-
- /**
- * A bit mask that specifies the collision categories this body may collide with.
- * See `body.collisionFilter` for more information.
- *
- * @property collisionFilter.mask
- * @type object
- * @default -1
- */
-
- /**
- * A `Number` that specifies a tolerance on how far a body is allowed to 'sink' or rotate into other bodies.
- * Avoid changing this value unless you understand the purpose of `slop` in physics engines.
- * The default should generally suffice, although very large bodies may require larger values for stable stacking.
- *
- * @property slop
- * @type number
- * @default 0.05
- */
-
- /**
- * A `Number` that allows per-body time scaling, e.g. a force-field where bodies inside are in slow-motion, while others are at full speed.
- *
- * @property timeScale
- * @type number
- * @default 1
- */
-
- /**
- * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
- *
- * @property render
- * @type object
- */
-
- /**
- * A flag that indicates if the body should be rendered.
- *
- * @property render.visible
- * @type boolean
- * @default true
- */
-
- /**
- * Sets the opacity to use when rendering.
- *
- * @property render.opacity
- * @type number
- * @default 1
- */
-
- /**
- * An `Object` that defines the sprite properties to use when rendering, if any.
- *
- * @property render.sprite
- * @type object
- */
-
- /**
- * An `String` that defines the path to the image to use as the sprite texture, if any.
- *
- * @property render.sprite.texture
- * @type string
- */
-
- /**
- * A `Number` that defines the scaling in the x-axis for the sprite, if any.
- *
- * @property render.sprite.xScale
- * @type number
- * @default 1
- */
-
- /**
- * A `Number` that defines the scaling in the y-axis for the sprite, if any.
- *
- * @property render.sprite.yScale
- * @type number
- * @default 1
- */
-
- /**
- * A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width).
- *
- * @property render.sprite.xOffset
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that defines the offset in the y-axis for the sprite (normalised by texture height).
- *
- * @property render.sprite.yOffset
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that defines the line width to use when rendering the body outline (if a sprite is not defined).
- * A value of `0` means no outline will be rendered.
- *
- * @property render.lineWidth
- * @type number
- * @default 0
- */
-
- /**
- * A `String` that defines the fill style to use when rendering the body (if a sprite is not defined).
- * It is the same as when using a canvas, so it accepts CSS style property values.
- *
- * @property render.fillStyle
- * @type string
- * @default a random colour
- */
-
- /**
- * A `String` that defines the stroke style to use when rendering the body outline (if a sprite is not defined).
- * It is the same as when using a canvas, so it accepts CSS style property values.
- *
- * @property render.strokeStyle
- * @type string
- * @default a random colour
- */
-
- /**
- * An array of unique axis vectors (edge normals) used for collision detection.
- * These are automatically calculated from the given convex hull (`vertices` array) in `Body.create`.
- * They are constantly updated by `Body.update` during the simulation.
- *
- * @property axes
- * @type vector[]
- */
-
- /**
- * A `Number` that _measures_ the area of the body's convex hull, calculated at creation by `Body.create`.
- *
- * @property area
- * @type string
- * @default
- */
-
- /**
- * A `Bounds` object that defines the AABB region for the body.
- * It is automatically calculated from the given convex hull (`vertices` array) in `Body.create` and constantly updated by `Body.update` during simulation.
- *
- * @property bounds
- * @type bounds
- */
-
-})();
-
-
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
@@ -3676,7 +3883,9 @@ var Sleeping = {};
module.exports = Sleeping;
-var Events = __webpack_require__(4);
+var Body = __webpack_require__(4);
+var Events = __webpack_require__(5);
+var Common = __webpack_require__(0);
(function() {
@@ -3688,15 +3897,18 @@ var Events = __webpack_require__(4);
* Puts bodies to sleep or wakes them up depending on their motion.
* @method update
* @param {body[]} bodies
- * @param {number} timeScale
+ * @param {number} delta
*/
- Sleeping.update = function(bodies, timeScale) {
- var timeFactor = timeScale * timeScale * timeScale;
-
+ Sleeping.update = function(bodies, delta) {
+ var timeScale = delta / Common._baseDelta,
+ motionSleepThreshold = Sleeping._motionSleepThreshold;
+
// update bodies sleeping status
for (var i = 0; i < bodies.length; i++) {
var body = bodies[i],
- motion = body.speed * body.speed + body.angularSpeed * body.angularSpeed;
+ speed = Body.getSpeed(body),
+ angularSpeed = Body.getAngularSpeed(body),
+ motion = speed * speed + angularSpeed * angularSpeed;
// wake up bodies if they have a force applied
if (body.force.x !== 0 || body.force.y !== 0) {
@@ -3709,12 +3921,13 @@ var Events = __webpack_require__(4);
// biased average motion estimation between frames
body.motion = Sleeping._minBias * minMotion + (1 - Sleeping._minBias) * maxMotion;
-
- if (body.sleepThreshold > 0 && body.motion < Sleeping._motionSleepThreshold * timeFactor) {
+
+ if (body.sleepThreshold > 0 && body.motion < motionSleepThreshold) {
body.sleepCounter += 1;
- if (body.sleepCounter >= body.sleepThreshold)
+ if (body.sleepCounter >= body.sleepThreshold / timeScale) {
Sleeping.set(body, true);
+ }
} else if (body.sleepCounter > 0) {
body.sleepCounter -= 1;
}
@@ -3725,10 +3938,9 @@ var Events = __webpack_require__(4);
* Given a set of colliding pairs, wakes the sleeping bodies involved.
* @method afterCollisions
* @param {pair[]} pairs
- * @param {number} timeScale
*/
- Sleeping.afterCollisions = function(pairs, timeScale) {
- var timeFactor = timeScale * timeScale * timeScale;
+ Sleeping.afterCollisions = function(pairs) {
+ var motionSleepThreshold = Sleeping._motionSleepThreshold;
// wake up bodies involved in collisions
for (var i = 0; i < pairs.length; i++) {
@@ -3750,7 +3962,7 @@ var Events = __webpack_require__(4);
var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB,
movingBody = sleepingBody === bodyA ? bodyB : bodyA;
- if (!sleepingBody.isStatic && movingBody.motion > Sleeping._motionWakeThreshold * timeFactor) {
+ if (!sleepingBody.isStatic && movingBody.motion > motionSleepThreshold) {
Sleeping.set(sleepingBody, false);
}
}
@@ -4225,7 +4437,7 @@ var Pair = {};
module.exports = Pair;
-var Contact = __webpack_require__(17);
+var Contact = __webpack_require__(16);
(function() {
@@ -4457,9 +4669,11 @@ var Common = __webpack_require__(0);
* @private
* @method solveAll
* @param {constraint[]} constraints
- * @param {number} timeScale
+ * @param {number} delta
*/
- Constraint.solveAll = function(constraints, timeScale) {
+ Constraint.solveAll = function(constraints, delta) {
+ var timeScale = Common.clamp(delta / Common._baseDelta, 0, 1);
+
// Solve fixed constraints first.
for (var i = 0; i < constraints.length; i += 1) {
var constraint = constraints[i],
@@ -4530,7 +4744,10 @@ var Common = __webpack_require__(0);
// solve distance constraint with Gauss-Siedel method
var difference = (currentLength - constraint.length) / currentLength,
- stiffness = constraint.stiffness < 1 ? constraint.stiffness * timeScale : constraint.stiffness,
+ isRigid = constraint.stiffness >= 1 || constraint.length === 0,
+ stiffness = isRigid ? constraint.stiffness * timeScale
+ : constraint.stiffness * timeScale * timeScale,
+ damping = constraint.damping * timeScale,
force = Vector.mult(delta, difference * stiffness),
massTotal = (bodyA ? bodyA.inverseMass : 0) + (bodyB ? bodyB.inverseMass : 0),
inertiaTotal = (bodyA ? bodyA.inverseInertia : 0) + (bodyB ? bodyB.inverseInertia : 0),
@@ -4540,8 +4757,8 @@ var Common = __webpack_require__(0);
normal,
normalVelocity,
relativeVelocity;
-
- if (constraint.damping) {
+
+ if (damping > 0) {
var zero = Vector.create();
normal = Vector.div(delta, currentLength);
@@ -4565,9 +4782,9 @@ var Common = __webpack_require__(0);
bodyA.position.y -= force.y * share;
// apply damping
- if (constraint.damping) {
- bodyA.positionPrev.x -= constraint.damping * normal.x * normalVelocity * share;
- bodyA.positionPrev.y -= constraint.damping * normal.y * normalVelocity * share;
+ if (damping > 0) {
+ bodyA.positionPrev.x -= damping * normal.x * normalVelocity * share;
+ bodyA.positionPrev.y -= damping * normal.y * normalVelocity * share;
}
// apply torque
@@ -4588,9 +4805,9 @@ var Common = __webpack_require__(0);
bodyB.position.y += force.y * share;
// apply damping
- if (constraint.damping) {
- bodyB.positionPrev.x += constraint.damping * normal.x * normalVelocity * share;
- bodyB.positionPrev.y += constraint.damping * normal.y * normalVelocity * share;
+ if (damping > 0) {
+ bodyB.positionPrev.x += damping * normal.x * normalVelocity * share;
+ bodyB.positionPrev.y += damping * normal.y * normalVelocity * share;
}
// apply torque
@@ -4655,8 +4872,10 @@ var Common = __webpack_require__(0);
*/
Constraint.pointAWorld = function(constraint) {
return {
- x: (constraint.bodyA ? constraint.bodyA.position.x : 0) + constraint.pointA.x,
- y: (constraint.bodyA ? constraint.bodyA.position.y : 0) + constraint.pointA.y
+ x: (constraint.bodyA ? constraint.bodyA.position.x : 0)
+ + (constraint.pointA ? constraint.pointA.x : 0),
+ y: (constraint.bodyA ? constraint.bodyA.position.y : 0)
+ + (constraint.pointA ? constraint.pointA.y : 0)
};
};
@@ -4668,8 +4887,10 @@ var Common = __webpack_require__(0);
*/
Constraint.pointBWorld = function(constraint) {
return {
- x: (constraint.bodyB ? constraint.bodyB.position.x : 0) + constraint.pointB.x,
- y: (constraint.bodyB ? constraint.bodyB.position.y : 0) + constraint.pointB.y
+ x: (constraint.bodyB ? constraint.bodyB.position.x : 0)
+ + (constraint.pointB ? constraint.pointB.x : 0),
+ y: (constraint.bodyB ? constraint.bodyB.position.y : 0)
+ + (constraint.pointB ? constraint.pointB.y : 0)
};
};
@@ -4917,7 +5138,7 @@ module.exports = Bodies;
var Vertices = __webpack_require__(3);
var Common = __webpack_require__(0);
-var Body = __webpack_require__(6);
+var Body = __webpack_require__(4);
var Bounds = __webpack_require__(1);
var Vector = __webpack_require__(2);
@@ -5264,6 +5485,202 @@ var Vector = __webpack_require__(2);
/* 13 */
/***/ (function(module, exports, __webpack_require__) {
+/**
+* The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm.
+*
+* @class Detector
+*/
+
+var Detector = {};
+
+module.exports = Detector;
+
+var Common = __webpack_require__(0);
+var Collision = __webpack_require__(8);
+
+(function() {
+
+ /**
+ * Creates a new collision detector.
+ * @method create
+ * @param {} options
+ * @return {detector} A new collision detector
+ */
+ Detector.create = function(options) {
+ var defaults = {
+ bodies: [],
+ pairs: null
+ };
+
+ return Common.extend(defaults, options);
+ };
+
+ /**
+ * Sets the list of bodies in the detector.
+ * @method setBodies
+ * @param {detector} detector
+ * @param {body[]} bodies
+ */
+ Detector.setBodies = function(detector, bodies) {
+ detector.bodies = bodies.slice(0);
+ };
+
+ /**
+ * Clears the detector including its list of bodies.
+ * @method clear
+ * @param {detector} detector
+ */
+ Detector.clear = function(detector) {
+ detector.bodies = [];
+ };
+
+ /**
+ * Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm.
+ *
+ * _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons.
+ * If a specific ordering is required then apply a sort to the resulting array.
+ * @method collisions
+ * @param {detector} detector
+ * @return {collision[]} collisions
+ */
+ Detector.collisions = function(detector) {
+ var collisions = [],
+ pairs = detector.pairs,
+ bodies = detector.bodies,
+ bodiesLength = bodies.length,
+ canCollide = Detector.canCollide,
+ collides = Collision.collides,
+ i,
+ j;
+
+ bodies.sort(Detector._compareBoundsX);
+
+ for (i = 0; i < bodiesLength; i++) {
+ var bodyA = bodies[i],
+ boundsA = bodyA.bounds,
+ boundXMax = bodyA.bounds.max.x,
+ boundYMax = bodyA.bounds.max.y,
+ boundYMin = bodyA.bounds.min.y,
+ bodyAStatic = bodyA.isStatic || bodyA.isSleeping,
+ partsALength = bodyA.parts.length,
+ partsASingle = partsALength === 1;
+
+ for (j = i + 1; j < bodiesLength; j++) {
+ var bodyB = bodies[j],
+ boundsB = bodyB.bounds;
+
+ if (boundsB.min.x > boundXMax) {
+ break;
+ }
+
+ if (boundYMax < boundsB.min.y || boundYMin > boundsB.max.y) {
+ continue;
+ }
+
+ if (bodyAStatic && (bodyB.isStatic || bodyB.isSleeping)) {
+ continue;
+ }
+
+ if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) {
+ continue;
+ }
+
+ var partsBLength = bodyB.parts.length;
+
+ if (partsASingle && partsBLength === 1) {
+ var collision = collides(bodyA, bodyB, pairs);
+
+ if (collision) {
+ collisions.push(collision);
+ }
+ } else {
+ var partsAStart = partsALength > 1 ? 1 : 0,
+ partsBStart = partsBLength > 1 ? 1 : 0;
+
+ for (var k = partsAStart; k < partsALength; k++) {
+ var partA = bodyA.parts[k],
+ boundsA = partA.bounds;
+
+ for (var z = partsBStart; z < partsBLength; z++) {
+ var partB = bodyB.parts[z],
+ boundsB = partB.bounds;
+
+ if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x
+ || boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) {
+ continue;
+ }
+
+ var collision = collides(partA, partB, pairs);
+
+ if (collision) {
+ collisions.push(collision);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return collisions;
+ };
+
+ /**
+ * Returns `true` if both supplied collision filters will allow a collision to occur.
+ * See `body.collisionFilter` for more information.
+ * @method canCollide
+ * @param {} filterA
+ * @param {} filterB
+ * @return {bool} `true` if collision can occur
+ */
+ Detector.canCollide = function(filterA, filterB) {
+ if (filterA.group === filterB.group && filterA.group !== 0)
+ return filterA.group > 0;
+
+ return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0;
+ };
+
+ /**
+ * The comparison function used in the broadphase algorithm.
+ * Returns the signed delta of the bodies bounds on the x-axis.
+ * @private
+ * @method _sortCompare
+ * @param {body} bodyA
+ * @param {body} bodyB
+ * @return {number} The signed delta used for sorting
+ */
+ Detector._compareBoundsX = function(bodyA, bodyB) {
+ return bodyA.bounds.min.x - bodyB.bounds.min.x;
+ };
+
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * The array of `Matter.Body` between which the detector finds collisions.
+ *
+ * _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector.
+ * @property bodies
+ * @type body[]
+ * @default []
+ */
+
+ /**
+ * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
+ * @property pairs
+ * @type {pairs|null}
+ * @default null
+ */
+
+})();
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
/**
* The `Matter.Mouse` module contains methods for creating and manipulating mouse inputs.
*
@@ -5467,202 +5884,6 @@ var Common = __webpack_require__(0);
})();
-/***/ }),
-/* 14 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm.
-*
-* @class Detector
-*/
-
-var Detector = {};
-
-module.exports = Detector;
-
-var Common = __webpack_require__(0);
-var Collision = __webpack_require__(8);
-
-(function() {
-
- /**
- * Creates a new collision detector.
- * @method create
- * @param {} options
- * @return {detector} A new collision detector
- */
- Detector.create = function(options) {
- var defaults = {
- bodies: [],
- pairs: null
- };
-
- return Common.extend(defaults, options);
- };
-
- /**
- * Sets the list of bodies in the detector.
- * @method setBodies
- * @param {detector} detector
- * @param {body[]} bodies
- */
- Detector.setBodies = function(detector, bodies) {
- detector.bodies = bodies.slice(0);
- };
-
- /**
- * Clears the detector including its list of bodies.
- * @method clear
- * @param {detector} detector
- */
- Detector.clear = function(detector) {
- detector.bodies = [];
- };
-
- /**
- * Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm.
- *
- * _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons.
- * If a specific ordering is required then apply a sort to the resulting array.
- * @method collisions
- * @param {detector} detector
- * @return {collision[]} collisions
- */
- Detector.collisions = function(detector) {
- var collisions = [],
- pairs = detector.pairs,
- bodies = detector.bodies,
- bodiesLength = bodies.length,
- canCollide = Detector.canCollide,
- collides = Collision.collides,
- i,
- j;
-
- bodies.sort(Detector._compareBoundsX);
-
- for (i = 0; i < bodiesLength; i++) {
- var bodyA = bodies[i],
- boundsA = bodyA.bounds,
- boundXMax = bodyA.bounds.max.x,
- boundYMax = bodyA.bounds.max.y,
- boundYMin = bodyA.bounds.min.y,
- bodyAStatic = bodyA.isStatic || bodyA.isSleeping,
- partsALength = bodyA.parts.length,
- partsASingle = partsALength === 1;
-
- for (j = i + 1; j < bodiesLength; j++) {
- var bodyB = bodies[j],
- boundsB = bodyB.bounds;
-
- if (boundsB.min.x > boundXMax) {
- break;
- }
-
- if (boundYMax < boundsB.min.y || boundYMin > boundsB.max.y) {
- continue;
- }
-
- if (bodyAStatic && (bodyB.isStatic || bodyB.isSleeping)) {
- continue;
- }
-
- if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) {
- continue;
- }
-
- var partsBLength = bodyB.parts.length;
-
- if (partsASingle && partsBLength === 1) {
- var collision = collides(bodyA, bodyB, pairs);
-
- if (collision) {
- collisions.push(collision);
- }
- } else {
- var partsAStart = partsALength > 1 ? 1 : 0,
- partsBStart = partsBLength > 1 ? 1 : 0;
-
- for (var k = partsAStart; k < partsALength; k++) {
- var partA = bodyA.parts[k],
- boundsA = partA.bounds;
-
- for (var z = partsBStart; z < partsBLength; z++) {
- var partB = bodyB.parts[z],
- boundsB = partB.bounds;
-
- if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x
- || boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) {
- continue;
- }
-
- var collision = collides(partA, partB, pairs);
-
- if (collision) {
- collisions.push(collision);
- }
- }
- }
- }
- }
- }
-
- return collisions;
- };
-
- /**
- * Returns `true` if both supplied collision filters will allow a collision to occur.
- * See `body.collisionFilter` for more information.
- * @method canCollide
- * @param {} filterA
- * @param {} filterB
- * @return {bool} `true` if collision can occur
- */
- Detector.canCollide = function(filterA, filterB) {
- if (filterA.group === filterB.group && filterA.group !== 0)
- return filterA.group > 0;
-
- return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0;
- };
-
- /**
- * The comparison function used in the broadphase algorithm.
- * Returns the signed delta of the bodies bounds on the x-axis.
- * @private
- * @method _sortCompare
- * @param {body} bodyA
- * @param {body} bodyB
- * @return {number} The signed delta used for sorting
- */
- Detector._compareBoundsX = function(bodyA, bodyB) {
- return bodyA.bounds.min.x - bodyB.bounds.min.x;
- };
-
- /*
- *
- * Properties Documentation
- *
- */
-
- /**
- * The array of `Matter.Body` between which the detector finds collisions.
- *
- * _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector.
- * @property bodies
- * @type body[]
- * @default []
- */
-
- /**
- * Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
- * @property pairs
- * @type {pairs|null}
- * @default null
- */
-
-})();
-
-
/***/ }),
/* 15 */
/***/ (function(module, exports, __webpack_require__) {
@@ -6022,6 +6243,2332 @@ var Common = __webpack_require__(0);
/***/ }),
/* 16 */
+/***/ (function(module, exports) {
+
+/**
+* The `Matter.Contact` module contains methods for creating and manipulating collision contacts.
+*
+* @class Contact
+*/
+
+var Contact = {};
+
+module.exports = Contact;
+
+(function() {
+
+ /**
+ * Creates a new contact.
+ * @method create
+ * @param {vertex} vertex
+ * @return {contact} A new contact
+ */
+ Contact.create = function(vertex) {
+ return {
+ vertex: vertex,
+ normalImpulse: 0,
+ tangentImpulse: 0
+ };
+ };
+
+})();
+
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* The `Matter.Engine` module contains methods for creating and manipulating engines.
+* An engine is a controller that manages updating the simulation of the world.
+* See `Matter.Runner` for an optional game loop utility.
+*
+* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
+*
+* @class Engine
+*/
+
+var Engine = {};
+
+module.exports = Engine;
+
+var Sleeping = __webpack_require__(7);
+var Resolver = __webpack_require__(18);
+var Detector = __webpack_require__(13);
+var Pairs = __webpack_require__(19);
+var Events = __webpack_require__(5);
+var Composite = __webpack_require__(6);
+var Constraint = __webpack_require__(10);
+var Common = __webpack_require__(0);
+var Body = __webpack_require__(4);
+
+(function() {
+
+ /**
+ * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults.
+ * All properties have default values, and many are pre-calculated automatically based on other properties.
+ * See the properties section below for detailed information on what you can pass via the `options` object.
+ * @method create
+ * @param {object} [options]
+ * @return {engine} engine
+ */
+ Engine.create = function(options) {
+ options = options || {};
+
+ var defaults = {
+ positionIterations: 6,
+ velocityIterations: 4,
+ constraintIterations: 2,
+ enableSleeping: false,
+ events: [],
+ plugin: {},
+ gravity: {
+ x: 0,
+ y: 1,
+ scale: 0.001
+ },
+ timing: {
+ timestamp: 0,
+ timeScale: 1,
+ lastDelta: 0,
+ lastElapsed: 0
+ }
+ };
+
+ var engine = Common.extend(defaults, options);
+
+ engine.world = options.world || Composite.create({ label: 'World' });
+ engine.pairs = options.pairs || Pairs.create();
+ engine.detector = options.detector || Detector.create();
+
+ // for temporary back compatibility only
+ engine.grid = { buckets: [] };
+ engine.world.gravity = engine.gravity;
+ engine.broadphase = engine.grid;
+ engine.metrics = {};
+
+ return engine;
+ };
+
+ /**
+ * Moves the simulation forward in time by `delta` milliseconds.
+ * Triggers `beforeUpdate` and `afterUpdate` events.
+ * Triggers `collisionStart`, `collisionActive` and `collisionEnd` events.
+ * @method update
+ * @param {engine} engine
+ * @param {number} [delta=16.666]
+ */
+ Engine.update = function(engine, delta) {
+ var startTime = Common.now();
+
+ var world = engine.world,
+ detector = engine.detector,
+ pairs = engine.pairs,
+ timing = engine.timing,
+ timestamp = timing.timestamp,
+ i;
+
+ delta = typeof delta !== 'undefined' ? delta : Common._baseDelta;
+ delta *= timing.timeScale;
+
+ // increment timestamp
+ timing.timestamp += delta;
+ timing.lastDelta = delta;
+
+ // create an event object
+ var event = {
+ timestamp: timing.timestamp,
+ delta: delta
+ };
+
+ Events.trigger(engine, 'beforeUpdate', event);
+
+ // get all bodies and all constraints in the world
+ var allBodies = Composite.allBodies(world),
+ allConstraints = Composite.allConstraints(world);
+
+ // if the world has changed
+ if (world.isModified) {
+ // update the detector bodies
+ Detector.setBodies(detector, allBodies);
+
+ // reset all composite modified flags
+ Composite.setModified(world, false, false, true);
+ }
+
+ // update sleeping if enabled
+ if (engine.enableSleeping)
+ Sleeping.update(allBodies, delta);
+
+ // apply gravity to all bodies
+ Engine._bodiesApplyGravity(allBodies, engine.gravity);
+
+ // update all body position and rotation by integration
+ if (delta > 0) {
+ Engine._bodiesUpdate(allBodies, delta);
+ }
+
+ // update all constraints (first pass)
+ Constraint.preSolveAll(allBodies);
+ for (i = 0; i < engine.constraintIterations; i++) {
+ Constraint.solveAll(allConstraints, delta);
+ }
+ Constraint.postSolveAll(allBodies);
+
+ // find all collisions
+ detector.pairs = engine.pairs;
+ var collisions = Detector.collisions(detector);
+
+ // update collision pairs
+ Pairs.update(pairs, collisions, timestamp);
+
+ // wake up bodies involved in collisions
+ if (engine.enableSleeping)
+ Sleeping.afterCollisions(pairs.list);
+
+ // trigger collision events
+ if (pairs.collisionStart.length > 0)
+ Events.trigger(engine, 'collisionStart', { pairs: pairs.collisionStart });
+
+ // iteratively resolve position between collisions
+ var positionDamping = Common.clamp(20 / engine.positionIterations, 0, 1);
+
+ Resolver.preSolvePosition(pairs.list);
+ for (i = 0; i < engine.positionIterations; i++) {
+ Resolver.solvePosition(pairs.list, delta, positionDamping);
+ }
+ Resolver.postSolvePosition(allBodies);
+
+ // update all constraints (second pass)
+ Constraint.preSolveAll(allBodies);
+ for (i = 0; i < engine.constraintIterations; i++) {
+ Constraint.solveAll(allConstraints, delta);
+ }
+ Constraint.postSolveAll(allBodies);
+
+ // iteratively resolve velocity between collisions
+ Resolver.preSolveVelocity(pairs.list);
+ for (i = 0; i < engine.velocityIterations; i++) {
+ Resolver.solveVelocity(pairs.list, delta);
+ }
+
+ // update body speed and velocity properties
+ Engine._bodiesUpdateVelocities(allBodies);
+
+ // trigger collision events
+ if (pairs.collisionActive.length > 0)
+ Events.trigger(engine, 'collisionActive', { pairs: pairs.collisionActive });
+
+ if (pairs.collisionEnd.length > 0)
+ Events.trigger(engine, 'collisionEnd', { pairs: pairs.collisionEnd });
+
+ // clear force buffers
+ Engine._bodiesClearForces(allBodies);
+
+ Events.trigger(engine, 'afterUpdate', event);
+
+ // log the time elapsed computing this update
+ engine.timing.lastElapsed = Common.now() - startTime;
+
+ return engine;
+ };
+
+ /**
+ * Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`.
+ * @method merge
+ * @param {engine} engineA
+ * @param {engine} engineB
+ */
+ Engine.merge = function(engineA, engineB) {
+ Common.extend(engineA, engineB);
+
+ if (engineB.world) {
+ engineA.world = engineB.world;
+
+ Engine.clear(engineA);
+
+ var bodies = Composite.allBodies(engineA.world);
+
+ for (var i = 0; i < bodies.length; i++) {
+ var body = bodies[i];
+ Sleeping.set(body, false);
+ body.id = Common.nextId();
+ }
+ }
+ };
+
+ /**
+ * Clears the engine pairs and detector.
+ * @method clear
+ * @param {engine} engine
+ */
+ Engine.clear = function(engine) {
+ Pairs.clear(engine.pairs);
+ Detector.clear(engine.detector);
+ };
+
+ /**
+ * Zeroes the `body.force` and `body.torque` force buffers.
+ * @method _bodiesClearForces
+ * @private
+ * @param {body[]} bodies
+ */
+ Engine._bodiesClearForces = function(bodies) {
+ var bodiesLength = bodies.length;
+
+ for (var i = 0; i < bodiesLength; i++) {
+ var body = bodies[i];
+
+ // reset force buffers
+ body.force.x = 0;
+ body.force.y = 0;
+ body.torque = 0;
+ }
+ };
+
+ /**
+ * Applies gravitational acceleration to all `bodies`.
+ * This models a [uniform gravitational field](https://en.wikipedia.org/wiki/Gravity_of_Earth), similar to near the surface of a planet.
+ *
+ * @method _bodiesApplyGravity
+ * @private
+ * @param {body[]} bodies
+ * @param {vector} gravity
+ */
+ Engine._bodiesApplyGravity = function(bodies, gravity) {
+ var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001,
+ bodiesLength = bodies.length;
+
+ if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) {
+ return;
+ }
+
+ for (var i = 0; i < bodiesLength; i++) {
+ var body = bodies[i];
+
+ if (body.isStatic || body.isSleeping)
+ continue;
+
+ // add the resultant force of gravity
+ body.force.y += body.mass * gravity.y * gravityScale;
+ body.force.x += body.mass * gravity.x * gravityScale;
+ }
+ };
+
+ /**
+ * Applies `Body.update` to all given `bodies`.
+ * @method _bodiesUpdate
+ * @private
+ * @param {body[]} bodies
+ * @param {number} delta The amount of time elapsed between updates
+ */
+ Engine._bodiesUpdate = function(bodies, delta) {
+ var bodiesLength = bodies.length;
+
+ for (var i = 0; i < bodiesLength; i++) {
+ var body = bodies[i];
+
+ if (body.isStatic || body.isSleeping)
+ continue;
+
+ Body.update(body, delta);
+ }
+ };
+
+ /**
+ * Applies `Body.updateVelocities` to all given `bodies`.
+ * @method _bodiesUpdateVelocities
+ * @private
+ * @param {body[]} bodies
+ */
+ Engine._bodiesUpdateVelocities = function(bodies) {
+ var bodiesLength = bodies.length;
+
+ for (var i = 0; i < bodiesLength; i++) {
+ Body.updateVelocities(bodies[i]);
+ }
+ };
+
+ /**
+ * A deprecated alias for `Runner.run`, use `Matter.Runner.run(engine)` instead and see `Matter.Runner` for more information.
+ * @deprecated use Matter.Runner.run(engine) instead
+ * @method run
+ * @param {engine} engine
+ */
+
+ /**
+ * Fired just before an update
+ *
+ * @event beforeUpdate
+ * @param {object} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {number} event.delta The delta time in milliseconds value used in the update
+ * @param {engine} event.source The source object of the event
+ * @param {string} event.name The name of the event
+ */
+
+ /**
+ * Fired after engine update and all collision events
+ *
+ * @event afterUpdate
+ * @param {object} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {number} event.delta The delta time in milliseconds value used in the update
+ * @param {engine} event.source The source object of the event
+ * @param {string} event.name The name of the event
+ */
+
+ /**
+ * Fired after engine update, provides a list of all pairs that have started to collide in the current tick (if any)
+ *
+ * @event collisionStart
+ * @param {object} event An event object
+ * @param {pair[]} event.pairs List of affected pairs
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {number} event.delta The delta time in milliseconds value used in the update
+ * @param {engine} event.source The source object of the event
+ * @param {string} event.name The name of the event
+ */
+
+ /**
+ * Fired after engine update, provides a list of all pairs that are colliding in the current tick (if any)
+ *
+ * @event collisionActive
+ * @param {object} event An event object
+ * @param {pair[]} event.pairs List of affected pairs
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {number} event.delta The delta time in milliseconds value used in the update
+ * @param {engine} event.source The source object of the event
+ * @param {string} event.name The name of the event
+ */
+
+ /**
+ * Fired after engine update, provides a list of all pairs that have ended collision in the current tick (if any)
+ *
+ * @event collisionEnd
+ * @param {object} event An event object
+ * @param {pair[]} event.pairs List of affected pairs
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {number} event.delta The delta time in milliseconds value used in the update
+ * @param {engine} event.source The source object of the event
+ * @param {string} event.name The name of the event
+ */
+
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * An integer `Number` that specifies the number of position iterations to perform each update.
+ * The higher the value, the higher quality the simulation will be at the expense of performance.
+ *
+ * @property positionIterations
+ * @type number
+ * @default 6
+ */
+
+ /**
+ * An integer `Number` that specifies the number of velocity iterations to perform each update.
+ * The higher the value, the higher quality the simulation will be at the expense of performance.
+ *
+ * @property velocityIterations
+ * @type number
+ * @default 4
+ */
+
+ /**
+ * An integer `Number` that specifies the number of constraint iterations to perform each update.
+ * The higher the value, the higher quality the simulation will be at the expense of performance.
+ * The default value of `2` is usually very adequate.
+ *
+ * @property constraintIterations
+ * @type number
+ * @default 2
+ */
+
+ /**
+ * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module.
+ * Sleeping can improve stability and performance, but often at the expense of accuracy.
+ *
+ * @property enableSleeping
+ * @type boolean
+ * @default false
+ */
+
+ /**
+ * An `Object` containing properties regarding the timing systems of the engine.
+ *
+ * @property timing
+ * @type object
+ */
+
+ /**
+ * A `Number` that specifies the global scaling factor of time for all bodies.
+ * A value of `0` freezes the simulation.
+ * A value of `0.1` gives a slow-motion effect.
+ * A value of `1.2` gives a speed-up effect.
+ *
+ * @property timing.timeScale
+ * @type number
+ * @default 1
+ */
+
+ /**
+ * A `Number` that specifies the current simulation-time in milliseconds starting from `0`.
+ * It is incremented on every `Engine.update` by the given `delta` argument.
+ *
+ * @property timing.timestamp
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that represents the total execution time elapsed during the last `Engine.update` in milliseconds.
+ * It is updated by timing from the start of the last `Engine.update` call until it ends.
+ *
+ * This value will also include the total execution time of all event handlers directly or indirectly triggered by the engine update.
+ *
+ * @property timing.lastElapsed
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that represents the `delta` value used in the last engine update.
+ *
+ * @property timing.lastDelta
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Matter.Detector` instance.
+ *
+ * @property detector
+ * @type detector
+ * @default a Matter.Detector instance
+ */
+
+ /**
+ * A `Matter.Grid` instance.
+ *
+ * @deprecated replaced by `engine.detector`
+ * @property grid
+ * @type grid
+ * @default a Matter.Grid instance
+ */
+
+ /**
+ * Replaced by and now alias for `engine.grid`.
+ *
+ * @deprecated replaced by `engine.detector`
+ * @property broadphase
+ * @type grid
+ * @default a Matter.Grid instance
+ */
+
+ /**
+ * The root `Matter.Composite` instance that will contain all bodies, constraints and other composites to be simulated by this engine.
+ *
+ * @property world
+ * @type composite
+ * @default a Matter.Composite instance
+ */
+
+ /**
+ * An object reserved for storing plugin-specific properties.
+ *
+ * @property plugin
+ * @type {}
+ */
+
+ /**
+ * An optional gravitational acceleration applied to all bodies in `engine.world` on every update.
+ *
+ * This models a [uniform gravitational field](https://en.wikipedia.org/wiki/Gravity_of_Earth), similar to near the surface of a planet. For gravity in other contexts, disable this and apply forces as needed.
+ *
+ * To disable set the `scale` component to `0`.
+ *
+ * This is split into three components for ease of use:
+ * a normalised direction (`x` and `y`) and magnitude (`scale`).
+ *
+ * @property gravity
+ * @type object
+ */
+
+ /**
+ * The gravitational direction normal `x` component, to be multiplied by `gravity.scale`.
+ *
+ * @property gravity.x
+ * @type object
+ * @default 0
+ */
+
+ /**
+ * The gravitational direction normal `y` component, to be multiplied by `gravity.scale`.
+ *
+ * @property gravity.y
+ * @type object
+ * @default 1
+ */
+
+ /**
+ * The magnitude of the gravitational acceleration.
+ *
+ * @property gravity.scale
+ * @type object
+ * @default 0.001
+ */
+
+})();
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* The `Matter.Resolver` module contains methods for resolving collision pairs.
+*
+* @class Resolver
+*/
+
+var Resolver = {};
+
+module.exports = Resolver;
+
+var Vertices = __webpack_require__(3);
+var Common = __webpack_require__(0);
+var Bounds = __webpack_require__(1);
+
+(function() {
+
+ Resolver._restingThresh = 2;
+ Resolver._restingThreshTangent = Math.sqrt(6);
+ Resolver._positionDampen = 0.9;
+ Resolver._positionWarming = 0.8;
+ Resolver._frictionNormalMultiplier = 5;
+ Resolver._frictionMaxStatic = Number.MAX_VALUE;
+
+ /**
+ * Prepare pairs for position solving.
+ * @method preSolvePosition
+ * @param {pair[]} pairs
+ */
+ Resolver.preSolvePosition = function(pairs) {
+ var i,
+ pair,
+ activeCount,
+ pairsLength = pairs.length;
+
+ // find total contacts on each body
+ for (i = 0; i < pairsLength; i++) {
+ pair = pairs[i];
+
+ if (!pair.isActive)
+ continue;
+
+ activeCount = pair.activeContacts.length;
+ pair.collision.parentA.totalContacts += activeCount;
+ pair.collision.parentB.totalContacts += activeCount;
+ }
+ };
+
+ /**
+ * Find a solution for pair positions.
+ * @method solvePosition
+ * @param {pair[]} pairs
+ * @param {number} delta
+ * @param {number} [damping=1]
+ */
+ Resolver.solvePosition = function(pairs, delta, damping) {
+ var i,
+ pair,
+ collision,
+ bodyA,
+ bodyB,
+ normal,
+ contactShare,
+ positionImpulse,
+ positionDampen = Resolver._positionDampen * (damping || 1),
+ slopDampen = Common.clamp(delta / Common._baseDelta, 0, 1),
+ pairsLength = pairs.length;
+
+ // find impulses required to resolve penetration
+ for (i = 0; i < pairsLength; i++) {
+ pair = pairs[i];
+
+ if (!pair.isActive || pair.isSensor)
+ continue;
+
+ collision = pair.collision;
+ bodyA = collision.parentA;
+ bodyB = collision.parentB;
+ normal = collision.normal;
+
+ // get current separation between body edges involved in collision
+ pair.separation =
+ normal.x * (bodyB.positionImpulse.x + collision.penetration.x - bodyA.positionImpulse.x)
+ + normal.y * (bodyB.positionImpulse.y + collision.penetration.y - bodyA.positionImpulse.y);
+ }
+
+ for (i = 0; i < pairsLength; i++) {
+ pair = pairs[i];
+
+ if (!pair.isActive || pair.isSensor)
+ continue;
+
+ collision = pair.collision;
+ bodyA = collision.parentA;
+ bodyB = collision.parentB;
+ normal = collision.normal;
+ positionImpulse = pair.separation - pair.slop * slopDampen;
+
+ if (bodyA.isStatic || bodyB.isStatic)
+ positionImpulse *= 2;
+
+ if (!(bodyA.isStatic || bodyA.isSleeping)) {
+ contactShare = positionDampen / bodyA.totalContacts;
+ bodyA.positionImpulse.x += normal.x * positionImpulse * contactShare;
+ bodyA.positionImpulse.y += normal.y * positionImpulse * contactShare;
+ }
+
+ if (!(bodyB.isStatic || bodyB.isSleeping)) {
+ contactShare = positionDampen / bodyB.totalContacts;
+ bodyB.positionImpulse.x -= normal.x * positionImpulse * contactShare;
+ bodyB.positionImpulse.y -= normal.y * positionImpulse * contactShare;
+ }
+ }
+ };
+
+ /**
+ * Apply position resolution.
+ * @method postSolvePosition
+ * @param {body[]} bodies
+ */
+ Resolver.postSolvePosition = function(bodies) {
+ var positionWarming = Resolver._positionWarming,
+ bodiesLength = bodies.length,
+ verticesTranslate = Vertices.translate,
+ boundsUpdate = Bounds.update;
+
+ for (var i = 0; i < bodiesLength; i++) {
+ var body = bodies[i],
+ positionImpulse = body.positionImpulse,
+ positionImpulseX = positionImpulse.x,
+ positionImpulseY = positionImpulse.y,
+ velocity = body.velocity;
+
+ // reset contact count
+ body.totalContacts = 0;
+
+ if (positionImpulseX !== 0 || positionImpulseY !== 0) {
+ // update body geometry
+ for (var j = 0; j < body.parts.length; j++) {
+ var part = body.parts[j];
+ verticesTranslate(part.vertices, positionImpulse);
+ boundsUpdate(part.bounds, part.vertices, velocity);
+ part.position.x += positionImpulseX;
+ part.position.y += positionImpulseY;
+ }
+
+ // move the body without changing velocity
+ body.positionPrev.x += positionImpulseX;
+ body.positionPrev.y += positionImpulseY;
+
+ if (positionImpulseX * velocity.x + positionImpulseY * velocity.y < 0) {
+ // reset cached impulse if the body has velocity along it
+ positionImpulse.x = 0;
+ positionImpulse.y = 0;
+ } else {
+ // warm the next iteration
+ positionImpulse.x *= positionWarming;
+ positionImpulse.y *= positionWarming;
+ }
+ }
+ }
+ };
+
+ /**
+ * Prepare pairs for velocity solving.
+ * @method preSolveVelocity
+ * @param {pair[]} pairs
+ */
+ Resolver.preSolveVelocity = function(pairs) {
+ var pairsLength = pairs.length,
+ i,
+ j;
+
+ for (i = 0; i < pairsLength; i++) {
+ var pair = pairs[i];
+
+ if (!pair.isActive || pair.isSensor)
+ continue;
+
+ var contacts = pair.activeContacts,
+ contactsLength = contacts.length,
+ collision = pair.collision,
+ bodyA = collision.parentA,
+ bodyB = collision.parentB,
+ normal = collision.normal,
+ tangent = collision.tangent;
+
+ // resolve each contact
+ for (j = 0; j < contactsLength; j++) {
+ var contact = contacts[j],
+ contactVertex = contact.vertex,
+ normalImpulse = contact.normalImpulse,
+ tangentImpulse = contact.tangentImpulse;
+
+ if (normalImpulse !== 0 || tangentImpulse !== 0) {
+ // total impulse from contact
+ var impulseX = normal.x * normalImpulse + tangent.x * tangentImpulse,
+ impulseY = normal.y * normalImpulse + tangent.y * tangentImpulse;
+
+ // apply impulse from contact
+ if (!(bodyA.isStatic || bodyA.isSleeping)) {
+ bodyA.positionPrev.x += impulseX * bodyA.inverseMass;
+ bodyA.positionPrev.y += impulseY * bodyA.inverseMass;
+ bodyA.anglePrev += bodyA.inverseInertia * (
+ (contactVertex.x - bodyA.position.x) * impulseY
+ - (contactVertex.y - bodyA.position.y) * impulseX
+ );
+ }
+
+ if (!(bodyB.isStatic || bodyB.isSleeping)) {
+ bodyB.positionPrev.x -= impulseX * bodyB.inverseMass;
+ bodyB.positionPrev.y -= impulseY * bodyB.inverseMass;
+ bodyB.anglePrev -= bodyB.inverseInertia * (
+ (contactVertex.x - bodyB.position.x) * impulseY
+ - (contactVertex.y - bodyB.position.y) * impulseX
+ );
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Find a solution for pair velocities.
+ * @method solveVelocity
+ * @param {pair[]} pairs
+ * @param {number} delta
+ */
+ Resolver.solveVelocity = function(pairs, delta) {
+ var timeScale = delta / Common._baseDelta,
+ timeScaleSquared = timeScale * timeScale,
+ timeScaleCubed = timeScaleSquared * timeScale,
+ restingThresh = -Resolver._restingThresh * timeScale,
+ restingThreshTangent = Resolver._restingThreshTangent,
+ frictionNormalMultiplier = Resolver._frictionNormalMultiplier * timeScale,
+ frictionMaxStatic = Resolver._frictionMaxStatic,
+ pairsLength = pairs.length,
+ tangentImpulse,
+ maxFriction,
+ i,
+ j;
+
+ for (i = 0; i < pairsLength; i++) {
+ var pair = pairs[i];
+
+ if (!pair.isActive || pair.isSensor)
+ continue;
+
+ var collision = pair.collision,
+ bodyA = collision.parentA,
+ bodyB = collision.parentB,
+ bodyAVelocity = bodyA.velocity,
+ bodyBVelocity = bodyB.velocity,
+ normalX = collision.normal.x,
+ normalY = collision.normal.y,
+ tangentX = collision.tangent.x,
+ tangentY = collision.tangent.y,
+ contacts = pair.activeContacts,
+ contactsLength = contacts.length,
+ contactShare = 1 / contactsLength,
+ inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass,
+ friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier;
+
+ // update body velocities
+ bodyAVelocity.x = bodyA.position.x - bodyA.positionPrev.x;
+ bodyAVelocity.y = bodyA.position.y - bodyA.positionPrev.y;
+ bodyBVelocity.x = bodyB.position.x - bodyB.positionPrev.x;
+ bodyBVelocity.y = bodyB.position.y - bodyB.positionPrev.y;
+ bodyA.angularVelocity = bodyA.angle - bodyA.anglePrev;
+ bodyB.angularVelocity = bodyB.angle - bodyB.anglePrev;
+
+ // resolve each contact
+ for (j = 0; j < contactsLength; j++) {
+ var contact = contacts[j],
+ contactVertex = contact.vertex;
+
+ var offsetAX = contactVertex.x - bodyA.position.x,
+ offsetAY = contactVertex.y - bodyA.position.y,
+ offsetBX = contactVertex.x - bodyB.position.x,
+ offsetBY = contactVertex.y - bodyB.position.y;
+
+ var velocityPointAX = bodyAVelocity.x - offsetAY * bodyA.angularVelocity,
+ velocityPointAY = bodyAVelocity.y + offsetAX * bodyA.angularVelocity,
+ velocityPointBX = bodyBVelocity.x - offsetBY * bodyB.angularVelocity,
+ velocityPointBY = bodyBVelocity.y + offsetBX * bodyB.angularVelocity;
+
+ var relativeVelocityX = velocityPointAX - velocityPointBX,
+ relativeVelocityY = velocityPointAY - velocityPointBY;
+
+ var normalVelocity = normalX * relativeVelocityX + normalY * relativeVelocityY,
+ tangentVelocity = tangentX * relativeVelocityX + tangentY * relativeVelocityY;
+
+ // coulomb friction
+ var normalOverlap = pair.separation + normalVelocity;
+ var normalForce = Math.min(normalOverlap, 1);
+ normalForce = normalOverlap < 0 ? 0 : normalForce;
+
+ var frictionLimit = normalForce * friction;
+
+ if (tangentVelocity < -frictionLimit || tangentVelocity > frictionLimit) {
+ maxFriction = (tangentVelocity > 0 ? tangentVelocity : -tangentVelocity);
+ tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScaleCubed;
+
+ if (tangentImpulse < -maxFriction) {
+ tangentImpulse = -maxFriction;
+ } else if (tangentImpulse > maxFriction) {
+ tangentImpulse = maxFriction;
+ }
+ } else {
+ tangentImpulse = tangentVelocity;
+ maxFriction = frictionMaxStatic;
+ }
+
+ // account for mass, inertia and contact offset
+ var oAcN = offsetAX * normalY - offsetAY * normalX,
+ oBcN = offsetBX * normalY - offsetBY * normalX,
+ share = contactShare / (inverseMassTotal + bodyA.inverseInertia * oAcN * oAcN + bodyB.inverseInertia * oBcN * oBcN);
+
+ // raw impulses
+ var normalImpulse = (1 + pair.restitution) * normalVelocity * share;
+ tangentImpulse *= share;
+
+ // handle high velocity and resting collisions separately
+ if (normalVelocity < restingThresh) {
+ // high normal velocity so clear cached contact normal impulse
+ contact.normalImpulse = 0;
+ } else {
+ // solve resting collision constraints using Erin Catto's method (GDC08)
+ // impulse constraint tends to 0
+ var contactNormalImpulse = contact.normalImpulse;
+ contact.normalImpulse += normalImpulse;
+ if (contact.normalImpulse > 0) contact.normalImpulse = 0;
+ normalImpulse = contact.normalImpulse - contactNormalImpulse;
+ }
+
+ // handle high velocity and resting collisions separately
+ if (tangentVelocity < -restingThreshTangent || tangentVelocity > restingThreshTangent) {
+ // high tangent velocity so clear cached contact tangent impulse
+ contact.tangentImpulse = 0;
+ } else {
+ // solve resting collision constraints using Erin Catto's method (GDC08)
+ // tangent impulse tends to -tangentSpeed or +tangentSpeed
+ var contactTangentImpulse = contact.tangentImpulse;
+ contact.tangentImpulse += tangentImpulse;
+ if (contact.tangentImpulse < -maxFriction) contact.tangentImpulse = -maxFriction;
+ if (contact.tangentImpulse > maxFriction) contact.tangentImpulse = maxFriction;
+ tangentImpulse = contact.tangentImpulse - contactTangentImpulse;
+ }
+
+ // total impulse from contact
+ var impulseX = normalX * normalImpulse + tangentX * tangentImpulse,
+ impulseY = normalY * normalImpulse + tangentY * tangentImpulse;
+
+ // apply impulse from contact
+ if (!(bodyA.isStatic || bodyA.isSleeping)) {
+ bodyA.positionPrev.x += impulseX * bodyA.inverseMass;
+ bodyA.positionPrev.y += impulseY * bodyA.inverseMass;
+ bodyA.anglePrev += (offsetAX * impulseY - offsetAY * impulseX) * bodyA.inverseInertia;
+ }
+
+ if (!(bodyB.isStatic || bodyB.isSleeping)) {
+ bodyB.positionPrev.x -= impulseX * bodyB.inverseMass;
+ bodyB.positionPrev.y -= impulseY * bodyB.inverseMass;
+ bodyB.anglePrev -= (offsetBX * impulseY - offsetBY * impulseX) * bodyB.inverseInertia;
+ }
+ }
+ }
+ };
+
+})();
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets.
+*
+* @class Pairs
+*/
+
+var Pairs = {};
+
+module.exports = Pairs;
+
+var Pair = __webpack_require__(9);
+var Common = __webpack_require__(0);
+
+(function() {
+
+ /**
+ * Creates a new pairs structure.
+ * @method create
+ * @param {object} options
+ * @return {pairs} A new pairs structure
+ */
+ Pairs.create = function(options) {
+ return Common.extend({
+ table: {},
+ list: [],
+ collisionStart: [],
+ collisionActive: [],
+ collisionEnd: []
+ }, options);
+ };
+
+ /**
+ * Updates pairs given a list of collisions.
+ * @method update
+ * @param {object} pairs
+ * @param {collision[]} collisions
+ * @param {number} timestamp
+ */
+ Pairs.update = function(pairs, collisions, timestamp) {
+ var pairsList = pairs.list,
+ pairsListLength = pairsList.length,
+ pairsTable = pairs.table,
+ collisionsLength = collisions.length,
+ collisionStart = pairs.collisionStart,
+ collisionEnd = pairs.collisionEnd,
+ collisionActive = pairs.collisionActive,
+ collision,
+ pairIndex,
+ pair,
+ i;
+
+ // clear collision state arrays, but maintain old reference
+ collisionStart.length = 0;
+ collisionEnd.length = 0;
+ collisionActive.length = 0;
+
+ for (i = 0; i < pairsListLength; i++) {
+ pairsList[i].confirmedActive = false;
+ }
+
+ for (i = 0; i < collisionsLength; i++) {
+ collision = collisions[i];
+ pair = collision.pair;
+
+ if (pair) {
+ // pair already exists (but may or may not be active)
+ if (pair.isActive) {
+ // pair exists and is active
+ collisionActive.push(pair);
+ } else {
+ // pair exists but was inactive, so a collision has just started again
+ collisionStart.push(pair);
+ }
+
+ // update the pair
+ Pair.update(pair, collision, timestamp);
+ pair.confirmedActive = true;
+ } else {
+ // pair did not exist, create a new pair
+ pair = Pair.create(collision, timestamp);
+ pairsTable[pair.id] = pair;
+
+ // push the new pair
+ collisionStart.push(pair);
+ pairsList.push(pair);
+ }
+ }
+
+ // find pairs that are no longer active
+ var removePairIndex = [];
+ pairsListLength = pairsList.length;
+
+ for (i = 0; i < pairsListLength; i++) {
+ pair = pairsList[i];
+
+ if (!pair.confirmedActive) {
+ Pair.setActive(pair, false, timestamp);
+ collisionEnd.push(pair);
+
+ if (!pair.collision.bodyA.isSleeping && !pair.collision.bodyB.isSleeping) {
+ removePairIndex.push(i);
+ }
+ }
+ }
+
+ // remove inactive pairs
+ for (i = 0; i < removePairIndex.length; i++) {
+ pairIndex = removePairIndex[i] - i;
+ pair = pairsList[pairIndex];
+ pairsList.splice(pairIndex, 1);
+ delete pairsTable[pair.id];
+ }
+ };
+
+ /**
+ * Clears the given pairs structure.
+ * @method clear
+ * @param {pairs} pairs
+ * @return {pairs} pairs
+ */
+ Pairs.clear = function(pairs) {
+ pairs.table = {};
+ pairs.list.length = 0;
+ pairs.collisionStart.length = 0;
+ pairs.collisionActive.length = 0;
+ pairs.collisionEnd.length = 0;
+ return pairs;
+ };
+
+})();
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var Matter = module.exports = __webpack_require__(21);
+
+Matter.Axes = __webpack_require__(11);
+Matter.Bodies = __webpack_require__(12);
+Matter.Body = __webpack_require__(4);
+Matter.Bounds = __webpack_require__(1);
+Matter.Collision = __webpack_require__(8);
+Matter.Common = __webpack_require__(0);
+Matter.Composite = __webpack_require__(6);
+Matter.Composites = __webpack_require__(22);
+Matter.Constraint = __webpack_require__(10);
+Matter.Contact = __webpack_require__(16);
+Matter.Detector = __webpack_require__(13);
+Matter.Engine = __webpack_require__(17);
+Matter.Events = __webpack_require__(5);
+Matter.Grid = __webpack_require__(23);
+Matter.Mouse = __webpack_require__(14);
+Matter.MouseConstraint = __webpack_require__(24);
+Matter.Pair = __webpack_require__(9);
+Matter.Pairs = __webpack_require__(19);
+Matter.Plugin = __webpack_require__(15);
+Matter.Query = __webpack_require__(25);
+Matter.Render = __webpack_require__(26);
+Matter.Resolver = __webpack_require__(18);
+Matter.Runner = __webpack_require__(27);
+Matter.SAT = __webpack_require__(28);
+Matter.Sleeping = __webpack_require__(7);
+Matter.Svg = __webpack_require__(29);
+Matter.Vector = __webpack_require__(2);
+Matter.Vertices = __webpack_require__(3);
+Matter.World = __webpack_require__(30);
+
+// temporary back compatibility
+Matter.Engine.run = Matter.Runner.run;
+Matter.Common.deprecated(Matter.Engine, 'run', 'Engine.run ➤ use Matter.Runner.run(engine) instead');
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* The `Matter` module is the top level namespace. It also includes a function for installing plugins on top of the library.
+*
+* @class Matter
+*/
+
+var Matter = {};
+
+module.exports = Matter;
+
+var Plugin = __webpack_require__(15);
+var Common = __webpack_require__(0);
+
+(function() {
+
+ /**
+ * The library name.
+ * @property name
+ * @readOnly
+ * @type {String}
+ */
+ Matter.name = 'matter-js';
+
+ /**
+ * The library version.
+ * @property version
+ * @readOnly
+ * @type {String}
+ */
+ Matter.version = true ? "0.19.0" : undefined;
+
+ /**
+ * A list of plugin dependencies to be installed. These are normally set and installed through `Matter.use`.
+ * Alternatively you may set `Matter.uses` manually and install them by calling `Plugin.use(Matter)`.
+ * @property uses
+ * @type {Array}
+ */
+ Matter.uses = [];
+
+ /**
+ * The plugins that have been installed through `Matter.Plugin.install`. Read only.
+ * @property used
+ * @readOnly
+ * @type {Array}
+ */
+ Matter.used = [];
+
+ /**
+ * Installs the given plugins on the `Matter` namespace.
+ * This is a short-hand for `Plugin.use`, see it for more information.
+ * Call this function once at the start of your code, with all of the plugins you wish to install as arguments.
+ * Avoid calling this function multiple times unless you intend to manually control installation order.
+ * @method use
+ * @param ...plugin {Function} The plugin(s) to install on `base` (multi-argument).
+ */
+ Matter.use = function() {
+ Plugin.use(Matter, Array.prototype.slice.call(arguments));
+ };
+
+ /**
+ * Chains a function to excute before the original function on the given `path` relative to `Matter`.
+ * See also docs for `Common.chain`.
+ * @method before
+ * @param {string} path The path relative to `Matter`
+ * @param {function} func The function to chain before the original
+ * @return {function} The chained function that replaced the original
+ */
+ Matter.before = function(path, func) {
+ path = path.replace(/^Matter./, '');
+ return Common.chainPathBefore(Matter, path, func);
+ };
+
+ /**
+ * Chains a function to excute after the original function on the given `path` relative to `Matter`.
+ * See also docs for `Common.chain`.
+ * @method after
+ * @param {string} path The path relative to `Matter`
+ * @param {function} func The function to chain after the original
+ * @return {function} The chained function that replaced the original
+ */
+ Matter.after = function(path, func) {
+ path = path.replace(/^Matter./, '');
+ return Common.chainPathAfter(Matter, path, func);
+ };
+
+})();
+
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* The `Matter.Composites` module contains factory methods for creating composite bodies
+* with commonly used configurations (such as stacks and chains).
+*
+* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
+*
+* @class Composites
+*/
+
+var Composites = {};
+
+module.exports = Composites;
+
+var Composite = __webpack_require__(6);
+var Constraint = __webpack_require__(10);
+var Common = __webpack_require__(0);
+var Body = __webpack_require__(4);
+var Bodies = __webpack_require__(12);
+var deprecated = Common.deprecated;
+
+(function() {
+
+ /**
+ * Create a new composite containing bodies created in the callback in a grid arrangement.
+ * This function uses the body's bounds to prevent overlaps.
+ * @method stack
+ * @param {number} xx
+ * @param {number} yy
+ * @param {number} columns
+ * @param {number} rows
+ * @param {number} columnGap
+ * @param {number} rowGap
+ * @param {function} callback
+ * @return {composite} A new composite containing objects created in the callback
+ */
+ Composites.stack = function(xx, yy, columns, rows, columnGap, rowGap, callback) {
+ var stack = Composite.create({ label: 'Stack' }),
+ x = xx,
+ y = yy,
+ lastBody,
+ i = 0;
+
+ for (var row = 0; row < rows; row++) {
+ var maxHeight = 0;
+
+ for (var column = 0; column < columns; column++) {
+ var body = callback(x, y, column, row, lastBody, i);
+
+ if (body) {
+ var bodyHeight = body.bounds.max.y - body.bounds.min.y,
+ bodyWidth = body.bounds.max.x - body.bounds.min.x;
+
+ if (bodyHeight > maxHeight)
+ maxHeight = bodyHeight;
+
+ Body.translate(body, { x: bodyWidth * 0.5, y: bodyHeight * 0.5 });
+
+ x = body.bounds.max.x + columnGap;
+
+ Composite.addBody(stack, body);
+
+ lastBody = body;
+ i += 1;
+ } else {
+ x += columnGap;
+ }
+ }
+
+ y += maxHeight + rowGap;
+ x = xx;
+ }
+
+ return stack;
+ };
+
+ /**
+ * Chains all bodies in the given composite together using constraints.
+ * @method chain
+ * @param {composite} composite
+ * @param {number} xOffsetA
+ * @param {number} yOffsetA
+ * @param {number} xOffsetB
+ * @param {number} yOffsetB
+ * @param {object} options
+ * @return {composite} A new composite containing objects chained together with constraints
+ */
+ Composites.chain = function(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options) {
+ var bodies = composite.bodies;
+
+ for (var i = 1; i < bodies.length; i++) {
+ var bodyA = bodies[i - 1],
+ bodyB = bodies[i],
+ bodyAHeight = bodyA.bounds.max.y - bodyA.bounds.min.y,
+ bodyAWidth = bodyA.bounds.max.x - bodyA.bounds.min.x,
+ bodyBHeight = bodyB.bounds.max.y - bodyB.bounds.min.y,
+ bodyBWidth = bodyB.bounds.max.x - bodyB.bounds.min.x;
+
+ var defaults = {
+ bodyA: bodyA,
+ pointA: { x: bodyAWidth * xOffsetA, y: bodyAHeight * yOffsetA },
+ bodyB: bodyB,
+ pointB: { x: bodyBWidth * xOffsetB, y: bodyBHeight * yOffsetB }
+ };
+
+ var constraint = Common.extend(defaults, options);
+
+ Composite.addConstraint(composite, Constraint.create(constraint));
+ }
+
+ composite.label += ' Chain';
+
+ return composite;
+ };
+
+ /**
+ * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces.
+ * @method mesh
+ * @param {composite} composite
+ * @param {number} columns
+ * @param {number} rows
+ * @param {boolean} crossBrace
+ * @param {object} options
+ * @return {composite} The composite containing objects meshed together with constraints
+ */
+ Composites.mesh = function(composite, columns, rows, crossBrace, options) {
+ var bodies = composite.bodies,
+ row,
+ col,
+ bodyA,
+ bodyB,
+ bodyC;
+
+ for (row = 0; row < rows; row++) {
+ for (col = 1; col < columns; col++) {
+ bodyA = bodies[(col - 1) + (row * columns)];
+ bodyB = bodies[col + (row * columns)];
+ Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));
+ }
+
+ if (row > 0) {
+ for (col = 0; col < columns; col++) {
+ bodyA = bodies[col + ((row - 1) * columns)];
+ bodyB = bodies[col + (row * columns)];
+ Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));
+
+ if (crossBrace && col > 0) {
+ bodyC = bodies[(col - 1) + ((row - 1) * columns)];
+ Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));
+ }
+
+ if (crossBrace && col < columns - 1) {
+ bodyC = bodies[(col + 1) + ((row - 1) * columns)];
+ Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));
+ }
+ }
+ }
+ }
+
+ composite.label += ' Mesh';
+
+ return composite;
+ };
+
+ /**
+ * Create a new composite containing bodies created in the callback in a pyramid arrangement.
+ * This function uses the body's bounds to prevent overlaps.
+ * @method pyramid
+ * @param {number} xx
+ * @param {number} yy
+ * @param {number} columns
+ * @param {number} rows
+ * @param {number} columnGap
+ * @param {number} rowGap
+ * @param {function} callback
+ * @return {composite} A new composite containing objects created in the callback
+ */
+ Composites.pyramid = function(xx, yy, columns, rows, columnGap, rowGap, callback) {
+ return Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y, column, row, lastBody, i) {
+ var actualRows = Math.min(rows, Math.ceil(columns / 2)),
+ lastBodyWidth = lastBody ? lastBody.bounds.max.x - lastBody.bounds.min.x : 0;
+
+ if (row > actualRows)
+ return;
+
+ // reverse row order
+ row = actualRows - row;
+
+ var start = row,
+ end = columns - 1 - row;
+
+ if (column < start || column > end)
+ return;
+
+ // retroactively fix the first body's position, since width was unknown
+ if (i === 1) {
+ Body.translate(lastBody, { x: (column + (columns % 2 === 1 ? 1 : -1)) * lastBodyWidth, y: 0 });
+ }
+
+ var xOffset = lastBody ? column * lastBodyWidth : 0;
+
+ return callback(xx + xOffset + column * columnGap, y, column, row, lastBody, i);
+ });
+ };
+
+ /**
+ * This has now moved to the [newtonsCradle example](https://github.com/liabru/matter-js/blob/master/examples/newtonsCradle.js), follow that instead as this function is deprecated here.
+ * @deprecated moved to newtonsCradle example
+ * @method newtonsCradle
+ * @param {number} xx
+ * @param {number} yy
+ * @param {number} number
+ * @param {number} size
+ * @param {number} length
+ * @return {composite} A new composite newtonsCradle body
+ */
+ Composites.newtonsCradle = function(xx, yy, number, size, length) {
+ var newtonsCradle = Composite.create({ label: 'Newtons Cradle' });
+
+ for (var i = 0; i < number; i++) {
+ var separation = 1.9,
+ circle = Bodies.circle(xx + i * (size * separation), yy + length, size,
+ { inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }),
+ constraint = Constraint.create({ pointA: { x: xx + i * (size * separation), y: yy }, bodyB: circle });
+
+ Composite.addBody(newtonsCradle, circle);
+ Composite.addConstraint(newtonsCradle, constraint);
+ }
+
+ return newtonsCradle;
+ };
+
+ deprecated(Composites, 'newtonsCradle', 'Composites.newtonsCradle ➤ moved to newtonsCradle example');
+
+ /**
+ * This has now moved to the [car example](https://github.com/liabru/matter-js/blob/master/examples/car.js), follow that instead as this function is deprecated here.
+ * @deprecated moved to car example
+ * @method car
+ * @param {number} xx
+ * @param {number} yy
+ * @param {number} width
+ * @param {number} height
+ * @param {number} wheelSize
+ * @return {composite} A new composite car body
+ */
+ Composites.car = function(xx, yy, width, height, wheelSize) {
+ var group = Body.nextGroup(true),
+ wheelBase = 20,
+ wheelAOffset = -width * 0.5 + wheelBase,
+ wheelBOffset = width * 0.5 - wheelBase,
+ wheelYOffset = 0;
+
+ var car = Composite.create({ label: 'Car' }),
+ body = Bodies.rectangle(xx, yy, width, height, {
+ collisionFilter: {
+ group: group
+ },
+ chamfer: {
+ radius: height * 0.5
+ },
+ density: 0.0002
+ });
+
+ var wheelA = Bodies.circle(xx + wheelAOffset, yy + wheelYOffset, wheelSize, {
+ collisionFilter: {
+ group: group
+ },
+ friction: 0.8
+ });
+
+ var wheelB = Bodies.circle(xx + wheelBOffset, yy + wheelYOffset, wheelSize, {
+ collisionFilter: {
+ group: group
+ },
+ friction: 0.8
+ });
+
+ var axelA = Constraint.create({
+ bodyB: body,
+ pointB: { x: wheelAOffset, y: wheelYOffset },
+ bodyA: wheelA,
+ stiffness: 1,
+ length: 0
+ });
+
+ var axelB = Constraint.create({
+ bodyB: body,
+ pointB: { x: wheelBOffset, y: wheelYOffset },
+ bodyA: wheelB,
+ stiffness: 1,
+ length: 0
+ });
+
+ Composite.addBody(car, body);
+ Composite.addBody(car, wheelA);
+ Composite.addBody(car, wheelB);
+ Composite.addConstraint(car, axelA);
+ Composite.addConstraint(car, axelB);
+
+ return car;
+ };
+
+ deprecated(Composites, 'car', 'Composites.car ➤ moved to car example');
+
+ /**
+ * This has now moved to the [softBody example](https://github.com/liabru/matter-js/blob/master/examples/softBody.js)
+ * and the [cloth example](https://github.com/liabru/matter-js/blob/master/examples/cloth.js), follow those instead as this function is deprecated here.
+ * @deprecated moved to softBody and cloth examples
+ * @method softBody
+ * @param {number} xx
+ * @param {number} yy
+ * @param {number} columns
+ * @param {number} rows
+ * @param {number} columnGap
+ * @param {number} rowGap
+ * @param {boolean} crossBrace
+ * @param {number} particleRadius
+ * @param {} particleOptions
+ * @param {} constraintOptions
+ * @return {composite} A new composite softBody
+ */
+ Composites.softBody = function(xx, yy, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) {
+ particleOptions = Common.extend({ inertia: Infinity }, particleOptions);
+ constraintOptions = Common.extend({ stiffness: 0.2, render: { type: 'line', anchors: false } }, constraintOptions);
+
+ var softBody = Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y) {
+ return Bodies.circle(x, y, particleRadius, particleOptions);
+ });
+
+ Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions);
+
+ softBody.label = 'Soft Body';
+
+ return softBody;
+ };
+
+ deprecated(Composites, 'softBody', 'Composites.softBody ➤ moved to softBody and cloth examples');
+})();
+
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* This module has now been replaced by `Matter.Detector`.
+*
+* All usage should be migrated to `Matter.Detector` or another alternative.
+* For back-compatibility purposes this module will remain for a short term and then later removed in a future release.
+*
+* The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures.
+*
+* @class Grid
+* @deprecated
+*/
+
+var Grid = {};
+
+module.exports = Grid;
+
+var Pair = __webpack_require__(9);
+var Common = __webpack_require__(0);
+var deprecated = Common.deprecated;
+
+(function() {
+
+ /**
+ * Creates a new grid.
+ * @deprecated replaced by Matter.Detector
+ * @method create
+ * @param {} options
+ * @return {grid} A new grid
+ */
+ Grid.create = function(options) {
+ var defaults = {
+ buckets: {},
+ pairs: {},
+ pairsList: [],
+ bucketWidth: 48,
+ bucketHeight: 48
+ };
+
+ return Common.extend(defaults, options);
+ };
+
+ /**
+ * The width of a single grid bucket.
+ *
+ * @property bucketWidth
+ * @type number
+ * @default 48
+ */
+
+ /**
+ * The height of a single grid bucket.
+ *
+ * @property bucketHeight
+ * @type number
+ * @default 48
+ */
+
+ /**
+ * Updates the grid.
+ * @deprecated replaced by Matter.Detector
+ * @method update
+ * @param {grid} grid
+ * @param {body[]} bodies
+ * @param {engine} engine
+ * @param {boolean} forceUpdate
+ */
+ Grid.update = function(grid, bodies, engine, forceUpdate) {
+ var i, col, row,
+ world = engine.world,
+ buckets = grid.buckets,
+ bucket,
+ bucketId,
+ gridChanged = false;
+
+ for (i = 0; i < bodies.length; i++) {
+ var body = bodies[i];
+
+ if (body.isSleeping && !forceUpdate)
+ continue;
+
+ // temporary back compatibility bounds check
+ if (world.bounds && (body.bounds.max.x < world.bounds.min.x || body.bounds.min.x > world.bounds.max.x
+ || body.bounds.max.y < world.bounds.min.y || body.bounds.min.y > world.bounds.max.y))
+ continue;
+
+ var newRegion = Grid._getRegion(grid, body);
+
+ // if the body has changed grid region
+ if (!body.region || newRegion.id !== body.region.id || forceUpdate) {
+
+ if (!body.region || forceUpdate)
+ body.region = newRegion;
+
+ var union = Grid._regionUnion(newRegion, body.region);
+
+ // update grid buckets affected by region change
+ // iterate over the union of both regions
+ for (col = union.startCol; col <= union.endCol; col++) {
+ for (row = union.startRow; row <= union.endRow; row++) {
+ bucketId = Grid._getBucketId(col, row);
+ bucket = buckets[bucketId];
+
+ var isInsideNewRegion = (col >= newRegion.startCol && col <= newRegion.endCol
+ && row >= newRegion.startRow && row <= newRegion.endRow);
+
+ var isInsideOldRegion = (col >= body.region.startCol && col <= body.region.endCol
+ && row >= body.region.startRow && row <= body.region.endRow);
+
+ // remove from old region buckets
+ if (!isInsideNewRegion && isInsideOldRegion) {
+ if (isInsideOldRegion) {
+ if (bucket)
+ Grid._bucketRemoveBody(grid, bucket, body);
+ }
+ }
+
+ // add to new region buckets
+ if (body.region === newRegion || (isInsideNewRegion && !isInsideOldRegion) || forceUpdate) {
+ if (!bucket)
+ bucket = Grid._createBucket(buckets, bucketId);
+ Grid._bucketAddBody(grid, bucket, body);
+ }
+ }
+ }
+
+ // set the new region
+ body.region = newRegion;
+
+ // flag changes so we can update pairs
+ gridChanged = true;
+ }
+ }
+
+ // update pairs list only if pairs changed (i.e. a body changed region)
+ if (gridChanged)
+ grid.pairsList = Grid._createActivePairsList(grid);
+ };
+
+ deprecated(Grid, 'update', 'Grid.update ➤ replaced by Matter.Detector');
+
+ /**
+ * Clears the grid.
+ * @deprecated replaced by Matter.Detector
+ * @method clear
+ * @param {grid} grid
+ */
+ Grid.clear = function(grid) {
+ grid.buckets = {};
+ grid.pairs = {};
+ grid.pairsList = [];
+ };
+
+ deprecated(Grid, 'clear', 'Grid.clear ➤ replaced by Matter.Detector');
+
+ /**
+ * Finds the union of two regions.
+ * @method _regionUnion
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} regionA
+ * @param {} regionB
+ * @return {} region
+ */
+ Grid._regionUnion = function(regionA, regionB) {
+ var startCol = Math.min(regionA.startCol, regionB.startCol),
+ endCol = Math.max(regionA.endCol, regionB.endCol),
+ startRow = Math.min(regionA.startRow, regionB.startRow),
+ endRow = Math.max(regionA.endRow, regionB.endRow);
+
+ return Grid._createRegion(startCol, endCol, startRow, endRow);
+ };
+
+ /**
+ * Gets the region a given body falls in for a given grid.
+ * @method _getRegion
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} grid
+ * @param {} body
+ * @return {} region
+ */
+ Grid._getRegion = function(grid, body) {
+ var bounds = body.bounds,
+ startCol = Math.floor(bounds.min.x / grid.bucketWidth),
+ endCol = Math.floor(bounds.max.x / grid.bucketWidth),
+ startRow = Math.floor(bounds.min.y / grid.bucketHeight),
+ endRow = Math.floor(bounds.max.y / grid.bucketHeight);
+
+ return Grid._createRegion(startCol, endCol, startRow, endRow);
+ };
+
+ /**
+ * Creates a region.
+ * @method _createRegion
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} startCol
+ * @param {} endCol
+ * @param {} startRow
+ * @param {} endRow
+ * @return {} region
+ */
+ Grid._createRegion = function(startCol, endCol, startRow, endRow) {
+ return {
+ id: startCol + ',' + endCol + ',' + startRow + ',' + endRow,
+ startCol: startCol,
+ endCol: endCol,
+ startRow: startRow,
+ endRow: endRow
+ };
+ };
+
+ /**
+ * Gets the bucket id at the given position.
+ * @method _getBucketId
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} column
+ * @param {} row
+ * @return {string} bucket id
+ */
+ Grid._getBucketId = function(column, row) {
+ return 'C' + column + 'R' + row;
+ };
+
+ /**
+ * Creates a bucket.
+ * @method _createBucket
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} buckets
+ * @param {} bucketId
+ * @return {} bucket
+ */
+ Grid._createBucket = function(buckets, bucketId) {
+ var bucket = buckets[bucketId] = [];
+ return bucket;
+ };
+
+ /**
+ * Adds a body to a bucket.
+ * @method _bucketAddBody
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} grid
+ * @param {} bucket
+ * @param {} body
+ */
+ Grid._bucketAddBody = function(grid, bucket, body) {
+ var gridPairs = grid.pairs,
+ pairId = Pair.id,
+ bucketLength = bucket.length,
+ i;
+
+ // add new pairs
+ for (i = 0; i < bucketLength; i++) {
+ var bodyB = bucket[i];
+
+ if (body.id === bodyB.id || (body.isStatic && bodyB.isStatic))
+ continue;
+
+ // keep track of the number of buckets the pair exists in
+ // important for Grid.update to work
+ var id = pairId(body, bodyB),
+ pair = gridPairs[id];
+
+ if (pair) {
+ pair[2] += 1;
+ } else {
+ gridPairs[id] = [body, bodyB, 1];
+ }
+ }
+
+ // add to bodies (after pairs, otherwise pairs with self)
+ bucket.push(body);
+ };
+
+ /**
+ * Removes a body from a bucket.
+ * @method _bucketRemoveBody
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} grid
+ * @param {} bucket
+ * @param {} body
+ */
+ Grid._bucketRemoveBody = function(grid, bucket, body) {
+ var gridPairs = grid.pairs,
+ pairId = Pair.id,
+ i;
+
+ // remove from bucket
+ bucket.splice(Common.indexOf(bucket, body), 1);
+
+ var bucketLength = bucket.length;
+
+ // update pair counts
+ for (i = 0; i < bucketLength; i++) {
+ // keep track of the number of buckets the pair exists in
+ // important for _createActivePairsList to work
+ var pair = gridPairs[pairId(body, bucket[i])];
+
+ if (pair)
+ pair[2] -= 1;
+ }
+ };
+
+ /**
+ * Generates a list of the active pairs in the grid.
+ * @method _createActivePairsList
+ * @deprecated replaced by Matter.Detector
+ * @private
+ * @param {} grid
+ * @return [] pairs
+ */
+ Grid._createActivePairsList = function(grid) {
+ var pair,
+ gridPairs = grid.pairs,
+ pairKeys = Common.keys(gridPairs),
+ pairKeysLength = pairKeys.length,
+ pairs = [],
+ k;
+
+ // iterate over grid.pairs
+ for (k = 0; k < pairKeysLength; k++) {
+ pair = gridPairs[pairKeys[k]];
+
+ // if pair exists in at least one bucket
+ // it is a pair that needs further collision testing so push it
+ if (pair[2] > 0) {
+ pairs.push(pair);
+ } else {
+ delete gridPairs[pairKeys[k]];
+ }
+ }
+
+ return pairs;
+ };
+
+})();
+
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* The `Matter.MouseConstraint` module contains methods for creating mouse constraints.
+* Mouse constraints are used for allowing user interaction, providing the ability to move bodies via the mouse or touch.
+*
+* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
+*
+* @class MouseConstraint
+*/
+
+var MouseConstraint = {};
+
+module.exports = MouseConstraint;
+
+var Vertices = __webpack_require__(3);
+var Sleeping = __webpack_require__(7);
+var Mouse = __webpack_require__(14);
+var Events = __webpack_require__(5);
+var Detector = __webpack_require__(13);
+var Constraint = __webpack_require__(10);
+var Composite = __webpack_require__(6);
+var Common = __webpack_require__(0);
+var Bounds = __webpack_require__(1);
+
+(function() {
+
+ /**
+ * Creates a new mouse constraint.
+ * All properties have default values, and many are pre-calculated automatically based on other properties.
+ * See the properties section below for detailed information on what you can pass via the `options` object.
+ * @method create
+ * @param {engine} engine
+ * @param {} options
+ * @return {MouseConstraint} A new MouseConstraint
+ */
+ MouseConstraint.create = function(engine, options) {
+ var mouse = (engine ? engine.mouse : null) || (options ? options.mouse : null);
+
+ if (!mouse) {
+ if (engine && engine.render && engine.render.canvas) {
+ mouse = Mouse.create(engine.render.canvas);
+ } else if (options && options.element) {
+ mouse = Mouse.create(options.element);
+ } else {
+ mouse = Mouse.create();
+ Common.warn('MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected');
+ }
+ }
+
+ var constraint = Constraint.create({
+ label: 'Mouse Constraint',
+ pointA: mouse.position,
+ pointB: { x: 0, y: 0 },
+ length: 0.01,
+ stiffness: 0.1,
+ angularStiffness: 1,
+ render: {
+ strokeStyle: '#90EE90',
+ lineWidth: 3
+ }
+ });
+
+ var defaults = {
+ type: 'mouseConstraint',
+ mouse: mouse,
+ element: null,
+ body: null,
+ constraint: constraint,
+ collisionFilter: {
+ category: 0x0001,
+ mask: 0xFFFFFFFF,
+ group: 0
+ }
+ };
+
+ var mouseConstraint = Common.extend(defaults, options);
+
+ Events.on(engine, 'beforeUpdate', function() {
+ var allBodies = Composite.allBodies(engine.world);
+ MouseConstraint.update(mouseConstraint, allBodies);
+ MouseConstraint._triggerEvents(mouseConstraint);
+ });
+
+ return mouseConstraint;
+ };
+
+ /**
+ * Updates the given mouse constraint.
+ * @private
+ * @method update
+ * @param {MouseConstraint} mouseConstraint
+ * @param {body[]} bodies
+ */
+ MouseConstraint.update = function(mouseConstraint, bodies) {
+ var mouse = mouseConstraint.mouse,
+ constraint = mouseConstraint.constraint,
+ body = mouseConstraint.body;
+
+ if (mouse.button === 0) {
+ if (!constraint.bodyB) {
+ for (var i = 0; i < bodies.length; i++) {
+ body = bodies[i];
+ if (Bounds.contains(body.bounds, mouse.position)
+ && Detector.canCollide(body.collisionFilter, mouseConstraint.collisionFilter)) {
+ for (var j = body.parts.length > 1 ? 1 : 0; j < body.parts.length; j++) {
+ var part = body.parts[j];
+ if (Vertices.contains(part.vertices, mouse.position)) {
+ constraint.pointA = mouse.position;
+ constraint.bodyB = mouseConstraint.body = body;
+ constraint.pointB = { x: mouse.position.x - body.position.x, y: mouse.position.y - body.position.y };
+ constraint.angleB = body.angle;
+
+ Sleeping.set(body, false);
+ Events.trigger(mouseConstraint, 'startdrag', { mouse: mouse, body: body });
+
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ Sleeping.set(constraint.bodyB, false);
+ constraint.pointA = mouse.position;
+ }
+ } else {
+ constraint.bodyB = mouseConstraint.body = null;
+ constraint.pointB = null;
+
+ if (body)
+ Events.trigger(mouseConstraint, 'enddrag', { mouse: mouse, body: body });
+ }
+ };
+
+ /**
+ * Triggers mouse constraint events.
+ * @method _triggerEvents
+ * @private
+ * @param {mouse} mouseConstraint
+ */
+ MouseConstraint._triggerEvents = function(mouseConstraint) {
+ var mouse = mouseConstraint.mouse,
+ mouseEvents = mouse.sourceEvents;
+
+ if (mouseEvents.mousemove)
+ Events.trigger(mouseConstraint, 'mousemove', { mouse: mouse });
+
+ if (mouseEvents.mousedown)
+ Events.trigger(mouseConstraint, 'mousedown', { mouse: mouse });
+
+ if (mouseEvents.mouseup)
+ Events.trigger(mouseConstraint, 'mouseup', { mouse: mouse });
+
+ // reset the mouse state ready for the next step
+ Mouse.clearSourceEvents(mouse);
+ };
+
+ /*
+ *
+ * Events Documentation
+ *
+ */
+
+ /**
+ * Fired when the mouse has moved (or a touch moves) during the last step
+ *
+ * @event mousemove
+ * @param {} event An event object
+ * @param {mouse} event.mouse The engine's mouse instance
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired when the mouse is down (or a touch has started) during the last step
+ *
+ * @event mousedown
+ * @param {} event An event object
+ * @param {mouse} event.mouse The engine's mouse instance
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired when the mouse is up (or a touch has ended) during the last step
+ *
+ * @event mouseup
+ * @param {} event An event object
+ * @param {mouse} event.mouse The engine's mouse instance
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired when the user starts dragging a body
+ *
+ * @event startdrag
+ * @param {} event An event object
+ * @param {mouse} event.mouse The engine's mouse instance
+ * @param {body} event.body The body being dragged
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired when the user ends dragging a body
+ *
+ * @event enddrag
+ * @param {} event An event object
+ * @param {mouse} event.mouse The engine's mouse instance
+ * @param {body} event.body The body that has stopped being dragged
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * A `String` denoting the type of object.
+ *
+ * @property type
+ * @type string
+ * @default "constraint"
+ * @readOnly
+ */
+
+ /**
+ * The `Mouse` instance in use. If not supplied in `MouseConstraint.create`, one will be created.
+ *
+ * @property mouse
+ * @type mouse
+ * @default mouse
+ */
+
+ /**
+ * The `Body` that is currently being moved by the user, or `null` if no body.
+ *
+ * @property body
+ * @type body
+ * @default null
+ */
+
+ /**
+ * The `Constraint` object that is used to move the body during interaction.
+ *
+ * @property constraint
+ * @type constraint
+ */
+
+ /**
+ * An `Object` that specifies the collision filter properties.
+ * The collision filter allows the user to define which types of body this mouse constraint can interact with.
+ * See `body.collisionFilter` for more information.
+ *
+ * @property collisionFilter
+ * @type object
+ */
+
+})();
+
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/**
+* The `Matter.Query` module contains methods for performing collision queries.
+*
+* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
+*
+* @class Query
+*/
+
+var Query = {};
+
+module.exports = Query;
+
+var Vector = __webpack_require__(2);
+var Collision = __webpack_require__(8);
+var Bounds = __webpack_require__(1);
+var Bodies = __webpack_require__(12);
+var Vertices = __webpack_require__(3);
+
+(function() {
+
+ /**
+ * Returns a list of collisions between `body` and `bodies`.
+ * @method collides
+ * @param {body} body
+ * @param {body[]} bodies
+ * @return {collision[]} Collisions
+ */
+ Query.collides = function(body, bodies) {
+ var collisions = [],
+ bodiesLength = bodies.length,
+ bounds = body.bounds,
+ collides = Collision.collides,
+ overlaps = Bounds.overlaps;
+
+ for (var i = 0; i < bodiesLength; i++) {
+ var bodyA = bodies[i],
+ partsALength = bodyA.parts.length,
+ partsAStart = partsALength === 1 ? 0 : 1;
+
+ if (overlaps(bodyA.bounds, bounds)) {
+ for (var j = partsAStart; j < partsALength; j++) {
+ var part = bodyA.parts[j];
+
+ if (overlaps(part.bounds, bounds)) {
+ var collision = collides(part, body);
+
+ if (collision) {
+ collisions.push(collision);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return collisions;
+ };
+
+ /**
+ * Casts a ray segment against a set of bodies and returns all collisions, ray width is optional. Intersection points are not provided.
+ * @method ray
+ * @param {body[]} bodies
+ * @param {vector} startPoint
+ * @param {vector} endPoint
+ * @param {number} [rayWidth]
+ * @return {collision[]} Collisions
+ */
+ Query.ray = function(bodies, startPoint, endPoint, rayWidth) {
+ rayWidth = rayWidth || 1e-100;
+
+ var rayAngle = Vector.angle(startPoint, endPoint),
+ rayLength = Vector.magnitude(Vector.sub(startPoint, endPoint)),
+ rayX = (endPoint.x + startPoint.x) * 0.5,
+ rayY = (endPoint.y + startPoint.y) * 0.5,
+ ray = Bodies.rectangle(rayX, rayY, rayLength, rayWidth, { angle: rayAngle }),
+ collisions = Query.collides(ray, bodies);
+
+ for (var i = 0; i < collisions.length; i += 1) {
+ var collision = collisions[i];
+ collision.body = collision.bodyB = collision.bodyA;
+ }
+
+ return collisions;
+ };
+
+ /**
+ * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies.
+ * @method region
+ * @param {body[]} bodies
+ * @param {bounds} bounds
+ * @param {bool} [outside=false]
+ * @return {body[]} The bodies matching the query
+ */
+ Query.region = function(bodies, bounds, outside) {
+ var result = [];
+
+ for (var i = 0; i < bodies.length; i++) {
+ var body = bodies[i],
+ overlaps = Bounds.overlaps(body.bounds, bounds);
+ if ((overlaps && !outside) || (!overlaps && outside))
+ result.push(body);
+ }
+
+ return result;
+ };
+
+ /**
+ * Returns all bodies whose vertices contain the given point, from the given set of bodies.
+ * @method point
+ * @param {body[]} bodies
+ * @param {vector} point
+ * @return {body[]} The bodies matching the query
+ */
+ Query.point = function(bodies, point) {
+ var result = [];
+
+ for (var i = 0; i < bodies.length; i++) {
+ var body = bodies[i];
+
+ if (Bounds.contains(body.bounds, point)) {
+ for (var j = body.parts.length === 1 ? 0 : 1; j < body.parts.length; j++) {
+ var part = body.parts[j];
+
+ if (Bounds.contains(part.bounds, point)
+ && Vertices.contains(part.vertices, point)) {
+ result.push(body);
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+ };
+
+})();
+
+
+/***/ }),
+/* 26 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -6036,12 +8583,13 @@ var Render = {};
module.exports = Render;
+var Body = __webpack_require__(4);
var Common = __webpack_require__(0);
-var Composite = __webpack_require__(5);
+var Composite = __webpack_require__(6);
var Bounds = __webpack_require__(1);
-var Events = __webpack_require__(4);
+var Events = __webpack_require__(5);
var Vector = __webpack_require__(2);
-var Mouse = __webpack_require__(13);
+var Mouse = __webpack_require__(14);
(function() {
@@ -6070,7 +8618,6 @@ var Mouse = __webpack_require__(13);
*/
Render.create = function(options) {
var defaults = {
- controller: Render,
engine: null,
element: null,
canvas: null,
@@ -6142,6 +8689,7 @@ var Mouse = __webpack_require__(13);
};
// for temporary back compatibility only
+ render.controller = Render;
render.options.showBroadphase = false;
if (render.options.pixelRatio !== 1) {
@@ -6150,8 +8698,6 @@ var Mouse = __webpack_require__(13);
if (Common.isElement(render.element)) {
render.element.appendChild(render.canvas);
- } else if (!render.canvas.parentNode) {
- Common.log('Render.create: options.element was undefined, render.canvas was created but not appended', 'warn');
}
return render;
@@ -7134,8 +9680,10 @@ var Mouse = __webpack_require__(13);
if (!body.render.visible)
continue;
+ var velocity = Body.getVelocity(body);
+
c.moveTo(body.position.x, body.position.y);
- c.lineTo(body.position.x + (body.position.x - body.positionPrev.x) * 2, body.position.y + (body.position.y - body.positionPrev.y) * 2);
+ c.lineTo(body.position.x + velocity.x, body.position.y + velocity.y);
}
c.lineWidth = 3;
@@ -7551,6 +10099,7 @@ var Mouse = __webpack_require__(13);
/**
* A back-reference to the `Matter.Render` module.
*
+ * @deprecated
* @property controller
* @type render
*/
@@ -7856,2298 +10405,6 @@ var Mouse = __webpack_require__(13);
})();
-/***/ }),
-/* 17 */
-/***/ (function(module, exports) {
-
-/**
-* The `Matter.Contact` module contains methods for creating and manipulating collision contacts.
-*
-* @class Contact
-*/
-
-var Contact = {};
-
-module.exports = Contact;
-
-(function() {
-
- /**
- * Creates a new contact.
- * @method create
- * @param {vertex} vertex
- * @return {contact} A new contact
- */
- Contact.create = function(vertex) {
- return {
- vertex: vertex,
- normalImpulse: 0,
- tangentImpulse: 0
- };
- };
-
-})();
-
-
-/***/ }),
-/* 18 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.Engine` module contains methods for creating and manipulating engines.
-* An engine is a controller that manages updating the simulation of the world.
-* See `Matter.Runner` for an optional game loop utility.
-*
-* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
-*
-* @class Engine
-*/
-
-var Engine = {};
-
-module.exports = Engine;
-
-var Sleeping = __webpack_require__(7);
-var Resolver = __webpack_require__(19);
-var Detector = __webpack_require__(14);
-var Pairs = __webpack_require__(20);
-var Events = __webpack_require__(4);
-var Composite = __webpack_require__(5);
-var Constraint = __webpack_require__(10);
-var Common = __webpack_require__(0);
-var Body = __webpack_require__(6);
-
-(function() {
-
- /**
- * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults.
- * All properties have default values, and many are pre-calculated automatically based on other properties.
- * See the properties section below for detailed information on what you can pass via the `options` object.
- * @method create
- * @param {object} [options]
- * @return {engine} engine
- */
- Engine.create = function(options) {
- options = options || {};
-
- var defaults = {
- positionIterations: 6,
- velocityIterations: 4,
- constraintIterations: 2,
- enableSleeping: false,
- events: [],
- plugin: {},
- gravity: {
- x: 0,
- y: 1,
- scale: 0.001
- },
- timing: {
- timestamp: 0,
- timeScale: 1,
- lastDelta: 0,
- lastElapsed: 0
- }
- };
-
- var engine = Common.extend(defaults, options);
-
- engine.world = options.world || Composite.create({ label: 'World' });
- engine.pairs = options.pairs || Pairs.create();
- engine.detector = options.detector || Detector.create();
-
- // for temporary back compatibility only
- engine.grid = { buckets: [] };
- engine.world.gravity = engine.gravity;
- engine.broadphase = engine.grid;
- engine.metrics = {};
-
- return engine;
- };
-
- /**
- * Moves the simulation forward in time by `delta` ms.
- * The `correction` argument is an optional `Number` that specifies the time correction factor to apply to the update.
- * This can help improve the accuracy of the simulation in cases where `delta` is changing between updates.
- * The value of `correction` is defined as `delta / lastDelta`, i.e. the percentage change of `delta` over the last step.
- * Therefore the value is always `1` (no correction) when `delta` constant (or when no correction is desired, which is the default).
- * See the paper on Time Corrected Verlet for more information.
- *
- * Triggers `beforeUpdate` and `afterUpdate` events.
- * Triggers `collisionStart`, `collisionActive` and `collisionEnd` events.
- * @method update
- * @param {engine} engine
- * @param {number} [delta=16.666]
- * @param {number} [correction=1]
- */
- Engine.update = function(engine, delta, correction) {
- var startTime = Common.now();
-
- delta = delta || 1000 / 60;
- correction = correction || 1;
-
- var world = engine.world,
- detector = engine.detector,
- pairs = engine.pairs,
- timing = engine.timing,
- timestamp = timing.timestamp,
- i;
-
- // increment timestamp
- timing.timestamp += delta * timing.timeScale;
- timing.lastDelta = delta * timing.timeScale;
-
- // create an event object
- var event = {
- timestamp: timing.timestamp
- };
-
- Events.trigger(engine, 'beforeUpdate', event);
-
- // get all bodies and all constraints in the world
- var allBodies = Composite.allBodies(world),
- allConstraints = Composite.allConstraints(world);
-
- // update the detector bodies if they have changed
- if (world.isModified) {
- Detector.setBodies(detector, allBodies);
- }
-
- // reset all composite modified flags
- if (world.isModified) {
- Composite.setModified(world, false, false, true);
- }
-
- // update sleeping if enabled
- if (engine.enableSleeping)
- Sleeping.update(allBodies, timing.timeScale);
-
- // apply gravity to all bodies
- Engine._bodiesApplyGravity(allBodies, engine.gravity);
-
- // update all body position and rotation by integration
- Engine._bodiesUpdate(allBodies, delta, timing.timeScale, correction, world.bounds);
-
- // update all constraints (first pass)
- Constraint.preSolveAll(allBodies);
- for (i = 0; i < engine.constraintIterations; i++) {
- Constraint.solveAll(allConstraints, timing.timeScale);
- }
- Constraint.postSolveAll(allBodies);
-
- // find all collisions
- detector.pairs = engine.pairs;
- var collisions = Detector.collisions(detector);
-
- // update collision pairs
- Pairs.update(pairs, collisions, timestamp);
-
- // wake up bodies involved in collisions
- if (engine.enableSleeping)
- Sleeping.afterCollisions(pairs.list, timing.timeScale);
-
- // trigger collision events
- if (pairs.collisionStart.length > 0)
- Events.trigger(engine, 'collisionStart', { pairs: pairs.collisionStart });
-
- // iteratively resolve position between collisions
- Resolver.preSolvePosition(pairs.list);
- for (i = 0; i < engine.positionIterations; i++) {
- Resolver.solvePosition(pairs.list, timing.timeScale);
- }
- Resolver.postSolvePosition(allBodies);
-
- // update all constraints (second pass)
- Constraint.preSolveAll(allBodies);
- for (i = 0; i < engine.constraintIterations; i++) {
- Constraint.solveAll(allConstraints, timing.timeScale);
- }
- Constraint.postSolveAll(allBodies);
-
- // iteratively resolve velocity between collisions
- Resolver.preSolveVelocity(pairs.list);
- for (i = 0; i < engine.velocityIterations; i++) {
- Resolver.solveVelocity(pairs.list, timing.timeScale);
- }
-
- // trigger collision events
- if (pairs.collisionActive.length > 0)
- Events.trigger(engine, 'collisionActive', { pairs: pairs.collisionActive });
-
- if (pairs.collisionEnd.length > 0)
- Events.trigger(engine, 'collisionEnd', { pairs: pairs.collisionEnd });
-
- // clear force buffers
- Engine._bodiesClearForces(allBodies);
-
- Events.trigger(engine, 'afterUpdate', event);
-
- // log the time elapsed computing this update
- engine.timing.lastElapsed = Common.now() - startTime;
-
- return engine;
- };
-
- /**
- * Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`.
- * @method merge
- * @param {engine} engineA
- * @param {engine} engineB
- */
- Engine.merge = function(engineA, engineB) {
- Common.extend(engineA, engineB);
-
- if (engineB.world) {
- engineA.world = engineB.world;
-
- Engine.clear(engineA);
-
- var bodies = Composite.allBodies(engineA.world);
-
- for (var i = 0; i < bodies.length; i++) {
- var body = bodies[i];
- Sleeping.set(body, false);
- body.id = Common.nextId();
- }
- }
- };
-
- /**
- * Clears the engine pairs and detector.
- * @method clear
- * @param {engine} engine
- */
- Engine.clear = function(engine) {
- Pairs.clear(engine.pairs);
- Detector.clear(engine.detector);
- };
-
- /**
- * Zeroes the `body.force` and `body.torque` force buffers.
- * @method _bodiesClearForces
- * @private
- * @param {body[]} bodies
- */
- Engine._bodiesClearForces = function(bodies) {
- for (var i = 0; i < bodies.length; i++) {
- var body = bodies[i];
-
- // reset force buffers
- body.force.x = 0;
- body.force.y = 0;
- body.torque = 0;
- }
- };
-
- /**
- * Applys a mass dependant force to all given bodies.
- * @method _bodiesApplyGravity
- * @private
- * @param {body[]} bodies
- * @param {vector} gravity
- */
- Engine._bodiesApplyGravity = function(bodies, gravity) {
- var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001;
-
- if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) {
- return;
- }
-
- for (var i = 0; i < bodies.length; i++) {
- var body = bodies[i];
-
- if (body.isStatic || body.isSleeping)
- continue;
-
- // apply gravity
- body.force.y += body.mass * gravity.y * gravityScale;
- body.force.x += body.mass * gravity.x * gravityScale;
- }
- };
-
- /**
- * Applys `Body.update` to all given `bodies`.
- * @method _bodiesUpdate
- * @private
- * @param {body[]} bodies
- * @param {number} deltaTime
- * The amount of time elapsed between updates
- * @param {number} timeScale
- * @param {number} correction
- * The Verlet correction factor (deltaTime / lastDeltaTime)
- * @param {bounds} worldBounds
- */
- Engine._bodiesUpdate = function(bodies, deltaTime, timeScale, correction, worldBounds) {
- for (var i = 0; i < bodies.length; i++) {
- var body = bodies[i];
-
- if (body.isStatic || body.isSleeping)
- continue;
-
- Body.update(body, deltaTime, timeScale, correction);
- }
- };
-
- /**
- * A deprecated alias for `Runner.run`, use `Matter.Runner.run(engine)` instead and see `Matter.Runner` for more information.
- * @deprecated use Matter.Runner.run(engine) instead
- * @method run
- * @param {engine} engine
- */
-
- /**
- * Fired just before an update
- *
- * @event beforeUpdate
- * @param {object} event An event object
- * @param {number} event.timestamp The engine.timing.timestamp of the event
- * @param {engine} event.source The source object of the event
- * @param {string} event.name The name of the event
- */
-
- /**
- * Fired after engine update and all collision events
- *
- * @event afterUpdate
- * @param {object} event An event object
- * @param {number} event.timestamp The engine.timing.timestamp of the event
- * @param {engine} event.source The source object of the event
- * @param {string} event.name The name of the event
- */
-
- /**
- * Fired after engine update, provides a list of all pairs that have started to collide in the current tick (if any)
- *
- * @event collisionStart
- * @param {object} event An event object
- * @param {pair[]} event.pairs List of affected pairs
- * @param {number} event.timestamp The engine.timing.timestamp of the event
- * @param {engine} event.source The source object of the event
- * @param {string} event.name The name of the event
- */
-
- /**
- * Fired after engine update, provides a list of all pairs that are colliding in the current tick (if any)
- *
- * @event collisionActive
- * @param {object} event An event object
- * @param {pair[]} event.pairs List of affected pairs
- * @param {number} event.timestamp The engine.timing.timestamp of the event
- * @param {engine} event.source The source object of the event
- * @param {string} event.name The name of the event
- */
-
- /**
- * Fired after engine update, provides a list of all pairs that have ended collision in the current tick (if any)
- *
- * @event collisionEnd
- * @param {object} event An event object
- * @param {pair[]} event.pairs List of affected pairs
- * @param {number} event.timestamp The engine.timing.timestamp of the event
- * @param {engine} event.source The source object of the event
- * @param {string} event.name The name of the event
- */
-
- /*
- *
- * Properties Documentation
- *
- */
-
- /**
- * An integer `Number` that specifies the number of position iterations to perform each update.
- * The higher the value, the higher quality the simulation will be at the expense of performance.
- *
- * @property positionIterations
- * @type number
- * @default 6
- */
-
- /**
- * An integer `Number` that specifies the number of velocity iterations to perform each update.
- * The higher the value, the higher quality the simulation will be at the expense of performance.
- *
- * @property velocityIterations
- * @type number
- * @default 4
- */
-
- /**
- * An integer `Number` that specifies the number of constraint iterations to perform each update.
- * The higher the value, the higher quality the simulation will be at the expense of performance.
- * The default value of `2` is usually very adequate.
- *
- * @property constraintIterations
- * @type number
- * @default 2
- */
-
- /**
- * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module.
- * Sleeping can improve stability and performance, but often at the expense of accuracy.
- *
- * @property enableSleeping
- * @type boolean
- * @default false
- */
-
- /**
- * An `Object` containing properties regarding the timing systems of the engine.
- *
- * @property timing
- * @type object
- */
-
- /**
- * A `Number` that specifies the global scaling factor of time for all bodies.
- * A value of `0` freezes the simulation.
- * A value of `0.1` gives a slow-motion effect.
- * A value of `1.2` gives a speed-up effect.
- *
- * @property timing.timeScale
- * @type number
- * @default 1
- */
-
- /**
- * A `Number` that specifies the current simulation-time in milliseconds starting from `0`.
- * It is incremented on every `Engine.update` by the given `delta` argument.
- *
- * @property timing.timestamp
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that represents the total execution time elapsed during the last `Engine.update` in milliseconds.
- * It is updated by timing from the start of the last `Engine.update` call until it ends.
- *
- * This value will also include the total execution time of all event handlers directly or indirectly triggered by the engine update.
- *
- * @property timing.lastElapsed
- * @type number
- * @default 0
- */
-
- /**
- * A `Number` that represents the `delta` value used in the last engine update.
- *
- * @property timing.lastDelta
- * @type number
- * @default 0
- */
-
- /**
- * A `Matter.Detector` instance.
- *
- * @property detector
- * @type detector
- * @default a Matter.Detector instance
- */
-
- /**
- * A `Matter.Grid` instance.
- *
- * @deprecated replaced by `engine.detector`
- * @property grid
- * @type grid
- * @default a Matter.Grid instance
- */
-
- /**
- * Replaced by and now alias for `engine.grid`.
- *
- * @deprecated replaced by `engine.detector`
- * @property broadphase
- * @type grid
- * @default a Matter.Grid instance
- */
-
- /**
- * The root `Matter.Composite` instance that will contain all bodies, constraints and other composites to be simulated by this engine.
- *
- * @property world
- * @type composite
- * @default a Matter.Composite instance
- */
-
- /**
- * An object reserved for storing plugin-specific properties.
- *
- * @property plugin
- * @type {}
- */
-
- /**
- * The gravity to apply on all bodies in `engine.world`.
- *
- * @property gravity
- * @type object
- */
-
- /**
- * The gravity x component.
- *
- * @property gravity.x
- * @type object
- * @default 0
- */
-
- /**
- * The gravity y component.
- *
- * @property gravity.y
- * @type object
- * @default 1
- */
-
- /**
- * The gravity scale factor.
- *
- * @property gravity.scale
- * @type object
- * @default 0.001
- */
-
-})();
-
-
-/***/ }),
-/* 19 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.Resolver` module contains methods for resolving collision pairs.
-*
-* @class Resolver
-*/
-
-var Resolver = {};
-
-module.exports = Resolver;
-
-var Vertices = __webpack_require__(3);
-var Bounds = __webpack_require__(1);
-
-(function() {
-
- Resolver._restingThresh = 4;
- Resolver._restingThreshTangent = 6;
- Resolver._positionDampen = 0.9;
- Resolver._positionWarming = 0.8;
- Resolver._frictionNormalMultiplier = 5;
-
- /**
- * Prepare pairs for position solving.
- * @method preSolvePosition
- * @param {pair[]} pairs
- */
- Resolver.preSolvePosition = function(pairs) {
- var i,
- pair,
- activeCount,
- pairsLength = pairs.length;
-
- // find total contacts on each body
- for (i = 0; i < pairsLength; i++) {
- pair = pairs[i];
-
- if (!pair.isActive)
- continue;
-
- activeCount = pair.activeContacts.length;
- pair.collision.parentA.totalContacts += activeCount;
- pair.collision.parentB.totalContacts += activeCount;
- }
- };
-
- /**
- * Find a solution for pair positions.
- * @method solvePosition
- * @param {pair[]} pairs
- * @param {number} timeScale
- */
- Resolver.solvePosition = function(pairs, timeScale) {
- var i,
- pair,
- collision,
- bodyA,
- bodyB,
- normal,
- contactShare,
- positionImpulse,
- positionDampen = Resolver._positionDampen,
- pairsLength = pairs.length;
-
- // find impulses required to resolve penetration
- for (i = 0; i < pairsLength; i++) {
- pair = pairs[i];
-
- if (!pair.isActive || pair.isSensor)
- continue;
-
- collision = pair.collision;
- bodyA = collision.parentA;
- bodyB = collision.parentB;
- normal = collision.normal;
-
- // get current separation between body edges involved in collision
- pair.separation =
- normal.x * (bodyB.positionImpulse.x + collision.penetration.x - bodyA.positionImpulse.x)
- + normal.y * (bodyB.positionImpulse.y + collision.penetration.y - bodyA.positionImpulse.y);
- }
-
- for (i = 0; i < pairsLength; i++) {
- pair = pairs[i];
-
- if (!pair.isActive || pair.isSensor)
- continue;
-
- collision = pair.collision;
- bodyA = collision.parentA;
- bodyB = collision.parentB;
- normal = collision.normal;
- positionImpulse = (pair.separation - pair.slop) * timeScale;
-
- if (bodyA.isStatic || bodyB.isStatic)
- positionImpulse *= 2;
-
- if (!(bodyA.isStatic || bodyA.isSleeping)) {
- contactShare = positionDampen / bodyA.totalContacts;
- bodyA.positionImpulse.x += normal.x * positionImpulse * contactShare;
- bodyA.positionImpulse.y += normal.y * positionImpulse * contactShare;
- }
-
- if (!(bodyB.isStatic || bodyB.isSleeping)) {
- contactShare = positionDampen / bodyB.totalContacts;
- bodyB.positionImpulse.x -= normal.x * positionImpulse * contactShare;
- bodyB.positionImpulse.y -= normal.y * positionImpulse * contactShare;
- }
- }
- };
-
- /**
- * Apply position resolution.
- * @method postSolvePosition
- * @param {body[]} bodies
- */
- Resolver.postSolvePosition = function(bodies) {
- var positionWarming = Resolver._positionWarming,
- bodiesLength = bodies.length,
- verticesTranslate = Vertices.translate,
- boundsUpdate = Bounds.update;
-
- for (var i = 0; i < bodiesLength; i++) {
- var body = bodies[i],
- positionImpulse = body.positionImpulse,
- positionImpulseX = positionImpulse.x,
- positionImpulseY = positionImpulse.y,
- velocity = body.velocity;
-
- // reset contact count
- body.totalContacts = 0;
-
- if (positionImpulseX !== 0 || positionImpulseY !== 0) {
- // update body geometry
- for (var j = 0; j < body.parts.length; j++) {
- var part = body.parts[j];
- verticesTranslate(part.vertices, positionImpulse);
- boundsUpdate(part.bounds, part.vertices, velocity);
- part.position.x += positionImpulseX;
- part.position.y += positionImpulseY;
- }
-
- // move the body without changing velocity
- body.positionPrev.x += positionImpulseX;
- body.positionPrev.y += positionImpulseY;
-
- if (positionImpulseX * velocity.x + positionImpulseY * velocity.y < 0) {
- // reset cached impulse if the body has velocity along it
- positionImpulse.x = 0;
- positionImpulse.y = 0;
- } else {
- // warm the next iteration
- positionImpulse.x *= positionWarming;
- positionImpulse.y *= positionWarming;
- }
- }
- }
- };
-
- /**
- * Prepare pairs for velocity solving.
- * @method preSolveVelocity
- * @param {pair[]} pairs
- */
- Resolver.preSolveVelocity = function(pairs) {
- var pairsLength = pairs.length,
- i,
- j;
-
- for (i = 0; i < pairsLength; i++) {
- var pair = pairs[i];
-
- if (!pair.isActive || pair.isSensor)
- continue;
-
- var contacts = pair.activeContacts,
- contactsLength = contacts.length,
- collision = pair.collision,
- bodyA = collision.parentA,
- bodyB = collision.parentB,
- normal = collision.normal,
- tangent = collision.tangent;
-
- // resolve each contact
- for (j = 0; j < contactsLength; j++) {
- var contact = contacts[j],
- contactVertex = contact.vertex,
- normalImpulse = contact.normalImpulse,
- tangentImpulse = contact.tangentImpulse;
-
- if (normalImpulse !== 0 || tangentImpulse !== 0) {
- // total impulse from contact
- var impulseX = normal.x * normalImpulse + tangent.x * tangentImpulse,
- impulseY = normal.y * normalImpulse + tangent.y * tangentImpulse;
-
- // apply impulse from contact
- if (!(bodyA.isStatic || bodyA.isSleeping)) {
- bodyA.positionPrev.x += impulseX * bodyA.inverseMass;
- bodyA.positionPrev.y += impulseY * bodyA.inverseMass;
- bodyA.anglePrev += bodyA.inverseInertia * (
- (contactVertex.x - bodyA.position.x) * impulseY
- - (contactVertex.y - bodyA.position.y) * impulseX
- );
- }
-
- if (!(bodyB.isStatic || bodyB.isSleeping)) {
- bodyB.positionPrev.x -= impulseX * bodyB.inverseMass;
- bodyB.positionPrev.y -= impulseY * bodyB.inverseMass;
- bodyB.anglePrev -= bodyB.inverseInertia * (
- (contactVertex.x - bodyB.position.x) * impulseY
- - (contactVertex.y - bodyB.position.y) * impulseX
- );
- }
- }
- }
- }
- };
-
- /**
- * Find a solution for pair velocities.
- * @method solveVelocity
- * @param {pair[]} pairs
- * @param {number} timeScale
- */
- Resolver.solveVelocity = function(pairs, timeScale) {
- var timeScaleSquared = timeScale * timeScale,
- restingThresh = Resolver._restingThresh * timeScaleSquared,
- frictionNormalMultiplier = Resolver._frictionNormalMultiplier,
- restingThreshTangent = Resolver._restingThreshTangent * timeScaleSquared,
- NumberMaxValue = Number.MAX_VALUE,
- pairsLength = pairs.length,
- tangentImpulse,
- maxFriction,
- i,
- j;
-
- for (i = 0; i < pairsLength; i++) {
- var pair = pairs[i];
-
- if (!pair.isActive || pair.isSensor)
- continue;
-
- var collision = pair.collision,
- bodyA = collision.parentA,
- bodyB = collision.parentB,
- bodyAVelocity = bodyA.velocity,
- bodyBVelocity = bodyB.velocity,
- normalX = collision.normal.x,
- normalY = collision.normal.y,
- tangentX = collision.tangent.x,
- tangentY = collision.tangent.y,
- contacts = pair.activeContacts,
- contactsLength = contacts.length,
- contactShare = 1 / contactsLength,
- inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass,
- friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier * timeScaleSquared;
-
- // update body velocities
- bodyAVelocity.x = bodyA.position.x - bodyA.positionPrev.x;
- bodyAVelocity.y = bodyA.position.y - bodyA.positionPrev.y;
- bodyBVelocity.x = bodyB.position.x - bodyB.positionPrev.x;
- bodyBVelocity.y = bodyB.position.y - bodyB.positionPrev.y;
- bodyA.angularVelocity = bodyA.angle - bodyA.anglePrev;
- bodyB.angularVelocity = bodyB.angle - bodyB.anglePrev;
-
- // resolve each contact
- for (j = 0; j < contactsLength; j++) {
- var contact = contacts[j],
- contactVertex = contact.vertex;
-
- var offsetAX = contactVertex.x - bodyA.position.x,
- offsetAY = contactVertex.y - bodyA.position.y,
- offsetBX = contactVertex.x - bodyB.position.x,
- offsetBY = contactVertex.y - bodyB.position.y;
-
- var velocityPointAX = bodyAVelocity.x - offsetAY * bodyA.angularVelocity,
- velocityPointAY = bodyAVelocity.y + offsetAX * bodyA.angularVelocity,
- velocityPointBX = bodyBVelocity.x - offsetBY * bodyB.angularVelocity,
- velocityPointBY = bodyBVelocity.y + offsetBX * bodyB.angularVelocity;
-
- var relativeVelocityX = velocityPointAX - velocityPointBX,
- relativeVelocityY = velocityPointAY - velocityPointBY;
-
- var normalVelocity = normalX * relativeVelocityX + normalY * relativeVelocityY,
- tangentVelocity = tangentX * relativeVelocityX + tangentY * relativeVelocityY;
-
- // coulomb friction
- var normalOverlap = pair.separation + normalVelocity;
- var normalForce = Math.min(normalOverlap, 1);
- normalForce = normalOverlap < 0 ? 0 : normalForce;
-
- var frictionLimit = normalForce * friction;
-
- if (tangentVelocity > frictionLimit || -tangentVelocity > frictionLimit) {
- maxFriction = tangentVelocity > 0 ? tangentVelocity : -tangentVelocity;
- tangentImpulse = pair.friction * (tangentVelocity > 0 ? 1 : -1) * timeScaleSquared;
-
- if (tangentImpulse < -maxFriction) {
- tangentImpulse = -maxFriction;
- } else if (tangentImpulse > maxFriction) {
- tangentImpulse = maxFriction;
- }
- } else {
- tangentImpulse = tangentVelocity;
- maxFriction = NumberMaxValue;
- }
-
- // account for mass, inertia and contact offset
- var oAcN = offsetAX * normalY - offsetAY * normalX,
- oBcN = offsetBX * normalY - offsetBY * normalX,
- share = contactShare / (inverseMassTotal + bodyA.inverseInertia * oAcN * oAcN + bodyB.inverseInertia * oBcN * oBcN);
-
- // raw impulses
- var normalImpulse = (1 + pair.restitution) * normalVelocity * share;
- tangentImpulse *= share;
-
- // handle high velocity and resting collisions separately
- if (normalVelocity * normalVelocity > restingThresh && normalVelocity < 0) {
- // high normal velocity so clear cached contact normal impulse
- contact.normalImpulse = 0;
- } else {
- // solve resting collision constraints using Erin Catto's method (GDC08)
- // impulse constraint tends to 0
- var contactNormalImpulse = contact.normalImpulse;
- contact.normalImpulse += normalImpulse;
- contact.normalImpulse = Math.min(contact.normalImpulse, 0);
- normalImpulse = contact.normalImpulse - contactNormalImpulse;
- }
-
- // handle high velocity and resting collisions separately
- if (tangentVelocity * tangentVelocity > restingThreshTangent) {
- // high tangent velocity so clear cached contact tangent impulse
- contact.tangentImpulse = 0;
- } else {
- // solve resting collision constraints using Erin Catto's method (GDC08)
- // tangent impulse tends to -tangentSpeed or +tangentSpeed
- var contactTangentImpulse = contact.tangentImpulse;
- contact.tangentImpulse += tangentImpulse;
- if (contact.tangentImpulse < -maxFriction) contact.tangentImpulse = -maxFriction;
- if (contact.tangentImpulse > maxFriction) contact.tangentImpulse = maxFriction;
- tangentImpulse = contact.tangentImpulse - contactTangentImpulse;
- }
-
- // total impulse from contact
- var impulseX = normalX * normalImpulse + tangentX * tangentImpulse,
- impulseY = normalY * normalImpulse + tangentY * tangentImpulse;
-
- // apply impulse from contact
- if (!(bodyA.isStatic || bodyA.isSleeping)) {
- bodyA.positionPrev.x += impulseX * bodyA.inverseMass;
- bodyA.positionPrev.y += impulseY * bodyA.inverseMass;
- bodyA.anglePrev += (offsetAX * impulseY - offsetAY * impulseX) * bodyA.inverseInertia;
- }
-
- if (!(bodyB.isStatic || bodyB.isSleeping)) {
- bodyB.positionPrev.x -= impulseX * bodyB.inverseMass;
- bodyB.positionPrev.y -= impulseY * bodyB.inverseMass;
- bodyB.anglePrev -= (offsetBX * impulseY - offsetBY * impulseX) * bodyB.inverseInertia;
- }
- }
- }
- };
-
-})();
-
-
-/***/ }),
-/* 20 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets.
-*
-* @class Pairs
-*/
-
-var Pairs = {};
-
-module.exports = Pairs;
-
-var Pair = __webpack_require__(9);
-var Common = __webpack_require__(0);
-
-(function() {
-
- /**
- * Creates a new pairs structure.
- * @method create
- * @param {object} options
- * @return {pairs} A new pairs structure
- */
- Pairs.create = function(options) {
- return Common.extend({
- table: {},
- list: [],
- collisionStart: [],
- collisionActive: [],
- collisionEnd: []
- }, options);
- };
-
- /**
- * Updates pairs given a list of collisions.
- * @method update
- * @param {object} pairs
- * @param {collision[]} collisions
- * @param {number} timestamp
- */
- Pairs.update = function(pairs, collisions, timestamp) {
- var pairsList = pairs.list,
- pairsListLength = pairsList.length,
- pairsTable = pairs.table,
- collisionsLength = collisions.length,
- collisionStart = pairs.collisionStart,
- collisionEnd = pairs.collisionEnd,
- collisionActive = pairs.collisionActive,
- collision,
- pairIndex,
- pair,
- i;
-
- // clear collision state arrays, but maintain old reference
- collisionStart.length = 0;
- collisionEnd.length = 0;
- collisionActive.length = 0;
-
- for (i = 0; i < pairsListLength; i++) {
- pairsList[i].confirmedActive = false;
- }
-
- for (i = 0; i < collisionsLength; i++) {
- collision = collisions[i];
- pair = collision.pair;
-
- if (pair) {
- // pair already exists (but may or may not be active)
- if (pair.isActive) {
- // pair exists and is active
- collisionActive.push(pair);
- } else {
- // pair exists but was inactive, so a collision has just started again
- collisionStart.push(pair);
- }
-
- // update the pair
- Pair.update(pair, collision, timestamp);
- pair.confirmedActive = true;
- } else {
- // pair did not exist, create a new pair
- pair = Pair.create(collision, timestamp);
- pairsTable[pair.id] = pair;
-
- // push the new pair
- collisionStart.push(pair);
- pairsList.push(pair);
- }
- }
-
- // find pairs that are no longer active
- var removePairIndex = [];
- pairsListLength = pairsList.length;
-
- for (i = 0; i < pairsListLength; i++) {
- pair = pairsList[i];
-
- if (!pair.confirmedActive) {
- Pair.setActive(pair, false, timestamp);
- collisionEnd.push(pair);
-
- if (!pair.collision.bodyA.isSleeping && !pair.collision.bodyB.isSleeping) {
- removePairIndex.push(i);
- }
- }
- }
-
- // remove inactive pairs
- for (i = 0; i < removePairIndex.length; i++) {
- pairIndex = removePairIndex[i] - i;
- pair = pairsList[pairIndex];
- pairsList.splice(pairIndex, 1);
- delete pairsTable[pair.id];
- }
- };
-
- /**
- * Clears the given pairs structure.
- * @method clear
- * @param {pairs} pairs
- * @return {pairs} pairs
- */
- Pairs.clear = function(pairs) {
- pairs.table = {};
- pairs.list.length = 0;
- pairs.collisionStart.length = 0;
- pairs.collisionActive.length = 0;
- pairs.collisionEnd.length = 0;
- return pairs;
- };
-
-})();
-
-
-/***/ }),
-/* 21 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Matter = module.exports = __webpack_require__(22);
-
-Matter.Axes = __webpack_require__(11);
-Matter.Bodies = __webpack_require__(12);
-Matter.Body = __webpack_require__(6);
-Matter.Bounds = __webpack_require__(1);
-Matter.Collision = __webpack_require__(8);
-Matter.Common = __webpack_require__(0);
-Matter.Composite = __webpack_require__(5);
-Matter.Composites = __webpack_require__(23);
-Matter.Constraint = __webpack_require__(10);
-Matter.Contact = __webpack_require__(17);
-Matter.Detector = __webpack_require__(14);
-Matter.Engine = __webpack_require__(18);
-Matter.Events = __webpack_require__(4);
-Matter.Grid = __webpack_require__(24);
-Matter.Mouse = __webpack_require__(13);
-Matter.MouseConstraint = __webpack_require__(25);
-Matter.Pair = __webpack_require__(9);
-Matter.Pairs = __webpack_require__(20);
-Matter.Plugin = __webpack_require__(15);
-Matter.Query = __webpack_require__(26);
-Matter.Render = __webpack_require__(16);
-Matter.Resolver = __webpack_require__(19);
-Matter.Runner = __webpack_require__(27);
-Matter.SAT = __webpack_require__(28);
-Matter.Sleeping = __webpack_require__(7);
-Matter.Svg = __webpack_require__(29);
-Matter.Vector = __webpack_require__(2);
-Matter.Vertices = __webpack_require__(3);
-Matter.World = __webpack_require__(30);
-
-// temporary back compatibility
-Matter.Engine.run = Matter.Runner.run;
-Matter.Common.deprecated(Matter.Engine, 'run', 'Engine.run ➤ use Matter.Runner.run(engine) instead');
-
-
-/***/ }),
-/* 22 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter` module is the top level namespace. It also includes a function for installing plugins on top of the library.
-*
-* @class Matter
-*/
-
-var Matter = {};
-
-module.exports = Matter;
-
-var Plugin = __webpack_require__(15);
-var Common = __webpack_require__(0);
-
-(function() {
-
- /**
- * The library name.
- * @property name
- * @readOnly
- * @type {String}
- */
- Matter.name = 'matter-js';
-
- /**
- * The library version.
- * @property version
- * @readOnly
- * @type {String}
- */
- Matter.version = true ? "0.18.0" : undefined;
-
- /**
- * A list of plugin dependencies to be installed. These are normally set and installed through `Matter.use`.
- * Alternatively you may set `Matter.uses` manually and install them by calling `Plugin.use(Matter)`.
- * @property uses
- * @type {Array}
- */
- Matter.uses = [];
-
- /**
- * The plugins that have been installed through `Matter.Plugin.install`. Read only.
- * @property used
- * @readOnly
- * @type {Array}
- */
- Matter.used = [];
-
- /**
- * Installs the given plugins on the `Matter` namespace.
- * This is a short-hand for `Plugin.use`, see it for more information.
- * Call this function once at the start of your code, with all of the plugins you wish to install as arguments.
- * Avoid calling this function multiple times unless you intend to manually control installation order.
- * @method use
- * @param ...plugin {Function} The plugin(s) to install on `base` (multi-argument).
- */
- Matter.use = function() {
- Plugin.use(Matter, Array.prototype.slice.call(arguments));
- };
-
- /**
- * Chains a function to excute before the original function on the given `path` relative to `Matter`.
- * See also docs for `Common.chain`.
- * @method before
- * @param {string} path The path relative to `Matter`
- * @param {function} func The function to chain before the original
- * @return {function} The chained function that replaced the original
- */
- Matter.before = function(path, func) {
- path = path.replace(/^Matter./, '');
- return Common.chainPathBefore(Matter, path, func);
- };
-
- /**
- * Chains a function to excute after the original function on the given `path` relative to `Matter`.
- * See also docs for `Common.chain`.
- * @method after
- * @param {string} path The path relative to `Matter`
- * @param {function} func The function to chain after the original
- * @return {function} The chained function that replaced the original
- */
- Matter.after = function(path, func) {
- path = path.replace(/^Matter./, '');
- return Common.chainPathAfter(Matter, path, func);
- };
-
-})();
-
-
-/***/ }),
-/* 23 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.Composites` module contains factory methods for creating composite bodies
-* with commonly used configurations (such as stacks and chains).
-*
-* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
-*
-* @class Composites
-*/
-
-var Composites = {};
-
-module.exports = Composites;
-
-var Composite = __webpack_require__(5);
-var Constraint = __webpack_require__(10);
-var Common = __webpack_require__(0);
-var Body = __webpack_require__(6);
-var Bodies = __webpack_require__(12);
-var deprecated = Common.deprecated;
-
-(function() {
-
- /**
- * Create a new composite containing bodies created in the callback in a grid arrangement.
- * This function uses the body's bounds to prevent overlaps.
- * @method stack
- * @param {number} xx
- * @param {number} yy
- * @param {number} columns
- * @param {number} rows
- * @param {number} columnGap
- * @param {number} rowGap
- * @param {function} callback
- * @return {composite} A new composite containing objects created in the callback
- */
- Composites.stack = function(xx, yy, columns, rows, columnGap, rowGap, callback) {
- var stack = Composite.create({ label: 'Stack' }),
- x = xx,
- y = yy,
- lastBody,
- i = 0;
-
- for (var row = 0; row < rows; row++) {
- var maxHeight = 0;
-
- for (var column = 0; column < columns; column++) {
- var body = callback(x, y, column, row, lastBody, i);
-
- if (body) {
- var bodyHeight = body.bounds.max.y - body.bounds.min.y,
- bodyWidth = body.bounds.max.x - body.bounds.min.x;
-
- if (bodyHeight > maxHeight)
- maxHeight = bodyHeight;
-
- Body.translate(body, { x: bodyWidth * 0.5, y: bodyHeight * 0.5 });
-
- x = body.bounds.max.x + columnGap;
-
- Composite.addBody(stack, body);
-
- lastBody = body;
- i += 1;
- } else {
- x += columnGap;
- }
- }
-
- y += maxHeight + rowGap;
- x = xx;
- }
-
- return stack;
- };
-
- /**
- * Chains all bodies in the given composite together using constraints.
- * @method chain
- * @param {composite} composite
- * @param {number} xOffsetA
- * @param {number} yOffsetA
- * @param {number} xOffsetB
- * @param {number} yOffsetB
- * @param {object} options
- * @return {composite} A new composite containing objects chained together with constraints
- */
- Composites.chain = function(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options) {
- var bodies = composite.bodies;
-
- for (var i = 1; i < bodies.length; i++) {
- var bodyA = bodies[i - 1],
- bodyB = bodies[i],
- bodyAHeight = bodyA.bounds.max.y - bodyA.bounds.min.y,
- bodyAWidth = bodyA.bounds.max.x - bodyA.bounds.min.x,
- bodyBHeight = bodyB.bounds.max.y - bodyB.bounds.min.y,
- bodyBWidth = bodyB.bounds.max.x - bodyB.bounds.min.x;
-
- var defaults = {
- bodyA: bodyA,
- pointA: { x: bodyAWidth * xOffsetA, y: bodyAHeight * yOffsetA },
- bodyB: bodyB,
- pointB: { x: bodyBWidth * xOffsetB, y: bodyBHeight * yOffsetB }
- };
-
- var constraint = Common.extend(defaults, options);
-
- Composite.addConstraint(composite, Constraint.create(constraint));
- }
-
- composite.label += ' Chain';
-
- return composite;
- };
-
- /**
- * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces.
- * @method mesh
- * @param {composite} composite
- * @param {number} columns
- * @param {number} rows
- * @param {boolean} crossBrace
- * @param {object} options
- * @return {composite} The composite containing objects meshed together with constraints
- */
- Composites.mesh = function(composite, columns, rows, crossBrace, options) {
- var bodies = composite.bodies,
- row,
- col,
- bodyA,
- bodyB,
- bodyC;
-
- for (row = 0; row < rows; row++) {
- for (col = 1; col < columns; col++) {
- bodyA = bodies[(col - 1) + (row * columns)];
- bodyB = bodies[col + (row * columns)];
- Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));
- }
-
- if (row > 0) {
- for (col = 0; col < columns; col++) {
- bodyA = bodies[col + ((row - 1) * columns)];
- bodyB = bodies[col + (row * columns)];
- Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));
-
- if (crossBrace && col > 0) {
- bodyC = bodies[(col - 1) + ((row - 1) * columns)];
- Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));
- }
-
- if (crossBrace && col < columns - 1) {
- bodyC = bodies[(col + 1) + ((row - 1) * columns)];
- Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));
- }
- }
- }
- }
-
- composite.label += ' Mesh';
-
- return composite;
- };
-
- /**
- * Create a new composite containing bodies created in the callback in a pyramid arrangement.
- * This function uses the body's bounds to prevent overlaps.
- * @method pyramid
- * @param {number} xx
- * @param {number} yy
- * @param {number} columns
- * @param {number} rows
- * @param {number} columnGap
- * @param {number} rowGap
- * @param {function} callback
- * @return {composite} A new composite containing objects created in the callback
- */
- Composites.pyramid = function(xx, yy, columns, rows, columnGap, rowGap, callback) {
- return Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y, column, row, lastBody, i) {
- var actualRows = Math.min(rows, Math.ceil(columns / 2)),
- lastBodyWidth = lastBody ? lastBody.bounds.max.x - lastBody.bounds.min.x : 0;
-
- if (row > actualRows)
- return;
-
- // reverse row order
- row = actualRows - row;
-
- var start = row,
- end = columns - 1 - row;
-
- if (column < start || column > end)
- return;
-
- // retroactively fix the first body's position, since width was unknown
- if (i === 1) {
- Body.translate(lastBody, { x: (column + (columns % 2 === 1 ? 1 : -1)) * lastBodyWidth, y: 0 });
- }
-
- var xOffset = lastBody ? column * lastBodyWidth : 0;
-
- return callback(xx + xOffset + column * columnGap, y, column, row, lastBody, i);
- });
- };
-
- /**
- * This has now moved to the [newtonsCradle example](https://github.com/liabru/matter-js/blob/master/examples/newtonsCradle.js), follow that instead as this function is deprecated here.
- * @deprecated moved to newtonsCradle example
- * @method newtonsCradle
- * @param {number} xx
- * @param {number} yy
- * @param {number} number
- * @param {number} size
- * @param {number} length
- * @return {composite} A new composite newtonsCradle body
- */
- Composites.newtonsCradle = function(xx, yy, number, size, length) {
- var newtonsCradle = Composite.create({ label: 'Newtons Cradle' });
-
- for (var i = 0; i < number; i++) {
- var separation = 1.9,
- circle = Bodies.circle(xx + i * (size * separation), yy + length, size,
- { inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }),
- constraint = Constraint.create({ pointA: { x: xx + i * (size * separation), y: yy }, bodyB: circle });
-
- Composite.addBody(newtonsCradle, circle);
- Composite.addConstraint(newtonsCradle, constraint);
- }
-
- return newtonsCradle;
- };
-
- deprecated(Composites, 'newtonsCradle', 'Composites.newtonsCradle ➤ moved to newtonsCradle example');
-
- /**
- * This has now moved to the [car example](https://github.com/liabru/matter-js/blob/master/examples/car.js), follow that instead as this function is deprecated here.
- * @deprecated moved to car example
- * @method car
- * @param {number} xx
- * @param {number} yy
- * @param {number} width
- * @param {number} height
- * @param {number} wheelSize
- * @return {composite} A new composite car body
- */
- Composites.car = function(xx, yy, width, height, wheelSize) {
- var group = Body.nextGroup(true),
- wheelBase = 20,
- wheelAOffset = -width * 0.5 + wheelBase,
- wheelBOffset = width * 0.5 - wheelBase,
- wheelYOffset = 0;
-
- var car = Composite.create({ label: 'Car' }),
- body = Bodies.rectangle(xx, yy, width, height, {
- collisionFilter: {
- group: group
- },
- chamfer: {
- radius: height * 0.5
- },
- density: 0.0002
- });
-
- var wheelA = Bodies.circle(xx + wheelAOffset, yy + wheelYOffset, wheelSize, {
- collisionFilter: {
- group: group
- },
- friction: 0.8
- });
-
- var wheelB = Bodies.circle(xx + wheelBOffset, yy + wheelYOffset, wheelSize, {
- collisionFilter: {
- group: group
- },
- friction: 0.8
- });
-
- var axelA = Constraint.create({
- bodyB: body,
- pointB: { x: wheelAOffset, y: wheelYOffset },
- bodyA: wheelA,
- stiffness: 1,
- length: 0
- });
-
- var axelB = Constraint.create({
- bodyB: body,
- pointB: { x: wheelBOffset, y: wheelYOffset },
- bodyA: wheelB,
- stiffness: 1,
- length: 0
- });
-
- Composite.addBody(car, body);
- Composite.addBody(car, wheelA);
- Composite.addBody(car, wheelB);
- Composite.addConstraint(car, axelA);
- Composite.addConstraint(car, axelB);
-
- return car;
- };
-
- deprecated(Composites, 'car', 'Composites.car ➤ moved to car example');
-
- /**
- * This has now moved to the [softBody example](https://github.com/liabru/matter-js/blob/master/examples/softBody.js)
- * and the [cloth example](https://github.com/liabru/matter-js/blob/master/examples/cloth.js), follow those instead as this function is deprecated here.
- * @deprecated moved to softBody and cloth examples
- * @method softBody
- * @param {number} xx
- * @param {number} yy
- * @param {number} columns
- * @param {number} rows
- * @param {number} columnGap
- * @param {number} rowGap
- * @param {boolean} crossBrace
- * @param {number} particleRadius
- * @param {} particleOptions
- * @param {} constraintOptions
- * @return {composite} A new composite softBody
- */
- Composites.softBody = function(xx, yy, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) {
- particleOptions = Common.extend({ inertia: Infinity }, particleOptions);
- constraintOptions = Common.extend({ stiffness: 0.2, render: { type: 'line', anchors: false } }, constraintOptions);
-
- var softBody = Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y) {
- return Bodies.circle(x, y, particleRadius, particleOptions);
- });
-
- Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions);
-
- softBody.label = 'Soft Body';
-
- return softBody;
- };
-
- deprecated(Composites, 'softBody', 'Composites.softBody ➤ moved to softBody and cloth examples');
-})();
-
-
-/***/ }),
-/* 24 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* This module has now been replaced by `Matter.Detector`.
-*
-* All usage should be migrated to `Matter.Detector` or another alternative.
-* For back-compatibility purposes this module will remain for a short term and then later removed in a future release.
-*
-* The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures.
-*
-* @class Grid
-* @deprecated
-*/
-
-var Grid = {};
-
-module.exports = Grid;
-
-var Pair = __webpack_require__(9);
-var Common = __webpack_require__(0);
-var deprecated = Common.deprecated;
-
-(function() {
-
- /**
- * Creates a new grid.
- * @deprecated replaced by Matter.Detector
- * @method create
- * @param {} options
- * @return {grid} A new grid
- */
- Grid.create = function(options) {
- var defaults = {
- buckets: {},
- pairs: {},
- pairsList: [],
- bucketWidth: 48,
- bucketHeight: 48
- };
-
- return Common.extend(defaults, options);
- };
-
- /**
- * The width of a single grid bucket.
- *
- * @property bucketWidth
- * @type number
- * @default 48
- */
-
- /**
- * The height of a single grid bucket.
- *
- * @property bucketHeight
- * @type number
- * @default 48
- */
-
- /**
- * Updates the grid.
- * @deprecated replaced by Matter.Detector
- * @method update
- * @param {grid} grid
- * @param {body[]} bodies
- * @param {engine} engine
- * @param {boolean} forceUpdate
- */
- Grid.update = function(grid, bodies, engine, forceUpdate) {
- var i, col, row,
- world = engine.world,
- buckets = grid.buckets,
- bucket,
- bucketId,
- gridChanged = false;
-
- for (i = 0; i < bodies.length; i++) {
- var body = bodies[i];
-
- if (body.isSleeping && !forceUpdate)
- continue;
-
- // temporary back compatibility bounds check
- if (world.bounds && (body.bounds.max.x < world.bounds.min.x || body.bounds.min.x > world.bounds.max.x
- || body.bounds.max.y < world.bounds.min.y || body.bounds.min.y > world.bounds.max.y))
- continue;
-
- var newRegion = Grid._getRegion(grid, body);
-
- // if the body has changed grid region
- if (!body.region || newRegion.id !== body.region.id || forceUpdate) {
-
- if (!body.region || forceUpdate)
- body.region = newRegion;
-
- var union = Grid._regionUnion(newRegion, body.region);
-
- // update grid buckets affected by region change
- // iterate over the union of both regions
- for (col = union.startCol; col <= union.endCol; col++) {
- for (row = union.startRow; row <= union.endRow; row++) {
- bucketId = Grid._getBucketId(col, row);
- bucket = buckets[bucketId];
-
- var isInsideNewRegion = (col >= newRegion.startCol && col <= newRegion.endCol
- && row >= newRegion.startRow && row <= newRegion.endRow);
-
- var isInsideOldRegion = (col >= body.region.startCol && col <= body.region.endCol
- && row >= body.region.startRow && row <= body.region.endRow);
-
- // remove from old region buckets
- if (!isInsideNewRegion && isInsideOldRegion) {
- if (isInsideOldRegion) {
- if (bucket)
- Grid._bucketRemoveBody(grid, bucket, body);
- }
- }
-
- // add to new region buckets
- if (body.region === newRegion || (isInsideNewRegion && !isInsideOldRegion) || forceUpdate) {
- if (!bucket)
- bucket = Grid._createBucket(buckets, bucketId);
- Grid._bucketAddBody(grid, bucket, body);
- }
- }
- }
-
- // set the new region
- body.region = newRegion;
-
- // flag changes so we can update pairs
- gridChanged = true;
- }
- }
-
- // update pairs list only if pairs changed (i.e. a body changed region)
- if (gridChanged)
- grid.pairsList = Grid._createActivePairsList(grid);
- };
-
- deprecated(Grid, 'update', 'Grid.update ➤ replaced by Matter.Detector');
-
- /**
- * Clears the grid.
- * @deprecated replaced by Matter.Detector
- * @method clear
- * @param {grid} grid
- */
- Grid.clear = function(grid) {
- grid.buckets = {};
- grid.pairs = {};
- grid.pairsList = [];
- };
-
- deprecated(Grid, 'clear', 'Grid.clear ➤ replaced by Matter.Detector');
-
- /**
- * Finds the union of two regions.
- * @method _regionUnion
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} regionA
- * @param {} regionB
- * @return {} region
- */
- Grid._regionUnion = function(regionA, regionB) {
- var startCol = Math.min(regionA.startCol, regionB.startCol),
- endCol = Math.max(regionA.endCol, regionB.endCol),
- startRow = Math.min(regionA.startRow, regionB.startRow),
- endRow = Math.max(regionA.endRow, regionB.endRow);
-
- return Grid._createRegion(startCol, endCol, startRow, endRow);
- };
-
- /**
- * Gets the region a given body falls in for a given grid.
- * @method _getRegion
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} grid
- * @param {} body
- * @return {} region
- */
- Grid._getRegion = function(grid, body) {
- var bounds = body.bounds,
- startCol = Math.floor(bounds.min.x / grid.bucketWidth),
- endCol = Math.floor(bounds.max.x / grid.bucketWidth),
- startRow = Math.floor(bounds.min.y / grid.bucketHeight),
- endRow = Math.floor(bounds.max.y / grid.bucketHeight);
-
- return Grid._createRegion(startCol, endCol, startRow, endRow);
- };
-
- /**
- * Creates a region.
- * @method _createRegion
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} startCol
- * @param {} endCol
- * @param {} startRow
- * @param {} endRow
- * @return {} region
- */
- Grid._createRegion = function(startCol, endCol, startRow, endRow) {
- return {
- id: startCol + ',' + endCol + ',' + startRow + ',' + endRow,
- startCol: startCol,
- endCol: endCol,
- startRow: startRow,
- endRow: endRow
- };
- };
-
- /**
- * Gets the bucket id at the given position.
- * @method _getBucketId
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} column
- * @param {} row
- * @return {string} bucket id
- */
- Grid._getBucketId = function(column, row) {
- return 'C' + column + 'R' + row;
- };
-
- /**
- * Creates a bucket.
- * @method _createBucket
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} buckets
- * @param {} bucketId
- * @return {} bucket
- */
- Grid._createBucket = function(buckets, bucketId) {
- var bucket = buckets[bucketId] = [];
- return bucket;
- };
-
- /**
- * Adds a body to a bucket.
- * @method _bucketAddBody
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} grid
- * @param {} bucket
- * @param {} body
- */
- Grid._bucketAddBody = function(grid, bucket, body) {
- var gridPairs = grid.pairs,
- pairId = Pair.id,
- bucketLength = bucket.length,
- i;
-
- // add new pairs
- for (i = 0; i < bucketLength; i++) {
- var bodyB = bucket[i];
-
- if (body.id === bodyB.id || (body.isStatic && bodyB.isStatic))
- continue;
-
- // keep track of the number of buckets the pair exists in
- // important for Grid.update to work
- var id = pairId(body, bodyB),
- pair = gridPairs[id];
-
- if (pair) {
- pair[2] += 1;
- } else {
- gridPairs[id] = [body, bodyB, 1];
- }
- }
-
- // add to bodies (after pairs, otherwise pairs with self)
- bucket.push(body);
- };
-
- /**
- * Removes a body from a bucket.
- * @method _bucketRemoveBody
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} grid
- * @param {} bucket
- * @param {} body
- */
- Grid._bucketRemoveBody = function(grid, bucket, body) {
- var gridPairs = grid.pairs,
- pairId = Pair.id,
- i;
-
- // remove from bucket
- bucket.splice(Common.indexOf(bucket, body), 1);
-
- var bucketLength = bucket.length;
-
- // update pair counts
- for (i = 0; i < bucketLength; i++) {
- // keep track of the number of buckets the pair exists in
- // important for _createActivePairsList to work
- var pair = gridPairs[pairId(body, bucket[i])];
-
- if (pair)
- pair[2] -= 1;
- }
- };
-
- /**
- * Generates a list of the active pairs in the grid.
- * @method _createActivePairsList
- * @deprecated replaced by Matter.Detector
- * @private
- * @param {} grid
- * @return [] pairs
- */
- Grid._createActivePairsList = function(grid) {
- var pair,
- gridPairs = grid.pairs,
- pairKeys = Common.keys(gridPairs),
- pairKeysLength = pairKeys.length,
- pairs = [],
- k;
-
- // iterate over grid.pairs
- for (k = 0; k < pairKeysLength; k++) {
- pair = gridPairs[pairKeys[k]];
-
- // if pair exists in at least one bucket
- // it is a pair that needs further collision testing so push it
- if (pair[2] > 0) {
- pairs.push(pair);
- } else {
- delete gridPairs[pairKeys[k]];
- }
- }
-
- return pairs;
- };
-
-})();
-
-
-/***/ }),
-/* 25 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.MouseConstraint` module contains methods for creating mouse constraints.
-* Mouse constraints are used for allowing user interaction, providing the ability to move bodies via the mouse or touch.
-*
-* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
-*
-* @class MouseConstraint
-*/
-
-var MouseConstraint = {};
-
-module.exports = MouseConstraint;
-
-var Vertices = __webpack_require__(3);
-var Sleeping = __webpack_require__(7);
-var Mouse = __webpack_require__(13);
-var Events = __webpack_require__(4);
-var Detector = __webpack_require__(14);
-var Constraint = __webpack_require__(10);
-var Composite = __webpack_require__(5);
-var Common = __webpack_require__(0);
-var Bounds = __webpack_require__(1);
-
-(function() {
-
- /**
- * Creates a new mouse constraint.
- * All properties have default values, and many are pre-calculated automatically based on other properties.
- * See the properties section below for detailed information on what you can pass via the `options` object.
- * @method create
- * @param {engine} engine
- * @param {} options
- * @return {MouseConstraint} A new MouseConstraint
- */
- MouseConstraint.create = function(engine, options) {
- var mouse = (engine ? engine.mouse : null) || (options ? options.mouse : null);
-
- if (!mouse) {
- if (engine && engine.render && engine.render.canvas) {
- mouse = Mouse.create(engine.render.canvas);
- } else if (options && options.element) {
- mouse = Mouse.create(options.element);
- } else {
- mouse = Mouse.create();
- Common.warn('MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected');
- }
- }
-
- var constraint = Constraint.create({
- label: 'Mouse Constraint',
- pointA: mouse.position,
- pointB: { x: 0, y: 0 },
- length: 0.01,
- stiffness: 0.1,
- angularStiffness: 1,
- render: {
- strokeStyle: '#90EE90',
- lineWidth: 3
- }
- });
-
- var defaults = {
- type: 'mouseConstraint',
- mouse: mouse,
- element: null,
- body: null,
- constraint: constraint,
- collisionFilter: {
- category: 0x0001,
- mask: 0xFFFFFFFF,
- group: 0
- }
- };
-
- var mouseConstraint = Common.extend(defaults, options);
-
- Events.on(engine, 'beforeUpdate', function() {
- var allBodies = Composite.allBodies(engine.world);
- MouseConstraint.update(mouseConstraint, allBodies);
- MouseConstraint._triggerEvents(mouseConstraint);
- });
-
- return mouseConstraint;
- };
-
- /**
- * Updates the given mouse constraint.
- * @private
- * @method update
- * @param {MouseConstraint} mouseConstraint
- * @param {body[]} bodies
- */
- MouseConstraint.update = function(mouseConstraint, bodies) {
- var mouse = mouseConstraint.mouse,
- constraint = mouseConstraint.constraint,
- body = mouseConstraint.body;
-
- if (mouse.button === 0) {
- if (!constraint.bodyB) {
- for (var i = 0; i < bodies.length; i++) {
- body = bodies[i];
- if (Bounds.contains(body.bounds, mouse.position)
- && Detector.canCollide(body.collisionFilter, mouseConstraint.collisionFilter)) {
- for (var j = body.parts.length > 1 ? 1 : 0; j < body.parts.length; j++) {
- var part = body.parts[j];
- if (Vertices.contains(part.vertices, mouse.position)) {
- constraint.pointA = mouse.position;
- constraint.bodyB = mouseConstraint.body = body;
- constraint.pointB = { x: mouse.position.x - body.position.x, y: mouse.position.y - body.position.y };
- constraint.angleB = body.angle;
-
- Sleeping.set(body, false);
- Events.trigger(mouseConstraint, 'startdrag', { mouse: mouse, body: body });
-
- break;
- }
- }
- }
- }
- } else {
- Sleeping.set(constraint.bodyB, false);
- constraint.pointA = mouse.position;
- }
- } else {
- constraint.bodyB = mouseConstraint.body = null;
- constraint.pointB = null;
-
- if (body)
- Events.trigger(mouseConstraint, 'enddrag', { mouse: mouse, body: body });
- }
- };
-
- /**
- * Triggers mouse constraint events.
- * @method _triggerEvents
- * @private
- * @param {mouse} mouseConstraint
- */
- MouseConstraint._triggerEvents = function(mouseConstraint) {
- var mouse = mouseConstraint.mouse,
- mouseEvents = mouse.sourceEvents;
-
- if (mouseEvents.mousemove)
- Events.trigger(mouseConstraint, 'mousemove', { mouse: mouse });
-
- if (mouseEvents.mousedown)
- Events.trigger(mouseConstraint, 'mousedown', { mouse: mouse });
-
- if (mouseEvents.mouseup)
- Events.trigger(mouseConstraint, 'mouseup', { mouse: mouse });
-
- // reset the mouse state ready for the next step
- Mouse.clearSourceEvents(mouse);
- };
-
- /*
- *
- * Events Documentation
- *
- */
-
- /**
- * Fired when the mouse has moved (or a touch moves) during the last step
- *
- * @event mousemove
- * @param {} event An event object
- * @param {mouse} event.mouse The engine's mouse instance
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired when the mouse is down (or a touch has started) during the last step
- *
- * @event mousedown
- * @param {} event An event object
- * @param {mouse} event.mouse The engine's mouse instance
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired when the mouse is up (or a touch has ended) during the last step
- *
- * @event mouseup
- * @param {} event An event object
- * @param {mouse} event.mouse The engine's mouse instance
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired when the user starts dragging a body
- *
- * @event startdrag
- * @param {} event An event object
- * @param {mouse} event.mouse The engine's mouse instance
- * @param {body} event.body The body being dragged
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired when the user ends dragging a body
- *
- * @event enddrag
- * @param {} event An event object
- * @param {mouse} event.mouse The engine's mouse instance
- * @param {body} event.body The body that has stopped being dragged
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /*
- *
- * Properties Documentation
- *
- */
-
- /**
- * A `String` denoting the type of object.
- *
- * @property type
- * @type string
- * @default "constraint"
- * @readOnly
- */
-
- /**
- * The `Mouse` instance in use. If not supplied in `MouseConstraint.create`, one will be created.
- *
- * @property mouse
- * @type mouse
- * @default mouse
- */
-
- /**
- * The `Body` that is currently being moved by the user, or `null` if no body.
- *
- * @property body
- * @type body
- * @default null
- */
-
- /**
- * The `Constraint` object that is used to move the body during interaction.
- *
- * @property constraint
- * @type constraint
- */
-
- /**
- * An `Object` that specifies the collision filter properties.
- * The collision filter allows the user to define which types of body this mouse constraint can interact with.
- * See `body.collisionFilter` for more information.
- *
- * @property collisionFilter
- * @type object
- */
-
-})();
-
-
-/***/ }),
-/* 26 */
-/***/ (function(module, exports, __webpack_require__) {
-
-/**
-* The `Matter.Query` module contains methods for performing collision queries.
-*
-* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
-*
-* @class Query
-*/
-
-var Query = {};
-
-module.exports = Query;
-
-var Vector = __webpack_require__(2);
-var Collision = __webpack_require__(8);
-var Bounds = __webpack_require__(1);
-var Bodies = __webpack_require__(12);
-var Vertices = __webpack_require__(3);
-
-(function() {
-
- /**
- * Returns a list of collisions between `body` and `bodies`.
- * @method collides
- * @param {body} body
- * @param {body[]} bodies
- * @return {collision[]} Collisions
- */
- Query.collides = function(body, bodies) {
- var collisions = [],
- bodiesLength = bodies.length,
- bounds = body.bounds,
- collides = Collision.collides,
- overlaps = Bounds.overlaps;
-
- for (var i = 0; i < bodiesLength; i++) {
- var bodyA = bodies[i],
- partsALength = bodyA.parts.length,
- partsAStart = partsALength === 1 ? 0 : 1;
-
- if (overlaps(bodyA.bounds, bounds)) {
- for (var j = partsAStart; j < partsALength; j++) {
- var part = bodyA.parts[j];
-
- if (overlaps(part.bounds, bounds)) {
- var collision = collides(part, body);
-
- if (collision) {
- collisions.push(collision);
- break;
- }
- }
- }
- }
- }
-
- return collisions;
- };
-
- /**
- * Casts a ray segment against a set of bodies and returns all collisions, ray width is optional. Intersection points are not provided.
- * @method ray
- * @param {body[]} bodies
- * @param {vector} startPoint
- * @param {vector} endPoint
- * @param {number} [rayWidth]
- * @return {collision[]} Collisions
- */
- Query.ray = function(bodies, startPoint, endPoint, rayWidth) {
- rayWidth = rayWidth || 1e-100;
-
- var rayAngle = Vector.angle(startPoint, endPoint),
- rayLength = Vector.magnitude(Vector.sub(startPoint, endPoint)),
- rayX = (endPoint.x + startPoint.x) * 0.5,
- rayY = (endPoint.y + startPoint.y) * 0.5,
- ray = Bodies.rectangle(rayX, rayY, rayLength, rayWidth, { angle: rayAngle }),
- collisions = Query.collides(ray, bodies);
-
- for (var i = 0; i < collisions.length; i += 1) {
- var collision = collisions[i];
- collision.body = collision.bodyB = collision.bodyA;
- }
-
- return collisions;
- };
-
- /**
- * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies.
- * @method region
- * @param {body[]} bodies
- * @param {bounds} bounds
- * @param {bool} [outside=false]
- * @return {body[]} The bodies matching the query
- */
- Query.region = function(bodies, bounds, outside) {
- var result = [];
-
- for (var i = 0; i < bodies.length; i++) {
- var body = bodies[i],
- overlaps = Bounds.overlaps(body.bounds, bounds);
- if ((overlaps && !outside) || (!overlaps && outside))
- result.push(body);
- }
-
- return result;
- };
-
- /**
- * Returns all bodies whose vertices contain the given point, from the given set of bodies.
- * @method point
- * @param {body[]} bodies
- * @param {vector} point
- * @return {body[]} The bodies matching the query
- */
- Query.point = function(bodies, point) {
- var result = [];
-
- for (var i = 0; i < bodies.length; i++) {
- var body = bodies[i];
-
- if (Bounds.contains(body.bounds, point)) {
- for (var j = body.parts.length === 1 ? 0 : 1; j < body.parts.length; j++) {
- var part = body.parts[j];
-
- if (Bounds.contains(part.bounds, point)
- && Vertices.contains(part.vertices, point)) {
- result.push(body);
- break;
- }
- }
- }
- }
-
- return result;
- };
-
-})();
-
-
/***/ }),
/* 27 */
/***/ (function(module, exports, __webpack_require__) {
@@ -10168,8 +10425,8 @@ var Runner = {};
module.exports = Runner;
-var Events = __webpack_require__(4);
-var Engine = __webpack_require__(18);
+var Events = __webpack_require__(5);
+var Engine = __webpack_require__(17);
var Common = __webpack_require__(0);
(function() {
@@ -10207,13 +10464,11 @@ var Common = __webpack_require__(0);
Runner.create = function(options) {
var defaults = {
fps: 60,
- correction: 1,
deltaSampleSize: 60,
counterTimestamp: 0,
frameCounter: 0,
deltaHistory: [],
timePrev: null,
- timeScalePrev: 1,
frameRequestId: null,
isFixed: false,
enabled: true
@@ -10241,8 +10496,8 @@ var Common = __webpack_require__(0);
runner = Runner.create();
}
- (function render(time){
- runner.frameRequestId = _requestAnimationFrame(render);
+ (function run(time){
+ runner.frameRequestId = _requestAnimationFrame(run);
if (time && runner.enabled) {
Runner.tick(runner, engine, time);
@@ -10263,16 +10518,8 @@ var Common = __webpack_require__(0);
*/
Runner.tick = function(runner, engine, time) {
var timing = engine.timing,
- correction = 1,
delta;
- // create an event object
- var event = {
- timestamp: timing.timestamp
- };
-
- Events.trigger(runner, 'beforeTick', event);
-
if (runner.isFixed) {
// fixed timestep
delta = runner.delta;
@@ -10285,27 +10532,21 @@ var Common = __webpack_require__(0);
runner.deltaHistory.push(delta);
runner.deltaHistory = runner.deltaHistory.slice(-runner.deltaSampleSize);
delta = Math.min.apply(null, runner.deltaHistory);
-
+
// limit delta
delta = delta < runner.deltaMin ? runner.deltaMin : delta;
delta = delta > runner.deltaMax ? runner.deltaMax : delta;
- // correction for delta
- correction = delta / runner.delta;
-
// update engine timing object
runner.delta = delta;
}
- // time correction for time scaling
- if (runner.timeScalePrev !== 0)
- correction *= timing.timeScale / runner.timeScalePrev;
+ // create an event object
+ var event = {
+ timestamp: timing.timestamp
+ };
- if (timing.timeScale === 0)
- correction = 0;
-
- runner.timeScalePrev = timing.timeScale;
- runner.correction = correction;
+ Events.trigger(runner, 'beforeTick', event);
// fps counter
runner.frameCounter += 1;
@@ -10319,7 +10560,9 @@ var Common = __webpack_require__(0);
// update
Events.trigger(runner, 'beforeUpdate', event);
- Engine.update(engine, delta, correction);
+
+ Engine.update(engine, delta);
+
Events.trigger(runner, 'afterUpdate', event);
Events.trigger(runner, 'afterTick', event);
@@ -10734,7 +10977,7 @@ var World = {};
module.exports = World;
-var Composite = __webpack_require__(5);
+var Composite = __webpack_require__(6);
var Common = __webpack_require__(0);
(function() {
diff --git a/build/matter.min.js b/build/matter.min.js
index 29d25db..1b31215 100644
--- a/build/matter.min.js
+++ b/build/matter.min.js
@@ -1,6 +1,6 @@
/*!
- * matter-js 0.18.0 by @liabru
+ * matter-js 0.19.0 by @liabru
* http://brm.io/matter-js/
* License MIT
*/
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Matter",[],t):"object"==typeof exports?exports.Matter=t():e.Matter=t()}(this,(function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=21)}([function(e,t){var n={};e.exports=n,function(){n._nextId=0,n._seed=0,n._nowStartTime=+new Date,n._warnedOnce={},n._decomp=null,n.extend=function(e,t){var i,o;"boolean"==typeof t?(i=2,o=t):(i=1,o=!0);for(var r=i;r0;t--){var i=Math.floor(n.random()*(t+1)),o=e[t];e[t]=e[i],e[i]=o}return e},n.choose=function(e){return e[Math.floor(n.random()*e.length)]},n.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},n.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},n.isFunction=function(e){return"function"==typeof e},n.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},n.isString=function(e){return"[object String]"===toString.call(e)},n.clamp=function(e,t,n){return en?n:e},n.sign=function(e){return e<0?-1:1},n.now=function(){if("undefined"!=typeof window&&window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return Date.now?Date.now():new Date-n._nowStartTime},n.random=function(t,n){return n=void 0!==n?n:1,(t=void 0!==t?t:0)+e()*(n-t)};var e=function(){return n._seed=(9301*n._seed+49297)%233280,n._seed/233280};n.colorToNumber=function(e){return 3==(e=e.replace("#","")).length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},n.logLevel=1,n.log=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.info=function(){console&&n.logLevel>0&&n.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warn=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warnOnce=function(){var e=Array.prototype.slice.call(arguments).join(" ");n._warnedOnce[e]||(n.warn(e),n._warnedOnce[e]=!0)},n.deprecated=function(e,t,i){e[t]=n.chain((function(){n.warnOnce("🔅 deprecated 🔅",i)}),e[t])},n.nextId=function(){return n._nextId++},n.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;ne.max.x&&(e.max.x=o.x),o.xe.max.y&&(e.max.y=o.y),o.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},n.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},n.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},n.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},n.shift=function(e,t){var n=e.max.x-e.min.x,i=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+i}},function(e,t){var n={};e.exports=n,n.create=function(e,t){return{x:e||0,y:t||0}},n.clone=function(e){return{x:e.x,y:e.y}},n.magnitude=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},n.magnitudeSquared=function(e){return e.x*e.x+e.y*e.y},n.rotate=function(e,t,n){var i=Math.cos(t),o=Math.sin(t);n||(n={});var r=e.x*i-e.y*o;return n.y=e.x*o+e.y*i,n.x=r,n},n.rotateAbout=function(e,t,n,i){var o=Math.cos(t),r=Math.sin(t);i||(i={});var a=n.x+((e.x-n.x)*o-(e.y-n.y)*r);return i.y=n.y+((e.x-n.x)*r+(e.y-n.y)*o),i.x=a,i},n.normalise=function(e){var t=n.magnitude(e);return 0===t?{x:0,y:0}:{x:e.x/t,y:e.y/t}},n.dot=function(e,t){return e.x*t.x+e.y*t.y},n.cross=function(e,t){return e.x*t.y-e.y*t.x},n.cross3=function(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)},n.add=function(e,t,n){return n||(n={}),n.x=e.x+t.x,n.y=e.y+t.y,n},n.sub=function(e,t,n){return n||(n={}),n.x=e.x-t.x,n.y=e.y-t.y,n},n.mult=function(e,t){return{x:e.x*t,y:e.y*t}},n.div=function(e,t){return{x:e.x/t,y:e.y/t}},n.perp=function(e,t){return{x:(t=!0===t?-1:1)*-e.y,y:t*e.x}},n.neg=function(e){return{x:-e.x,y:-e.y}},n.angle=function(e,t){return Math.atan2(t.y-e.y,t.x-e.x)},n._temp=[n.create(),n.create(),n.create(),n.create(),n.create(),n.create()]},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.create=function(e,t){for(var n=[],i=0;i0)return!1;a=n}return!0},i.scale=function(e,t,n,r){if(1===t&&1===n)return e;var a,s;r=r||i.centre(e);for(var l=0;l=0?l-1:e.length-1],u=e[l],d=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},i.hull=function(e){var t,n,i=[],r=[];for((e=e.slice(0)).sort((function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y})),n=0;n=2&&o.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];i.length>=2&&o.cross3(i[i.length-2],i[i.length-1],t)<=0;)i.pop();i.push(t)}return i.pop(),r.pop(),i.concat(r)}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.on=function(e,t,n){for(var i,o=t.split(" "),r=0;r0){n||(n={}),i=t.split(" ");for(var c=0;c0&&r.rotateAbout(a.position,n,e.position,a.position)}},i.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y,e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},i.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},i.translate=function(e,t){i.setPosition(e,r.add(e.position,t))},i.rotate=function(e,t,n){if(n){var o=Math.cos(t),r=Math.sin(t),a=e.position.x-n.x,s=e.position.y-n.y;i.setPosition(e,{x:n.x+(a*o-s*r),y:n.y+(a*r+s*o)}),i.setAngle(e,e.angle+t)}else i.setAngle(e,e.angle+t)},i.scale=function(e,t,n,r){var a=0,s=0;r=r||e.position;for(var u=0;u0&&(a+=d.area,s+=d.inertia),d.position.x=r.x+(d.position.x-r.x)*t,d.position.y=r.y+(d.position.y-r.y)*n,l.update(d.bounds,d.vertices,e.velocity)}e.parts.length>1&&(e.area=a,e.isStatic||(i.setMass(e,e.density*a),i.setInertia(e,s))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},i.update=function(e,t,n,i){var a=Math.pow(t*n*e.timeScale,2),s=1-e.frictionAir*n*e.timeScale,u=e.position.x-e.positionPrev.x,d=e.position.y-e.positionPrev.y;e.velocity.x=u*s*i+e.force.x/e.mass*a,e.velocity.y=d*s*i+e.force.y/e.mass*a,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.angularVelocity=(e.angle-e.anglePrev)*s*i+e.torque/e.inertia*a,e.anglePrev=e.angle,e.angle+=e.angularVelocity,e.speed=r.magnitude(e.velocity),e.angularSpeed=Math.abs(e.angularVelocity);for(var p=0;p0&&(f.position.x+=e.velocity.x,f.position.y+=e.velocity.y),0!==e.angularVelocity&&(o.rotate(f.vertices,e.angularVelocity,e.position),c.rotate(f.axes,e.angularVelocity),p>0&&r.rotateAbout(f.position,e.angularVelocity,e.position,f.position)),l.update(f.bounds,f.vertices,e.velocity)}},i.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var i=t.x-e.position.x,o=t.y-e.position.y;e.torque+=i*n.y-o*n.x},i._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n0&&r.motion=r.sleepThreshold&&i.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else i.set(r,!1)}},i.afterCollisions=function(e,t){for(var n=t*t*t,o=0;oi._motionWakeThreshold*n&&i.set(c,!1)}}}},i.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||o.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&o.trigger(e,"sleepEnd"))}},function(e,t,n){var i={};e.exports=i;var o,r,a,s=n(3),l=n(9);o=[],r={overlap:0,axis:null},a={overlap:0,axis:null},i.create=function(e,t){return{pair:null,collided:!1,bodyA:e,bodyB:t,parentA:e.parent,parentB:t.parent,depth:0,normal:{x:0,y:0},tangent:{x:0,y:0},penetration:{x:0,y:0},supports:[]}},i.collides=function(e,t,n){if(i._overlapAxes(r,e.vertices,t.vertices,e.axes),r.overlap<=0)return null;if(i._overlapAxes(a,t.vertices,e.vertices,t.axes),a.overlap<=0)return null;var o,c,u=n&&n.table[l.id(e,t)];u?o=u.collision:((o=i.create(e,t)).collided=!0,o.bodyA=e.idP?P=s:sC?C=s:so?o=a:al.frictionStatic?s.frictionStatic:l.frictionStatic,e.restitution=s.restitution>l.restitution?s.restitution:l.restitution,e.slop=s.slop>l.slop?s.slop:l.slop,t.pair=e,a.length=0;for(var u=0;u0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var a={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(a.type="pin",a.anchors=!1):t.stiffness<.9&&(a.type="spring"),t.render=c.extend(a,t.render),t},i.preSolveAll=function(e){for(var t=0;t0&&(d.position.x+=c.x,d.position.y+=c.y),0!==c.angle&&(o.rotate(d.vertices,c.angle,n.position),l.rotate(d.axes,c.angle),u>0&&r.rotateAbout(d.position,c.angle,n.position,d.position)),s.update(d.bounds,d.vertices,n.velocity)}c.angle*=i._warming,c.x*=i._warming,c.y*=i._warming}}},i.pointAWorld=function(e){return{x:(e.bodyA?e.bodyA.position.x:0)+e.pointA.x,y:(e.bodyA?e.bodyA.position.y:0)+e.pointA.y}},i.pointBWorld=function(e){return{x:(e.bodyB?e.bodyB.position.x:0)+e.pointB.x,y:(e.bodyB?e.bodyB.position.y:0)+e.pointB.y}}},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.fromVertices=function(e){for(var t={},n=0;n0&&o.area(M)1?(v=a.create(r.extend({parts:y.slice(0)},i)),a.setPosition(v,{x:e,y:t}),v):y[0]}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.create=function(e){var t={};return e||o.log("Mouse.create: element was undefined, defaulting to document.body","warn"),t.element=e||document.body,t.absolute={x:0,y:0},t.position={x:0,y:0},t.mousedownPosition={x:0,y:0},t.mouseupPosition={x:0,y:0},t.offset={x:0,y:0},t.scale={x:1,y:1},t.wheelDelta=0,t.button=-1,t.pixelRatio=parseInt(t.element.getAttribute("data-pixel-ratio"),10)||1,t.sourceEvents={mousemove:null,mousedown:null,mouseup:null,mousewheel:null},t.mousemove=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&(t.button=0,e.preventDefault()),t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.sourceEvents.mousemove=e},t.mousedown=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches?(t.button=0,e.preventDefault()):t.button=e.button,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mousedownPosition.x=t.position.x,t.mousedownPosition.y=t.position.y,t.sourceEvents.mousedown=e},t.mouseup=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&e.preventDefault(),t.button=-1,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mouseupPosition.x=t.position.x,t.mouseupPosition.y=t.position.y,t.sourceEvents.mouseup=e},t.mousewheel=function(e){t.wheelDelta=Math.max(-1,Math.min(1,e.wheelDelta||-e.detail)),e.preventDefault()},i.setElement(t,t.element),t},i.setElement=function(e,t){e.element=t,t.addEventListener("mousemove",e.mousemove),t.addEventListener("mousedown",e.mousedown),t.addEventListener("mouseup",e.mouseup),t.addEventListener("mousewheel",e.mousewheel),t.addEventListener("DOMMouseScroll",e.mousewheel),t.addEventListener("touchmove",e.mousemove),t.addEventListener("touchstart",e.mousedown),t.addEventListener("touchend",e.mouseup)},i.clearSourceEvents=function(e){e.sourceEvents.mousemove=null,e.sourceEvents.mousedown=null,e.sourceEvents.mouseup=null,e.sourceEvents.mousewheel=null,e.wheelDelta=0},i.setOffset=function(e,t){e.offset.x=t.x,e.offset.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i.setScale=function(e,t){e.scale.x=t.x,e.scale.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i._getRelativeMousePosition=function(e,t,n){var i,o,r=t.getBoundingClientRect(),a=document.documentElement||document.body.parentNode||document.body,s=void 0!==window.pageXOffset?window.pageXOffset:a.scrollLeft,l=void 0!==window.pageYOffset?window.pageYOffset:a.scrollTop,c=e.changedTouches;return c?(i=c[0].pageX-r.left-s,o=c[0].pageY-r.top-l):(i=e.pageX-r.left-s,o=e.pageY-r.top-l),{x:i/(t.clientWidth/(t.width||t.clientWidth)*n),y:o/(t.clientHeight/(t.height||t.clientHeight)*n)}}},function(e,t,n){var i={};e.exports=i;var o=n(0),r=n(8);i.create=function(e){return o.extend({bodies:[],pairs:null},e)},i.setBodies=function(e,t){e.bodies=t.slice(0)},i.clear=function(e){e.bodies=[]},i.collisions=function(e){var t,n,o=[],a=e.pairs,s=e.bodies,l=s.length,c=i.canCollide,u=r.collides;for(s.sort(i._compareBoundsX),t=0;tf)break;if(!(vB.max.y)&&(!m||!h.isStatic&&!h.isSleeping)&&c(d.collisionFilter,h.collisionFilter)){var b=h.parts.length;if(x&&1===b)(C=u(d,h,a))&&o.push(C);else for(var S=b>1?1:0,w=g>1?1:0;wB.max.x||p.max.xB.max.y||(C=u(A,M,a))&&o.push(C)}}}}return o},i.canCollide=function(e,t){return e.group===t.group&&0!==e.group?e.group>0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)},i._compareBoundsX=function(e,t){return e.bounds.min.x-t.bounds.min.x}},function(e,t,n){var i={};e.exports=i;var o=n(0);i._registry={},i.register=function(e){if(i.isPlugin(e)||o.warn("Plugin.register:",i.toString(e),"does not implement all required fields."),e.name in i._registry){var t=i._registry[e.name],n=i.versionParse(e.version).number,r=i.versionParse(t.version).number;n>r?(o.warn("Plugin.register:",i.toString(t),"was upgraded to",i.toString(e)),i._registry[e.name]=e):n-1},i.isFor=function(e,t){var n=e.for&&i.dependencyParse(e.for);return!e.for||t.name===n.name&&i.versionSatisfies(t.version,n.range)},i.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0!==e.uses.length){for(var n=i.dependencies(e),r=o.topologicalSort(n),a=[],s=0;s0&&o.info(a.join(" "))}else o.warn("Plugin.use:",i.toString(e),"does not specify any dependencies to install.")},i.dependencies=function(e,t){var n=i.dependencyParse(e),r=n.name;if(!(r in(t=t||{}))){e=i.resolve(e)||e,t[r]=o.map(e.uses||[],(function(t){i.isPlugin(t)&&i.register(t);var r=i.dependencyParse(t),a=i.resolve(t);return a&&!i.versionSatisfies(a.version,r.range)?(o.warn("Plugin.dependencies:",i.toString(a),"does not satisfy",i.toString(r),"used by",i.toString(n)+"."),a._warned=!0,e._warned=!0):a||(o.warn("Plugin.dependencies:",i.toString(t),"used by",i.toString(n),"could not be resolved."),e._warned=!0),r.name}));for(var a=0;a=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-+]+)?$/;t.test(e)||o.warn("Plugin.versionParse:",e,"is not a valid version or range.");var n=t.exec(e),i=Number(n[4]),r=Number(n[5]),a=Number(n[6]);return{isRange:Boolean(n[1]||n[2]),version:n[3],range:e,operator:n[1]||n[2]||"",major:i,minor:r,patch:a,parts:[i,r,a],prerelease:n[7],number:1e8*i+1e4*r+a}},i.versionSatisfies=function(e,t){t=t||"*";var n=i.versionParse(t),o=i.versionParse(e);if(n.isRange){if("*"===n.operator||"*"===e)return!0;if(">"===n.operator)return o.number>n.number;if(">="===n.operator)return o.number>=n.number;if("~"===n.operator)return o.major===n.major&&o.minor===n.minor&&o.patch>=n.patch;if("^"===n.operator)return n.major>0?o.major===n.major&&o.number>=n.number:n.minor>0?o.minor===n.minor&&o.patch>=n.patch:o.patch===n.patch}return e===t||"*"===e}},function(e,t,n){var i={};e.exports=i;var o=n(0),r=n(5),a=n(1),s=n(4),l=n(2),c=n(13);!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout((function(){e(o.now())}),1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),i._goodFps=30,i._goodDelta=1e3/60,i.create=function(e){var t={controller:i,engine:null,element:null,canvas:null,mouse:null,frameRequestId:null,timing:{historySize:60,delta:0,deltaHistory:[],lastTime:0,lastTimestamp:0,lastElapsed:0,timestampElapsed:0,timestampElapsedHistory:[],engineDeltaHistory:[],engineElapsedHistory:[],elapsedHistory:[]},options:{width:800,height:600,pixelRatio:1,background:"#14151f",wireframeBackground:"#14151f",hasBounds:!!e.bounds,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showStats:!1,showPerformance:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showSeparations:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showVertexNumbers:!1,showConvexHulls:!1,showInternalEdges:!1,showMousePosition:!1}},n=o.extend(t,e);return n.canvas&&(n.canvas.width=n.options.width||n.canvas.width,n.canvas.height=n.options.height||n.canvas.height),n.mouse=e.mouse,n.engine=e.engine,n.canvas=n.canvas||d(n.options.width,n.options.height),n.context=n.canvas.getContext("2d"),n.textures={},n.bounds=n.bounds||{min:{x:0,y:0},max:{x:n.canvas.width,y:n.canvas.height}},n.options.showBroadphase=!1,1!==n.options.pixelRatio&&i.setPixelRatio(n,n.options.pixelRatio),o.isElement(n.element)?n.element.appendChild(n.canvas):n.canvas.parentNode||o.log("Render.create: options.element was undefined, render.canvas was created but not appended","warn"),n},i.run=function(t){!function o(r){t.frameRequestId=e(o),n(t,r),i.world(t,r),(t.options.showStats||t.options.showDebug)&&i.stats(t,t.context,r),(t.options.showPerformance||t.options.showDebug)&&i.performance(t,t.context,r)}()},i.stop=function(e){t(e.frameRequestId)},i.setPixelRatio=function(e,t){var n=e.options,i=e.canvas;"auto"===t&&(t=p(i)),n.pixelRatio=t,i.setAttribute("data-pixel-ratio",t),i.width=n.width*t,i.height=n.height*t,i.style.width=n.width+"px",i.style.height=n.height+"px"},i.lookAt=function(e,t,n,i){i=void 0===i||i,t=o.isArray(t)?t:[t],n=n||{x:0,y:0};for(var r={min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}},a=0;ar.max.x&&(r.max.x=u.x),l.yr.max.y&&(r.max.y=u.y))}var d=r.max.x-r.min.x+2*n.x,p=r.max.y-r.min.y+2*n.y,f=e.canvas.height,v=e.canvas.width/f,y=d/p,m=1,g=1;y>v?g=y/v:m=v/y,e.options.hasBounds=!0,e.bounds.min.x=r.min.x,e.bounds.max.x=r.min.x+d*m,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*g,i&&(e.bounds.min.x+=.5*d-d*m*.5,e.bounds.max.x+=.5*d-d*m*.5,e.bounds.min.y+=.5*p-p*g*.5,e.bounds.max.y+=.5*p-p*g*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(c.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}),c.setOffset(e.mouse,e.bounds.min))},i.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,i=t/e.options.width,o=n/e.options.height;e.context.setTransform(e.options.pixelRatio/i,0,0,e.options.pixelRatio/o,0,0),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},i.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},i.world=function(e,t){var n,u=o.now(),d=e.engine,p=d.world,f=e.canvas,y=e.context,m=e.options,g=e.timing,x=r.allBodies(p),h=r.allConstraints(p),b=m.wireframes?m.wireframeBackground:m.background,S=[],w=[],A={timestamp:d.timing.timestamp};if(s.trigger(e,"beforeRender",A),e.currentBackground!==b&&v(e,b),y.globalCompositeOperation="source-in",y.fillStyle="transparent",y.fillRect(0,0,f.width,f.height),y.globalCompositeOperation="source-over",m.hasBounds){for(n=0;n1?1:0;a1?1:0;s1?1:0;r1?1:0;s1?1:0;r1?1:0;r1?1:0;o0)){var u=i.activeContacts[0].vertex.x,d=i.activeContacts[0].vertex.y;2===i.activeContacts.length&&(u=(i.activeContacts[0].vertex.x+i.activeContacts[1].vertex.x)/2,d=(i.activeContacts[0].vertex.y+i.activeContacts[1].vertex.y)/2),o.bodyB===o.supports[0].body||!0===o.bodyA.isStatic?s.moveTo(u-8*o.normal.x,d-8*o.normal.y):s.moveTo(u+8*o.normal.x,d+8*o.normal.y),s.lineTo(u,d)}l.wireframes?s.strokeStyle="rgba(255,165,0,0.7)":s.strokeStyle="orange",s.lineWidth=1,s.stroke()},i.separations=function(e,t,n){var i,o,r,a,s,l=n,c=e.options;for(l.beginPath(),s=0;s0&&l.trigger(e,"collisionStart",{pairs:m.collisionStart}),r.preSolvePosition(m.list),f=0;f0&&l.trigger(e,"collisionActive",{pairs:m.collisionActive}),m.collisionEnd.length>0&&l.trigger(e,"collisionEnd",{pairs:m.collisionEnd}),i._bodiesClearForces(b),l.trigger(e,"afterUpdate",h),e.timing.lastElapsed=d.now()-p,e},i.merge=function(e,t){if(d.extend(e,t),t.world){e.world=t.world,i.clear(e);for(var n=c.allBodies(e.world),r=0;rW||-H>W?(o=H>0?H:-H,(n=f.friction*(H>0?1:-1)*s)<-o?n=-o:n>o&&(n=o)):(n=H,o=d);var G=I*b-T*h,N=R*b-E*h,U=C/(M+y.inverseInertia*G*G+m.inverseInertia*N*N),z=(1+f.restitution)*F*U;if(n*=U,F*F>l&&F<0)k.normalImpulse=0;else{var X=k.normalImpulse;k.normalImpulse+=z,k.normalImpulse=Math.min(k.normalImpulse,0),z=k.normalImpulse-X}if(H*H>u)k.tangentImpulse=0;else{var Q=k.tangentImpulse;k.tangentImpulse+=n,k.tangentImpulse<-o&&(k.tangentImpulse=-o),k.tangentImpulse>o&&(k.tangentImpulse=o),n=k.tangentImpulse-Q}var Y=h*z+S*n,Z=b*z+w*n;y.isStatic||y.isSleeping||(y.positionPrev.x+=Y*y.inverseMass,y.positionPrev.y+=Z*y.inverseMass,y.anglePrev+=(I*Z-T*Y)*y.inverseInertia),m.isStatic||m.isSleeping||(m.positionPrev.x-=Y*m.inverseMass,m.positionPrev.y-=Z*m.inverseMass,m.anglePrev-=(R*Z-E*Y)*m.inverseInertia)}}}}},function(e,t,n){var i={};e.exports=i;var o=n(9),r=n(0);i.create=function(e){return r.extend({table:{},list:[],collisionStart:[],collisionActive:[],collisionEnd:[]},e)},i.update=function(e,t,n){var i,r,a,s,l=e.list,c=l.length,u=e.table,d=t.length,p=e.collisionStart,f=e.collisionEnd,v=e.collisionActive;for(p.length=0,f.length=0,v.length=0,s=0;sy&&(y=x),s.translate(g,{x:.5*h,y:.5*x}),d=g.bounds.max.x+r,o.addBody(u,g),c=g,f+=1}else d+=r}p+=y+a,d=e}return u},i.chain=function(e,t,n,i,s,l){for(var c=e.bodies,u=1;u0)for(c=0;c0&&(p=f[c-1+(l-1)*t],o.addConstraint(e,r.create(a.extend({bodyA:p,bodyB:d},s)))),i&&cp||a<(c=p-c)||a>n-1-c))return 1===d&&s.translate(u,{x:(a+(n%2==1?1:-1))*f,y:0}),l(e+(u?a*f:0)+a*r,i,a,c,u,d)}))},i.newtonsCradle=function(e,t,n,i,a){for(var s=o.create({label:"Newtons Cradle"}),c=0;cu.bounds.max.x||f.bounds.max.yu.bounds.max.y))){var v=i._getRegion(e,f);if(!f.region||v.id!==f.region.id||o){f.region&&!o||(f.region=v);var y=i._regionUnion(v,f.region);for(a=y.startCol;a<=y.endCol;a++)for(s=y.startRow;s<=y.endRow;s++){l=d[c=i._getBucketId(a,s)];var m=a>=v.startCol&&a<=v.endCol&&s>=v.startRow&&s<=v.endRow,g=a>=f.region.startCol&&a<=f.region.endCol&&s>=f.region.startRow&&s<=f.region.endRow;!m&&g&&g&&l&&i._bucketRemoveBody(e,l,f),(f.region===v||m&&!g||o)&&(l||(l=i._createBucket(d,c)),i._bucketAddBody(e,l,f))}f.region=v,p=!0}}}p&&(e.pairsList=i._createActivePairsList(e))},a(i,"update","Grid.update ➤ replaced by Matter.Detector"),i.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},a(i,"clear","Grid.clear ➤ replaced by Matter.Detector"),i._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),o=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),a=Math.max(e.endRow,t.endRow);return i._createRegion(n,o,r,a)},i._getRegion=function(e,t){var n=t.bounds,o=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),a=Math.floor(n.min.y/e.bucketHeight),s=Math.floor(n.max.y/e.bucketHeight);return i._createRegion(o,r,a,s)},i._createRegion=function(e,t,n,i){return{id:e+","+t+","+n+","+i,startCol:e,endCol:t,startRow:n,endRow:i}},i._getBucketId=function(e,t){return"C"+e+"R"+t},i._createBucket=function(e,t){return e[t]=[]},i._bucketAddBody=function(e,t,n){var i,r=e.pairs,a=o.id,s=t.length;for(i=0;i0?s.push(t):delete i[o[n]];return s}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(7),a=n(13),s=n(4),l=n(14),c=n(10),u=n(5),d=n(0),p=n(1);i.create=function(e,t){var n=(e?e.mouse:null)||(t?t.mouse:null);n||(e&&e.render&&e.render.canvas?n=a.create(e.render.canvas):t&&t.element?n=a.create(t.element):(n=a.create(),d.warn("MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected")));var o={type:"mouseConstraint",mouse:n,element:null,body:null,constraint:c.create({label:"Mouse Constraint",pointA:n.position,pointB:{x:0,y:0},length:.01,stiffness:.1,angularStiffness:1,render:{strokeStyle:"#90EE90",lineWidth:3}}),collisionFilter:{category:1,mask:4294967295,group:0}},r=d.extend(o,t);return s.on(e,"beforeUpdate",(function(){var t=u.allBodies(e.world);i.update(r,t),i._triggerEvents(r)})),r},i.update=function(e,t){var n=e.mouse,i=e.constraint,a=e.body;if(0===n.button){if(i.bodyB)r.set(i.bodyB,!1),i.pointA=n.position;else for(var c=0;c1?1:0;ue.deltaMax?e.deltaMax:i)/e.delta,e.delta=i),0!==e.timeScalePrev&&(s*=a.timeScale/e.timeScalePrev),0===a.timeScale&&(s=0),e.timeScalePrev=a.timeScale,e.correction=s,e.frameCounter+=1,n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),o.trigger(e,"tick",l),o.trigger(e,"beforeUpdate",l),r.update(t,i,s),o.trigger(e,"afterUpdate",l),o.trigger(e,"afterTick",l)},i.stop=function(e){t(e.frameRequestId)},i.start=function(e,t){i.run(e,t)}}()},function(e,t,n){var i={};e.exports=i;var o=n(8),r=n(0).deprecated;i.collides=function(e,t){return o.collides(e,t)},r(i,"collides","SAT.collides ➤ replaced by Collision.collides")},function(e,t,n){var i={};e.exports=i;n(1);var o=n(0);i.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||o.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,a,s,l,c,u,d,p,f,v,y=[],m=0,g=0,x=0;t=t||15;var h=function(e,t,n){var i=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&i?(f=p.x,v=p.y):(f=0,v=0);var o={x:f+e,y:v+t};!i&&p||(p=o),y.push(o),g=f+e,x=v+t}},b=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":g=e.x,x=e.y;break;case"H":g=e.x;break;case"V":x=e.y}h(g,x,e.pathSegType)}};for(i._svgPathToAbsolute(e),a=e.getTotalLength(),c=[],n=0;n0;t--){var i=Math.floor(n.random()*(t+1)),o=e[t];e[t]=e[i],e[i]=o}return e},n.choose=function(e){return e[Math.floor(n.random()*e.length)]},n.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},n.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},n.isFunction=function(e){return"function"==typeof e},n.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},n.isString=function(e){return"[object String]"===toString.call(e)},n.clamp=function(e,t,n){return en?n:e},n.sign=function(e){return e<0?-1:1},n.now=function(){if("undefined"!=typeof window&&window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return Date.now?Date.now():new Date-n._nowStartTime},n.random=function(t,n){return n=void 0!==n?n:1,(t=void 0!==t?t:0)+e()*(n-t)};var e=function(){return n._seed=(9301*n._seed+49297)%233280,n._seed/233280};n.colorToNumber=function(e){return 3==(e=e.replace("#","")).length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},n.logLevel=1,n.log=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.info=function(){console&&n.logLevel>0&&n.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warn=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warnOnce=function(){var e=Array.prototype.slice.call(arguments).join(" ");n._warnedOnce[e]||(n.warn(e),n._warnedOnce[e]=!0)},n.deprecated=function(e,t,i){e[t]=n.chain((function(){n.warnOnce("🔅 deprecated 🔅",i)}),e[t])},n.nextId=function(){return n._nextId++},n.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;ne.max.x&&(e.max.x=o.x),o.xe.max.y&&(e.max.y=o.y),o.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},n.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},n.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},n.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},n.shift=function(e,t){var n=e.max.x-e.min.x,i=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+i}},function(e,t){var n={};e.exports=n,n.create=function(e,t){return{x:e||0,y:t||0}},n.clone=function(e){return{x:e.x,y:e.y}},n.magnitude=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},n.magnitudeSquared=function(e){return e.x*e.x+e.y*e.y},n.rotate=function(e,t,n){var i=Math.cos(t),o=Math.sin(t);n||(n={});var r=e.x*i-e.y*o;return n.y=e.x*o+e.y*i,n.x=r,n},n.rotateAbout=function(e,t,n,i){var o=Math.cos(t),r=Math.sin(t);i||(i={});var a=n.x+((e.x-n.x)*o-(e.y-n.y)*r);return i.y=n.y+((e.x-n.x)*r+(e.y-n.y)*o),i.x=a,i},n.normalise=function(e){var t=n.magnitude(e);return 0===t?{x:0,y:0}:{x:e.x/t,y:e.y/t}},n.dot=function(e,t){return e.x*t.x+e.y*t.y},n.cross=function(e,t){return e.x*t.y-e.y*t.x},n.cross3=function(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)},n.add=function(e,t,n){return n||(n={}),n.x=e.x+t.x,n.y=e.y+t.y,n},n.sub=function(e,t,n){return n||(n={}),n.x=e.x-t.x,n.y=e.y-t.y,n},n.mult=function(e,t){return{x:e.x*t,y:e.y*t}},n.div=function(e,t){return{x:e.x/t,y:e.y/t}},n.perp=function(e,t){return{x:(t=!0===t?-1:1)*-e.y,y:t*e.x}},n.neg=function(e){return{x:-e.x,y:-e.y}},n.angle=function(e,t){return Math.atan2(t.y-e.y,t.x-e.x)},n._temp=[n.create(),n.create(),n.create(),n.create(),n.create(),n.create()]},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.create=function(e,t){for(var n=[],i=0;i0)return!1;a=n}return!0},i.scale=function(e,t,n,r){if(1===t&&1===n)return e;var a,s;r=r||i.centre(e);for(var l=0;l=0?l-1:e.length-1],u=e[l],d=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},i.hull=function(e){var t,n,i=[],r=[];for((e=e.slice(0)).sort((function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y})),n=0;n=2&&o.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];i.length>=2&&o.cross3(i[i.length-2],i[i.length-1],t)<=0;)i.pop();i.push(t)}return i.pop(),r.pop(),i.concat(r)}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(2),a=n(7),s=n(0),l=n(1),c=n(11);!function(){i._timeCorrection=!0,i._inertiaScale=4,i._nextCollidingGroupId=1,i._nextNonCollidingGroupId=-1,i._nextCategory=1,i._baseDelta=1e3/60,i.create=function(t){var n={id:s.nextId(),type:"body",label:"Body",parts:[],plugin:{},angle:0,vertices:o.fromPath("L 0 0 L 40 0 L 40 40 L 0 40"),position:{x:0,y:0},force:{x:0,y:0},torque:0,positionImpulse:{x:0,y:0},constraintImpulse:{x:0,y:0,angle:0},totalContacts:0,speed:0,angularSpeed:0,velocity:{x:0,y:0},angularVelocity:0,isSensor:!1,isStatic:!1,isSleeping:!1,motion:0,sleepThreshold:60,density:.001,restitution:0,friction:.1,frictionStatic:.5,frictionAir:.01,collisionFilter:{category:1,mask:4294967295,group:0},slop:.05,timeScale:1,render:{visible:!0,opacity:1,strokeStyle:null,fillStyle:null,lineWidth:null,sprite:{xScale:1,yScale:1,xOffset:0,yOffset:0}},events:null,bounds:null,chamfer:null,circleRadius:0,positionPrev:null,anglePrev:0,parent:null,axes:null,area:0,mass:0,inertia:0,deltaTime:1e3/60,_original:null},i=s.extend(n,t);return e(i,t),i},i.nextGroup=function(e){return e?i._nextNonCollidingGroupId--:i._nextCollidingGroupId++},i.nextCategory=function(){return i._nextCategory=i._nextCategory<<1,i._nextCategory};var e=function(e,t){t=t||{},i.set(e,{bounds:e.bounds||l.create(e.vertices),positionPrev:e.positionPrev||r.clone(e.position),anglePrev:e.anglePrev||e.angle,vertices:e.vertices,parts:e.parts||[e],isStatic:e.isStatic,isSleeping:e.isSleeping,parent:e.parent||e}),o.rotate(e.vertices,e.angle,e.position),c.rotate(e.axes,e.angle),l.update(e.bounds,e.vertices,e.velocity),i.set(e,{axes:t.axes||e.axes,area:t.area||e.area,mass:t.mass||e.mass,inertia:t.inertia||e.inertia});var n=e.isStatic?"#14151f":s.choose(["#f19648","#f5d259","#f55a3c","#063e7b","#ececd1"]),a=e.isStatic?"#555":"#ccc",u=e.isStatic&&null===e.render.fillStyle?1:0;e.render.fillStyle=e.render.fillStyle||n,e.render.strokeStyle=e.render.strokeStyle||a,e.render.lineWidth=e.render.lineWidth||u,e.render.sprite.xOffset+=-(e.bounds.min.x-e.position.x)/(e.bounds.max.x-e.bounds.min.x),e.render.sprite.yOffset+=-(e.bounds.min.y-e.position.y)/(e.bounds.max.y-e.bounds.min.y)};i.set=function(e,t,n){var o;for(o in"string"==typeof t&&(o=t,(t={})[o]=n),t)if(Object.prototype.hasOwnProperty.call(t,o))switch(n=t[o],o){case"isStatic":i.setStatic(e,n);break;case"isSleeping":a.set(e,n);break;case"mass":i.setMass(e,n);break;case"density":i.setDensity(e,n);break;case"inertia":i.setInertia(e,n);break;case"vertices":i.setVertices(e,n);break;case"position":i.setPosition(e,n);break;case"angle":i.setAngle(e,n);break;case"velocity":i.setVelocity(e,n);break;case"angularVelocity":i.setAngularVelocity(e,n);break;case"speed":i.setSpeed(e,n);break;case"angularSpeed":i.setAngularSpeed(e,n);break;case"parts":i.setParts(e,n);break;case"centre":i.setCentre(e,n);break;default:e[o]=n}},i.setStatic=function(e,t){for(var n=0;n0&&r.rotateAbout(s.position,i,e.position,s.position)}},i.setVelocity=function(e,t){var n=e.deltaTime/i._baseDelta;e.positionPrev.x=e.position.x-t.x*n,e.positionPrev.y=e.position.y-t.y*n,e.velocity.x=(e.position.x-e.positionPrev.x)/n,e.velocity.y=(e.position.y-e.positionPrev.y)/n,e.speed=r.magnitude(e.velocity)},i.getVelocity=function(e){var t=i._baseDelta/e.deltaTime;return{x:(e.position.x-e.positionPrev.x)*t,y:(e.position.y-e.positionPrev.y)*t}},i.getSpeed=function(e){return r.magnitude(i.getVelocity(e))},i.setSpeed=function(e,t){i.setVelocity(e,r.mult(r.normalise(i.getVelocity(e)),t))},i.setAngularVelocity=function(e,t){var n=e.deltaTime/i._baseDelta;e.anglePrev=e.angle-t*n,e.angularVelocity=(e.angle-e.anglePrev)/n,e.angularSpeed=Math.abs(e.angularVelocity)},i.getAngularVelocity=function(e){return(e.angle-e.anglePrev)*i._baseDelta/e.deltaTime},i.getAngularSpeed=function(e){return Math.abs(i.getAngularVelocity(e))},i.setAngularSpeed=function(e,t){i.setAngularVelocity(e,s.sign(i.getAngularVelocity(e))*t)},i.translate=function(e,t,n){i.setPosition(e,r.add(e.position,t),n)},i.rotate=function(e,t,n,o){if(n){var r=Math.cos(t),a=Math.sin(t),s=e.position.x-n.x,l=e.position.y-n.y;i.setPosition(e,{x:n.x+(s*r-l*a),y:n.y+(s*a+l*r)},o),i.setAngle(e,e.angle+t,o)}else i.setAngle(e,e.angle+t,o)},i.scale=function(e,t,n,r){var a=0,s=0;r=r||e.position;for(var u=0;u0&&(a+=d.area,s+=d.inertia),d.position.x=r.x+(d.position.x-r.x)*t,d.position.y=r.y+(d.position.y-r.y)*n,l.update(d.bounds,d.vertices,e.velocity)}e.parts.length>1&&(e.area=a,e.isStatic||(i.setMass(e,e.density*a),i.setInertia(e,s))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},i.update=function(e,t){var n=(t=(void 0!==t?t:1e3/60)*e.timeScale)*t,a=i._timeCorrection?t/(e.deltaTime||t):1,u=1-e.frictionAir*(t/s._baseDelta),d=(e.position.x-e.positionPrev.x)*a,p=(e.position.y-e.positionPrev.y)*a;e.velocity.x=d*u+e.force.x/e.mass*n,e.velocity.y=p*u+e.force.y/e.mass*n,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.deltaTime=t,e.angularVelocity=(e.angle-e.anglePrev)*u*a+e.torque/e.inertia*n,e.anglePrev=e.angle,e.angle+=e.angularVelocity;for(var f=0;f0&&(v.position.x+=e.velocity.x,v.position.y+=e.velocity.y),0!==e.angularVelocity&&(o.rotate(v.vertices,e.angularVelocity,e.position),c.rotate(v.axes,e.angularVelocity),f>0&&r.rotateAbout(v.position,e.angularVelocity,e.position,v.position)),l.update(v.bounds,v.vertices,e.velocity)}},i.updateVelocities=function(e){var t=i._baseDelta/e.deltaTime,n=e.velocity;n.x=(e.position.x-e.positionPrev.x)*t,n.y=(e.position.y-e.positionPrev.y)*t,e.speed=Math.sqrt(n.x*n.x+n.y*n.y),e.angularVelocity=(e.angle-e.anglePrev)*t,e.angularSpeed=Math.abs(e.angularVelocity)},i.applyForce=function(e,t,n){var i=t.x-e.position.x,o=t.y-e.position.y;e.force.x+=n.x,e.force.y+=n.y,e.torque+=i*n.y-o*n.x},i._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n0){n||(n={}),i=t.split(" ");for(var c=0;c0&&l.motion=l.sleepThreshold/n&&i.set(l,!0)):l.sleepCounter>0&&(l.sleepCounter-=1)}else i.set(l,!1)}},i.afterCollisions=function(e){for(var t=i._motionSleepThreshold,n=0;nt&&i.set(l,!1)}}}},i.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||r.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&r.trigger(e,"sleepEnd"))}},function(e,t,n){var i={};e.exports=i;var o,r,a,s=n(3),l=n(9);o=[],r={overlap:0,axis:null},a={overlap:0,axis:null},i.create=function(e,t){return{pair:null,collided:!1,bodyA:e,bodyB:t,parentA:e.parent,parentB:t.parent,depth:0,normal:{x:0,y:0},tangent:{x:0,y:0},penetration:{x:0,y:0},supports:[]}},i.collides=function(e,t,n){if(i._overlapAxes(r,e.vertices,t.vertices,e.axes),r.overlap<=0)return null;if(i._overlapAxes(a,t.vertices,e.vertices,t.axes),a.overlap<=0)return null;var o,c,u=n&&n.table[l.id(e,t)];u?o=u.collision:((o=i.create(e,t)).collided=!0,o.bodyA=e.idP?P=s:sC?C=s:so?o=a:al.frictionStatic?s.frictionStatic:l.frictionStatic,e.restitution=s.restitution>l.restitution?s.restitution:l.restitution,e.slop=s.slop>l.slop?s.slop:l.slop,t.pair=e,a.length=0;for(var u=0;u0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var a={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(a.type="pin",a.anchors=!1):t.stiffness<.9&&(a.type="spring"),t.render=c.extend(a,t.render),t},i.preSolveAll=function(e){for(var t=0;t=1||0===e.length?e.stiffness*t:e.stiffness*t*t,h=e.damping*t,b=r.mult(u,g*x),S=(n?n.inverseMass:0)+(o?o.inverseMass:0),w=S+((n?n.inverseInertia:0)+(o?o.inverseInertia:0));if(h>0){var A=r.create();v=r.div(u,d),m=r.sub(o&&r.sub(o.position,o.positionPrev)||A,n&&r.sub(n.position,n.positionPrev)||A),y=r.dot(v,m)}n&&!n.isStatic&&(f=n.inverseMass/S,n.constraintImpulse.x-=b.x*f,n.constraintImpulse.y-=b.y*f,n.position.x-=b.x*f,n.position.y-=b.y*f,h>0&&(n.positionPrev.x-=h*v.x*y*f,n.positionPrev.y-=h*v.y*y*f),p=r.cross(a,b)/w*i._torqueDampen*n.inverseInertia*(1-e.angularStiffness),n.constraintImpulse.angle-=p,n.angle-=p),o&&!o.isStatic&&(f=o.inverseMass/S,o.constraintImpulse.x+=b.x*f,o.constraintImpulse.y+=b.y*f,o.position.x+=b.x*f,o.position.y+=b.y*f,h>0&&(o.positionPrev.x+=h*v.x*y*f,o.positionPrev.y+=h*v.y*y*f),p=r.cross(s,b)/w*i._torqueDampen*o.inverseInertia*(1-e.angularStiffness),o.constraintImpulse.angle+=p,o.angle+=p)}}},i.postSolveAll=function(e){for(var t=0;t0&&(d.position.x+=c.x,d.position.y+=c.y),0!==c.angle&&(o.rotate(d.vertices,c.angle,n.position),l.rotate(d.axes,c.angle),u>0&&r.rotateAbout(d.position,c.angle,n.position,d.position)),s.update(d.bounds,d.vertices,n.velocity)}c.angle*=i._warming,c.x*=i._warming,c.y*=i._warming}}},i.pointAWorld=function(e){return{x:(e.bodyA?e.bodyA.position.x:0)+(e.pointA?e.pointA.x:0),y:(e.bodyA?e.bodyA.position.y:0)+(e.pointA?e.pointA.y:0)}},i.pointBWorld=function(e){return{x:(e.bodyB?e.bodyB.position.x:0)+(e.pointB?e.pointB.x:0),y:(e.bodyB?e.bodyB.position.y:0)+(e.pointB?e.pointB.y:0)}}},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.fromVertices=function(e){for(var t={},n=0;n0&&o.area(M)1?(v=a.create(r.extend({parts:y.slice(0)},i)),a.setPosition(v,{x:e,y:t}),v):y[0]}},function(e,t,n){var i={};e.exports=i;var o=n(0),r=n(8);i.create=function(e){return o.extend({bodies:[],pairs:null},e)},i.setBodies=function(e,t){e.bodies=t.slice(0)},i.clear=function(e){e.bodies=[]},i.collisions=function(e){var t,n,o=[],a=e.pairs,s=e.bodies,l=s.length,c=i.canCollide,u=r.collides;for(s.sort(i._compareBoundsX),t=0;tf)break;if(!(vB.max.y)&&(!m||!h.isStatic&&!h.isSleeping)&&c(d.collisionFilter,h.collisionFilter)){var b=h.parts.length;if(x&&1===b)(C=u(d,h,a))&&o.push(C);else for(var S=b>1?1:0,w=g>1?1:0;wB.max.x||p.max.xB.max.y||(C=u(A,M,a))&&o.push(C)}}}}return o},i.canCollide=function(e,t){return e.group===t.group&&0!==e.group?e.group>0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)},i._compareBoundsX=function(e,t){return e.bounds.min.x-t.bounds.min.x}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.create=function(e){var t={};return e||o.log("Mouse.create: element was undefined, defaulting to document.body","warn"),t.element=e||document.body,t.absolute={x:0,y:0},t.position={x:0,y:0},t.mousedownPosition={x:0,y:0},t.mouseupPosition={x:0,y:0},t.offset={x:0,y:0},t.scale={x:1,y:1},t.wheelDelta=0,t.button=-1,t.pixelRatio=parseInt(t.element.getAttribute("data-pixel-ratio"),10)||1,t.sourceEvents={mousemove:null,mousedown:null,mouseup:null,mousewheel:null},t.mousemove=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&(t.button=0,e.preventDefault()),t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.sourceEvents.mousemove=e},t.mousedown=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches?(t.button=0,e.preventDefault()):t.button=e.button,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mousedownPosition.x=t.position.x,t.mousedownPosition.y=t.position.y,t.sourceEvents.mousedown=e},t.mouseup=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&e.preventDefault(),t.button=-1,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mouseupPosition.x=t.position.x,t.mouseupPosition.y=t.position.y,t.sourceEvents.mouseup=e},t.mousewheel=function(e){t.wheelDelta=Math.max(-1,Math.min(1,e.wheelDelta||-e.detail)),e.preventDefault()},i.setElement(t,t.element),t},i.setElement=function(e,t){e.element=t,t.addEventListener("mousemove",e.mousemove),t.addEventListener("mousedown",e.mousedown),t.addEventListener("mouseup",e.mouseup),t.addEventListener("mousewheel",e.mousewheel),t.addEventListener("DOMMouseScroll",e.mousewheel),t.addEventListener("touchmove",e.mousemove),t.addEventListener("touchstart",e.mousedown),t.addEventListener("touchend",e.mouseup)},i.clearSourceEvents=function(e){e.sourceEvents.mousemove=null,e.sourceEvents.mousedown=null,e.sourceEvents.mouseup=null,e.sourceEvents.mousewheel=null,e.wheelDelta=0},i.setOffset=function(e,t){e.offset.x=t.x,e.offset.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i.setScale=function(e,t){e.scale.x=t.x,e.scale.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i._getRelativeMousePosition=function(e,t,n){var i,o,r=t.getBoundingClientRect(),a=document.documentElement||document.body.parentNode||document.body,s=void 0!==window.pageXOffset?window.pageXOffset:a.scrollLeft,l=void 0!==window.pageYOffset?window.pageYOffset:a.scrollTop,c=e.changedTouches;return c?(i=c[0].pageX-r.left-s,o=c[0].pageY-r.top-l):(i=e.pageX-r.left-s,o=e.pageY-r.top-l),{x:i/(t.clientWidth/(t.width||t.clientWidth)*n),y:o/(t.clientHeight/(t.height||t.clientHeight)*n)}}},function(e,t,n){var i={};e.exports=i;var o=n(0);i._registry={},i.register=function(e){if(i.isPlugin(e)||o.warn("Plugin.register:",i.toString(e),"does not implement all required fields."),e.name in i._registry){var t=i._registry[e.name],n=i.versionParse(e.version).number,r=i.versionParse(t.version).number;n>r?(o.warn("Plugin.register:",i.toString(t),"was upgraded to",i.toString(e)),i._registry[e.name]=e):n-1},i.isFor=function(e,t){var n=e.for&&i.dependencyParse(e.for);return!e.for||t.name===n.name&&i.versionSatisfies(t.version,n.range)},i.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0!==e.uses.length){for(var n=i.dependencies(e),r=o.topologicalSort(n),a=[],s=0;s0&&o.info(a.join(" "))}else o.warn("Plugin.use:",i.toString(e),"does not specify any dependencies to install.")},i.dependencies=function(e,t){var n=i.dependencyParse(e),r=n.name;if(!(r in(t=t||{}))){e=i.resolve(e)||e,t[r]=o.map(e.uses||[],(function(t){i.isPlugin(t)&&i.register(t);var r=i.dependencyParse(t),a=i.resolve(t);return a&&!i.versionSatisfies(a.version,r.range)?(o.warn("Plugin.dependencies:",i.toString(a),"does not satisfy",i.toString(r),"used by",i.toString(n)+"."),a._warned=!0,e._warned=!0):a||(o.warn("Plugin.dependencies:",i.toString(t),"used by",i.toString(n),"could not be resolved."),e._warned=!0),r.name}));for(var a=0;a=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-+]+)?$/;t.test(e)||o.warn("Plugin.versionParse:",e,"is not a valid version or range.");var n=t.exec(e),i=Number(n[4]),r=Number(n[5]),a=Number(n[6]);return{isRange:Boolean(n[1]||n[2]),version:n[3],range:e,operator:n[1]||n[2]||"",major:i,minor:r,patch:a,parts:[i,r,a],prerelease:n[7],number:1e8*i+1e4*r+a}},i.versionSatisfies=function(e,t){t=t||"*";var n=i.versionParse(t),o=i.versionParse(e);if(n.isRange){if("*"===n.operator||"*"===e)return!0;if(">"===n.operator)return o.number>n.number;if(">="===n.operator)return o.number>=n.number;if("~"===n.operator)return o.major===n.major&&o.minor===n.minor&&o.patch>=n.patch;if("^"===n.operator)return n.major>0?o.major===n.major&&o.number>=n.number:n.minor>0?o.minor===n.minor&&o.patch>=n.patch:o.patch===n.patch}return e===t||"*"===e}},function(e,t){var n={};e.exports=n,n.create=function(e){return{vertex:e,normalImpulse:0,tangentImpulse:0}}},function(e,t,n){var i={};e.exports=i;var o=n(7),r=n(18),a=n(13),s=n(19),l=n(5),c=n(6),u=n(10),d=n(0),p=n(4);i.create=function(e){e=e||{};var t=d.extend({positionIterations:6,velocityIterations:4,constraintIterations:2,enableSleeping:!1,events:[],plugin:{},gravity:{x:0,y:1,scale:.001},timing:{timestamp:0,timeScale:1,lastDelta:0,lastElapsed:0}},e);return t.world=e.world||c.create({label:"World"}),t.pairs=e.pairs||s.create(),t.detector=e.detector||a.create(),t.grid={buckets:[]},t.world.gravity=t.gravity,t.broadphase=t.grid,t.metrics={},t},i.update=function(e,t){var n,p=d.now(),f=e.world,v=e.detector,y=e.pairs,m=e.timing,g=m.timestamp;t=void 0!==t?t:d._baseDelta,t*=m.timeScale,m.timestamp+=t,m.lastDelta=t;var x={timestamp:m.timestamp,delta:t};l.trigger(e,"beforeUpdate",x);var h=c.allBodies(f),b=c.allConstraints(f);for(f.isModified&&(a.setBodies(v,h),c.setModified(f,!1,!1,!0)),e.enableSleeping&&o.update(h,t),i._bodiesApplyGravity(h,e.gravity),t>0&&i._bodiesUpdate(h,t),u.preSolveAll(h),n=0;n0&&l.trigger(e,"collisionStart",{pairs:y.collisionStart});var w=d.clamp(20/e.positionIterations,0,1);for(r.preSolvePosition(y.list),n=0;n0&&l.trigger(e,"collisionActive",{pairs:y.collisionActive}),y.collisionEnd.length>0&&l.trigger(e,"collisionEnd",{pairs:y.collisionEnd}),i._bodiesClearForces(h),l.trigger(e,"afterUpdate",x),e.timing.lastElapsed=d.now()-p,e},i.merge=function(e,t){if(d.extend(e,t),t.world){e.world=t.world,i.clear(e);for(var n=c.allBodies(e.world),r=0;rU?(o=q>0?q:-q,(n=y.friction*(q>0?1:-1)*c)<-o?n=-o:n>o&&(n=o)):(n=q,o=f);var N=R*w-V*S,z=E*w-L*S,X=B/(_+g.inverseInertia*N*N+x.inverseInertia*z*z),Q=(1+y.restitution)*j*X;if(n*=X,j0&&(I.normalImpulse=0),Q=I.normalImpulse-Y}if(q<-d||q>d)I.tangentImpulse=0;else{var Z=I.tangentImpulse;I.tangentImpulse+=n,I.tangentImpulse<-o&&(I.tangentImpulse=-o),I.tangentImpulse>o&&(I.tangentImpulse=o),n=I.tangentImpulse-Z}var $=S*Q+A*n,J=w*Q+P*n;g.isStatic||g.isSleeping||(g.positionPrev.x+=$*g.inverseMass,g.positionPrev.y+=J*g.inverseMass,g.anglePrev+=(R*J-V*$)*g.inverseInertia),x.isStatic||x.isSleeping||(x.positionPrev.x-=$*x.inverseMass,x.positionPrev.y-=J*x.inverseMass,x.anglePrev-=(E*J-L*$)*x.inverseInertia)}}}}},function(e,t,n){var i={};e.exports=i;var o=n(9),r=n(0);i.create=function(e){return r.extend({table:{},list:[],collisionStart:[],collisionActive:[],collisionEnd:[]},e)},i.update=function(e,t,n){var i,r,a,s,l=e.list,c=l.length,u=e.table,d=t.length,p=e.collisionStart,f=e.collisionEnd,v=e.collisionActive;for(p.length=0,f.length=0,v.length=0,s=0;sy&&(y=x),s.translate(g,{x:.5*h,y:.5*x}),d=g.bounds.max.x+r,o.addBody(u,g),c=g,f+=1}else d+=r}p+=y+a,d=e}return u},i.chain=function(e,t,n,i,s,l){for(var c=e.bodies,u=1;u0)for(c=0;c0&&(p=f[c-1+(l-1)*t],o.addConstraint(e,r.create(a.extend({bodyA:p,bodyB:d},s)))),i&&cp||a<(c=p-c)||a>n-1-c))return 1===d&&s.translate(u,{x:(a+(n%2==1?1:-1))*f,y:0}),l(e+(u?a*f:0)+a*r,i,a,c,u,d)}))},i.newtonsCradle=function(e,t,n,i,a){for(var s=o.create({label:"Newtons Cradle"}),c=0;cu.bounds.max.x||f.bounds.max.yu.bounds.max.y))){var v=i._getRegion(e,f);if(!f.region||v.id!==f.region.id||o){f.region&&!o||(f.region=v);var y=i._regionUnion(v,f.region);for(a=y.startCol;a<=y.endCol;a++)for(s=y.startRow;s<=y.endRow;s++){l=d[c=i._getBucketId(a,s)];var m=a>=v.startCol&&a<=v.endCol&&s>=v.startRow&&s<=v.endRow,g=a>=f.region.startCol&&a<=f.region.endCol&&s>=f.region.startRow&&s<=f.region.endRow;!m&&g&&g&&l&&i._bucketRemoveBody(e,l,f),(f.region===v||m&&!g||o)&&(l||(l=i._createBucket(d,c)),i._bucketAddBody(e,l,f))}f.region=v,p=!0}}}p&&(e.pairsList=i._createActivePairsList(e))},a(i,"update","Grid.update ➤ replaced by Matter.Detector"),i.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},a(i,"clear","Grid.clear ➤ replaced by Matter.Detector"),i._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),o=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),a=Math.max(e.endRow,t.endRow);return i._createRegion(n,o,r,a)},i._getRegion=function(e,t){var n=t.bounds,o=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),a=Math.floor(n.min.y/e.bucketHeight),s=Math.floor(n.max.y/e.bucketHeight);return i._createRegion(o,r,a,s)},i._createRegion=function(e,t,n,i){return{id:e+","+t+","+n+","+i,startCol:e,endCol:t,startRow:n,endRow:i}},i._getBucketId=function(e,t){return"C"+e+"R"+t},i._createBucket=function(e,t){return e[t]=[]},i._bucketAddBody=function(e,t,n){var i,r=e.pairs,a=o.id,s=t.length;for(i=0;i0?s.push(t):delete i[o[n]];return s}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(7),a=n(14),s=n(5),l=n(13),c=n(10),u=n(6),d=n(0),p=n(1);i.create=function(e,t){var n=(e?e.mouse:null)||(t?t.mouse:null);n||(e&&e.render&&e.render.canvas?n=a.create(e.render.canvas):t&&t.element?n=a.create(t.element):(n=a.create(),d.warn("MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected")));var o={type:"mouseConstraint",mouse:n,element:null,body:null,constraint:c.create({label:"Mouse Constraint",pointA:n.position,pointB:{x:0,y:0},length:.01,stiffness:.1,angularStiffness:1,render:{strokeStyle:"#90EE90",lineWidth:3}}),collisionFilter:{category:1,mask:4294967295,group:0}},r=d.extend(o,t);return s.on(e,"beforeUpdate",(function(){var t=u.allBodies(e.world);i.update(r,t),i._triggerEvents(r)})),r},i.update=function(e,t){var n=e.mouse,i=e.constraint,a=e.body;if(0===n.button){if(i.bodyB)r.set(i.bodyB,!1),i.pointA=n.position;else for(var c=0;c1?1:0;uo.max.x&&(o.max.x=c.x),l.yo.max.y&&(o.max.y=c.y))}var d=o.max.x-o.min.x+2*n.x,p=o.max.y-o.min.y+2*n.y,f=e.canvas.height,v=e.canvas.width/f,y=d/p,m=1,g=1;y>v?g=y/v:m=v/y,e.options.hasBounds=!0,e.bounds.min.x=o.min.x,e.bounds.max.x=o.min.x+d*m,e.bounds.min.y=o.min.y,e.bounds.max.y=o.min.y+p*g,i&&(e.bounds.min.x+=.5*d-d*m*.5,e.bounds.max.x+=.5*d-d*m*.5,e.bounds.min.y+=.5*p-p*g*.5,e.bounds.max.y+=.5*p-p*g*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(u.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}),u.setOffset(e.mouse,e.bounds.min))},i.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,i=t/e.options.width,o=n/e.options.height;e.context.setTransform(e.options.pixelRatio/i,0,0,e.options.pixelRatio/o,0,0),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},i.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},i.world=function(e,t){var n,o=r.now(),d=e.engine,p=d.world,f=e.canvas,v=e.context,m=e.options,g=e.timing,x=a.allBodies(p),h=a.allConstraints(p),b=m.wireframes?m.wireframeBackground:m.background,S=[],w=[],A={timestamp:d.timing.timestamp};if(l.trigger(e,"beforeRender",A),e.currentBackground!==b&&y(e,b),v.globalCompositeOperation="source-in",v.fillStyle="transparent",v.fillRect(0,0,f.width,f.height),v.globalCompositeOperation="source-over",m.hasBounds){for(n=0;n1?1:0;a1?1:0;s1?1:0;r1?1:0;s1?1:0;r1?1:0;r1?1:0;o0)){var u=i.activeContacts[0].vertex.x,d=i.activeContacts[0].vertex.y;2===i.activeContacts.length&&(u=(i.activeContacts[0].vertex.x+i.activeContacts[1].vertex.x)/2,d=(i.activeContacts[0].vertex.y+i.activeContacts[1].vertex.y)/2),o.bodyB===o.supports[0].body||!0===o.bodyA.isStatic?s.moveTo(u-8*o.normal.x,d-8*o.normal.y):s.moveTo(u+8*o.normal.x,d+8*o.normal.y),s.lineTo(u,d)}l.wireframes?s.strokeStyle="rgba(255,165,0,0.7)":s.strokeStyle="orange",s.lineWidth=1,s.stroke()},i.separations=function(e,t,n){var i,o,r,a,s,l=n,c=e.options;for(l.beginPath(),s=0;se.deltaMax?e.deltaMax:i,e.delta=i);var s={timestamp:a.timestamp};o.trigger(e,"beforeTick",s),e.frameCounter+=1,n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),o.trigger(e,"tick",s),o.trigger(e,"beforeUpdate",s),r.update(t,i),o.trigger(e,"afterUpdate",s),o.trigger(e,"afterTick",s)},i.stop=function(e){t(e.frameRequestId)},i.start=function(e,t){i.run(e,t)}}()},function(e,t,n){var i={};e.exports=i;var o=n(8),r=n(0).deprecated;i.collides=function(e,t){return o.collides(e,t)},r(i,"collides","SAT.collides ➤ replaced by Collision.collides")},function(e,t,n){var i={};e.exports=i;n(1);var o=n(0);i.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||o.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,a,s,l,c,u,d,p,f,v,y=[],m=0,g=0,x=0;t=t||15;var h=function(e,t,n){var i=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&i?(f=p.x,v=p.y):(f=0,v=0);var o={x:f+e,y:v+t};!i&&p||(p=o),y.push(o),g=f+e,x=v+t}},b=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":g=e.x,x=e.y;break;case"H":g=e.x;break;case"V":x=e.y}h(g,x,e.pathSegType)}};for(i._svgPathToAbsolute(e),a=e.getTotalLength(),c=[],n=0;n
-
+