diff --git a/build/matter.js b/build/matter.js
index 442ff88..63be5ac 100644
--- a/build/matter.js
+++ b/build/matter.js
@@ -1,5 +1,5 @@
/**
-* matter.js 0.8.0-edge 2014-05-04
+* matter.js 0.8.0-edge 2014-06-09
* http://brm.io/matter-js/
* License: MIT
*/
@@ -41,9 +41,13 @@ var Matter = {};
// Begin src/body/Body.js
/**
+* 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 [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
-*
+
* @class Body
*/
@@ -51,10 +55,14 @@ var Body = {};
(function() {
+ Body._inertiaScale = 4;
+
var _nextGroupId = 1;
/**
- * Description to be written.
+ * 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.
+ * See the properites section below for detailed information on what you can pass via the `options` object.
* @method create
* @param {} options
* @return {body} body
@@ -98,13 +106,13 @@ var Body = {};
var body = Common.extend(defaults, options);
- _initProperties(body);
+ _initProperties(body, options);
return body;
};
/**
- * Description
+ * Returns the next unique groupID number.
* @method nextGroupId
* @return {Number} Unique groupID
*/
@@ -113,41 +121,44 @@ var Body = {};
};
/**
- * Initialises body properties
+ * Initialises body properties.
* @method _initProperties
* @private
* @param {body} body
+ * @param {} options
*/
- var _initProperties = function(body) {
- // calculated properties
- body.axes = body.axes || Axes.fromVertices(body.vertices);
- body.area = Vertices.area(body.vertices);
- body.bounds = Bounds.create(body.vertices);
- body.mass = body.mass || (body.density * body.area);
- body.inverseMass = 1 / body.mass;
- body.inertia = body.inertia || Vertices.inertia(body.vertices, body.mass);
- body.inverseInertia = 1 / body.inertia;
- body.positionPrev = body.positionPrev || { x: body.position.x, y: body.position.y };
+ var _initProperties = function(body, options) {
+ // init required properties
+ body.bounds = body.bounds || Bounds.create(body.vertices);
+ body.positionPrev = body.positionPrev || Vector.clone(body.position);
body.anglePrev = body.anglePrev || body.angle;
- body.render.fillStyle = body.render.fillStyle || (body.isStatic ? '#eeeeee' : Common.choose(['#556270', '#4ECDC4', '#C7F464', '#FF6B6B', '#C44D58']));
- body.render.strokeStyle = body.render.strokeStyle || Common.shadeColor(body.render.fillStyle, -20);
-
- // update geometry
- Vertices.create(body.vertices, body);
- var centre = Vertices.centre(body.vertices);
- Vertices.translate(body.vertices, body.position);
- Vertices.translate(body.vertices, centre, -1);
- Vertices.rotate(body.vertices, body.angle, body.position);
- Axes.rotate(body.axes, body.angle);
- Bounds.update(body.bounds, body.vertices, body.velocity);
+ // must use setters for the more complicated properties
+ Body.setVertices(body, body.vertices);
Body.setStatic(body, body.isStatic);
Sleeping.set(body, body.isSleeping);
+ Vertices.rotate(body.vertices, body.angle, body.position);
+ Axes.rotate(body.axes, body.angle);
+
+ // allow options to override the automatically calculated properties
+ body.axes = options.axes || body.axes;
+ body.area = options.area || body.area;
+ body.mass = options.mass || body.mass;
+ body.inertia = options.inertia || body.inertia;
+ body.inverseMass = 1 / body.mass;
+ body.inverseInertia = 1 / body.inertia;
+
+ // render properties
+ var defaultFillStyle = (body.isStatic ? '#eeeeee' : Common.choose(['#556270', '#4ECDC4', '#C7F464', '#FF6B6B', '#C44D58'])),
+ defaultStrokeStyle = Common.shadeColor(defaultFillStyle, -20);
+ body.render.fillStyle = body.render.fillStyle || defaultFillStyle;
+ body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle;
};
/**
- * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity
+ * 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) {
@@ -171,7 +182,155 @@ var Body = {};
};
/**
- * Description
+ * 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.mass = body.density * body.area;
+ body.inverseMass = 1 / body.mass;
+
+ // 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.inertia = Body._inertiaScale * Vertices.inertia(body.vertices, body.mass);
+ body.inverseInertia = 1 / body.inertia;
+
+ // update geometry
+ Vertices.translate(body.vertices, body.position);
+ Bounds.update(body.bounds, body.vertices, body.velocity);
+ };
+
+ /**
+ * 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.position.x = position.x;
+ body.position.y = position.y;
+ body.positionPrev.x += delta.x;
+ body.positionPrev.y += delta.y;
+
+ Vertices.translate(body.vertices, delta);
+ Bounds.update(body.bounds, body.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.angle = angle;
+ body.anglePrev += delta;
+
+ Vertices.rotate(body.vertices, delta, body.position);
+ Axes.rotate(body.axes, delta);
+ Bounds.update(body.bounds, body.vertices, body.velocity);
+ };
+
+ /**
+ * 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
+ */
+ Body.rotate = function(body, rotation) {
+ Body.setAngle(body, body.angle + angle);
+ };
+
+ /**
+ * 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) {
+ // scale vertices
+ Vertices.scale(body.vertices, scaleX, scaleY, point);
+
+ // update properties
+ body.axes = Axes.fromVertices(body.vertices);
+ body.area = Vertices.area(body.vertices);
+ body.mass = body.density * body.area;
+ body.inverseMass = 1 / body.mass;
+
+ // update inertia (requires vertices to be at origin)
+ Vertices.translate(body.vertices, { x: -body.position.x, y: -body.position.y });
+ body.inertia = Vertices.inertia(body.vertices, body.mass);
+ body.inverseInertia = 1 / body.inertia;
+ Vertices.translate(body.vertices, { x: body.position.x, y: body.position.y });
+
+ // update bounds
+ Bounds.update(body.bounds, body.vertices, body.velocity);
+ };
+
+ /**
+ * Zeroes the `body.force` and `body.torque` force buffers.
* @method resetForcesAll
* @param {body[]} bodies
*/
@@ -187,7 +346,7 @@ var Body = {};
};
/**
- * Description
+ * Applys a mass dependant force to all given bodies.
* @method applyGravityAll
* @param {body[]} bodies
* @param {vector} gravity
@@ -206,12 +365,14 @@ var Body = {};
};
/**
- * Description
+ * Applys `Body.update` to all given `bodies`.
* @method updateAll
* @param {body[]} bodies
- * @param {number} deltaTime
+ * @param {number} deltaTime
+ * The amount of time elapsed between updates
* @param {number} timeScale
- * @param {number} correction
+ * @param {number} correction
+ * The Verlet correction factor (deltaTime / lastDeltaTime)
* @param {bounds} worldBounds
*/
Body.updateAll = function(bodies, deltaTime, timeScale, correction, worldBounds) {
@@ -232,7 +393,7 @@ var Body = {};
};
/**
- * Description
+ * Performs a simulation step for the given `body`, including updating position and angle using Verlet integration.
* @method update
* @param {body} body
* @param {number} deltaTime
@@ -275,7 +436,7 @@ var Body = {};
};
/**
- * Description
+ * Applies a force to a body from a given world-space position, including resulting torque.
* @method applyForce
* @param {body} body
* @param {vector} position
@@ -288,62 +449,366 @@ var Body = {};
body.torque += (offset.x * force.y - offset.y * force.x) * body.inverseInertia;
};
- /**
- * Description
- * @method translate
- * @param {body} body
- * @param {vector} translation
- */
- Body.translate = function(body, translation) {
- body.positionPrev.x += translation.x;
- body.positionPrev.y += translation.y;
- body.position.x += translation.x;
- body.position.y += translation.y;
- Vertices.translate(body.vertices, translation);
- Bounds.update(body.bounds, body.vertices, body.velocity);
- };
+ /*
+ *
+ * Properties Documentation
+ *
+ */
/**
- * Description
- * @method rotate
- * @param {body} body
- * @param {number} angle
+ * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`.
+ *
+ * @property id
+ * @type number
*/
- Body.rotate = function(body, angle) {
- body.anglePrev += angle;
- body.angle += angle;
- Vertices.rotate(body.vertices, angle, body.position);
- Axes.rotate(body.axes, angle);
- Bounds.update(body.bounds, body.vertices, body.velocity);
- };
/**
- * Scales the body, including updating physical properties (mass, area, axes, inertia), from a point (default is centre)
- * @method translate
- * @param {body} body
- * @param {number} scaleX
- * @param {number} scaleY
- * @param {vector} point
+ * A `String` denoting the type of object.
+ *
+ * @property type
+ * @type string
+ * @default "body"
*/
- Body.scale = function(body, scaleX, scaleY, point) {
- // scale vertices
- Vertices.scale(body.vertices, scaleX, scaleY, point);
- // update properties
- body.axes = Axes.fromVertices(body.vertices);
- body.area = Vertices.area(body.vertices);
- body.mass = body.density * body.area;
- body.inverseMass = 1 / body.mass;
+ /**
+ * An arbitrary `String` name to help the user identify and manage bodies.
+ *
+ * @property label
+ * @type string
+ * @default "Body"
+ */
- // update inertia (requires vertices to be at origin)
- Vertices.translate(body.vertices, { x: -body.position.x, y: -body.position.y });
- body.inertia = Vertices.inertia(body.vertices, body.mass);
- body.inverseInertia = 1 / body.inertia;
- Vertices.translate(body.vertices, { x: body.position.x, y: body.position.y });
+ /**
+ * A `Number` specifying the angle of the body, in radians.
+ *
+ * @property angle
+ * @type number
+ * @default 0
+ */
- // update bounds
- Bounds.update(body.bounds, body.vertices, body.velocity);
- };
+ /**
+ * 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 verticies 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 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 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 integer `Number` that specifies the collision group the body belongs to.
+ * Bodies with the same `groupId` are considered _as-one_ body and therefore do not interact.
+ * This allows for creation of segmented bodies that can self-intersect, such as a rope.
+ * The default value 0 means the body does not belong to a group, and can interact with all other bodies.
+ *
+ * @property groupId
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that specifies a tollerance 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
+ */
+
+ /**
+ * 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 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 1.5
+ */
+
+ /**
+ * 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
+ */
})();
@@ -353,6 +818,11 @@ var Body = {};
// Begin src/body/Composite.js
/**
+* The `Matter.Composite` module contains methods for creating and manipulating composite bodies.
+* A composite body is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite`, therefore composites form a tree structure.
+* It is important to use the functions in this module to modify composites, rather than directly modifying their properties.
+* Note that the `Matter.World` object is also a type of `Matter.Composite` and as such all composite methods here can also operate on a `Matter.World`.
+*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
@@ -366,9 +836,10 @@ var Composite = {};
(function() {
/**
- * Description
+ * Creates a new composite. The options parameter is an object that specifies any properties you wish to override the defaults.
+ * See the properites section below for detailed information on what you can pass via the `options` object.
* @method create
- * @param {} options
+ * @param {} [options]
* @return {composite} A new composite
*/
Composite.create = function(options) {
@@ -391,8 +862,8 @@ var Composite = {};
* @method setModified
* @param {composite} composite
* @param {boolean} isModified
- * @param {boolean} updateParents
- * @param {boolean} updateChildren
+ * @param {boolean} [updateParents=false]
+ * @param {boolean} [updateChildren=false]
*/
Composite.setModified = function(composite, isModified, updateParents, updateChildren) {
composite.isModified = isModified;
@@ -449,7 +920,7 @@ var Composite = {};
* @method remove
* @param {composite} composite
* @param {} object
- * @param {boolean} deep
+ * @param {boolean} [deep=false]
* @return {composite} The original composite with the objects removed
*/
Composite.remove = function(composite, object, deep) {
@@ -480,7 +951,7 @@ var Composite = {};
};
/**
- * Description
+ * Adds a composite to the given composite
* @method addComposite
* @param {composite} compositeA
* @param {composite} compositeB
@@ -498,7 +969,7 @@ var Composite = {};
* @method removeComposite
* @param {composite} compositeA
* @param {composite} compositeB
- * @param {boolean} deep
+ * @param {boolean} [deep=false]
* @return {composite} The original compositeA with the composite removed
*/
Composite.removeComposite = function(compositeA, compositeB, deep) {
@@ -531,7 +1002,7 @@ var Composite = {};
};
/**
- * Description
+ * Adds a body to the given composite
* @method addBody
* @param {composite} composite
* @param {body} body
@@ -548,7 +1019,7 @@ var Composite = {};
* @method removeBody
* @param {composite} composite
* @param {body} body
- * @param {boolean} deep
+ * @param {boolean} [deep=false]
* @return {composite} The original composite with the body removed
*/
Composite.removeBody = function(composite, body, deep) {
@@ -581,7 +1052,7 @@ var Composite = {};
};
/**
- * Description
+ * Adds a constraint to the given composite
* @method addConstraint
* @param {composite} composite
* @param {constraint} constraint
@@ -598,7 +1069,7 @@ var Composite = {};
* @method removeConstraint
* @param {composite} composite
* @param {constraint} constraint
- * @param {boolean} deep
+ * @param {boolean} [deep=false]
* @return {composite} The original composite with the constraint removed
*/
Composite.removeConstraint = function(composite, constraint, deep) {
@@ -635,7 +1106,7 @@ var Composite = {};
* @method clear
* @param {world} world
* @param {boolean} keepStatic
- * @param {boolean} deep
+ * @param {boolean} [deep=false]
*/
Composite.clear = function(composite, keepStatic, deep) {
if (deep) {
@@ -770,6 +1241,83 @@ var Composite = {};
return composite;
};
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`.
+ *
+ * @property id
+ * @type number
+ */
+
+ /**
+ * A `String` denoting the type of object.
+ *
+ * @property type
+ * @type string
+ * @default "composite"
+ */
+
+ /**
+ * An arbitrary `String` name to help the user identify and manage composites.
+ *
+ * @property label
+ * @type string
+ * @default "Composite"
+ */
+
+ /**
+ * A flag that specifies whether the composite has been modified during the current step.
+ * Most `Matter.Composite` methods will automatically set this flag to `true` to inform the engine of changes to be handled.
+ * If you need to change it manually, you should use the `Composite.setModified` method.
+ *
+ * @property isModified
+ * @type boolean
+ * @default false
+ */
+
+ /**
+ * The `Composite` that is the parent of this composite. It is automatically managed by the `Matter.Composite` methods.
+ *
+ * @property parent
+ * @type composite
+ * @default null
+ */
+
+ /**
+ * An array of `Body` that are _direct_ children of this composite.
+ * To add or remove bodies you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property.
+ * If you wish to recursively find all descendants, you should use the `Composite.allBodies` method.
+ *
+ * @property bodies
+ * @type body[]
+ * @default []
+ */
+
+ /**
+ * An array of `Constraint` that are _direct_ children of this composite.
+ * To add or remove constraints you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property.
+ * If you wish to recursively find all descendants, you should use the `Composite.allConstraints` method.
+ *
+ * @property constraints
+ * @type constraint[]
+ * @default []
+ */
+
+ /**
+ * An array of `Composite` that are _direct_ children of this composite.
+ * To add or remove composites you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property.
+ * If you wish to recursively find all descendants, you should use the `Composite.allComposites` method.
+ *
+ * @property composites
+ * @type composite[]
+ * @default []
+ */
+
})();
; // End src/body/Composite.js
@@ -778,6 +1326,12 @@ var Composite = {};
// Begin src/body/World.js
/**
+* The `Matter.World` module contains methods for creating and manipulating the world composite.
+* A `Matter.World` is a `Matter.Composite` body, which is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite`.
+* A `Matter.World` has a few additional properties including `gravity` and `bounds`.
+* It is important to use the functions in the `Matter.Composite` module to modify the world composite, rather than directly modifying its properties.
+* There are also a few methods here that alias those in `Matter.Composite` for easier readability.
+*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
@@ -789,7 +1343,8 @@ var World = {};
(function() {
/**
- * Description
+ * Creates a new world composite. The options parameter is an object that specifies any properties you wish to override the defaults.
+ * See the properites section below for detailed information on what you can pass via the `options` object.
* @method create
* @constructor
* @param {} options
@@ -814,14 +1369,14 @@ var World = {};
// see src/module/Outro.js for these aliases:
/**
- * An alias for Composite.clear since World is also a Composite (see Outro.js)
+ * An alias for Composite.clear since World is also a Composite
* @method clear
* @param {world} world
* @param {boolean} keepStatic
*/
/**
- * An alias for Composite.add since World is also a Composite (see Outro.js)
+ * An alias for Composite.add since World is also a Composite
* @method addComposite
* @param {world} world
* @param {composite} composite
@@ -829,7 +1384,7 @@ var World = {};
*/
/**
- * An alias for Composite.addBody since World is also a Composite (see Outro.js)
+ * An alias for Composite.addBody since World is also a Composite
* @method addBody
* @param {world} world
* @param {body} body
@@ -837,7 +1392,7 @@ var World = {};
*/
/**
- * An alias for Composite.addConstraint since World is also a Composite (see Outro.js)
+ * An alias for Composite.addConstraint since World is also a Composite
* @method addConstraint
* @param {world} world
* @param {constraint} constraint
@@ -1599,7 +2154,7 @@ var Pairs = {};
// Begin src/collision/Query.js
/**
-* Functions for performing collision queries
+* The `Matter.Query` module contains methods for performing collision queries.
*
* @class Query
*/
@@ -1614,6 +2169,7 @@ var Query = {};
* @param {body[]} bodies
* @param {vector} startPoint
* @param {vector} endPoint
+ * @param {number} [rayWidth]
* @return {object[]} Collisions
*/
Query.ray = function(bodies, startPoint, endPoint, rayWidth) {
@@ -1642,11 +2198,11 @@ var Query = {};
};
/**
- * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies
+ * 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
+ * @param {bool} [outside=false]
* @return {body[]} The bodies matching the query
*/
Query.region = function(bodies, bounds, outside) {
@@ -2203,6 +2759,10 @@ var SAT = {};
// Begin src/constraint/Constraint.js
/**
+* The `Matter.Constraint` module contains methods for creating and manipulating constraints.
+* Constraints are used for specifying that a fixed distance must be maintained between two bodies (or a body and a fixed world-space position).
+* The stiffness of constraints can be modified to create springs or elastic.
+*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
@@ -2225,7 +2785,9 @@ var Constraint = {};
_minDifference = 0.001;
/**
- * Description
+ * Creates a new constraint.
+ * All properties have default values, and many are pre-calculated automatically based on other properties.
+ * See the properites section below for detailed information on what you can pass via the `options` object.
* @method create
* @param {} options
* @return {constraint} constraint
@@ -2269,6 +2831,7 @@ var Constraint = {};
/**
* Description
+ * @private
* @method solveAll
* @param {constraint[]} constraints
* @param {number} timeScale
@@ -2281,6 +2844,7 @@ var Constraint = {};
/**
* Description
+ * @private
* @method solve
* @param {constraint} constraint
* @param {number} timeScale
@@ -2435,6 +2999,7 @@ var Constraint = {};
/**
* Performs body updates required after solving constraints
+ * @private
* @method postSolveAll
* @param {body[]} bodies
*/
@@ -2459,6 +3024,118 @@ var Constraint = {};
}
};
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`.
+ *
+ * @property id
+ * @type number
+ */
+
+ /**
+ * A `String` denoting the type of object.
+ *
+ * @property type
+ * @type string
+ * @default "constraint"
+ */
+
+ /**
+ * An arbitrary `String` name to help the user identify and manage bodies.
+ *
+ * @property label
+ * @type string
+ * @default "Constraint"
+ */
+
+ /**
+ * 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 constraint should be rendered.
+ *
+ * @property render.visible
+ * @type boolean
+ * @default true
+ */
+
+ /**
+ * A `Number` that defines the line width to use when rendering the constraint outline.
+ * A value of `0` means no outline will be rendered.
+ *
+ * @property render.lineWidth
+ * @type number
+ * @default 2
+ */
+
+ /**
+ * A `String` that defines the stroke style to use when rendering the constraint outline.
+ * 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
+ */
+
+ /**
+ * The first possible `Body` that this constraint is attached to.
+ *
+ * @property bodyA
+ * @type body
+ * @default null
+ */
+
+ /**
+ * The second possible `Body` that this constraint is attached to.
+ *
+ * @property bodyB
+ * @type body
+ * @default null
+ */
+
+ /**
+ * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position.
+ *
+ * @property pointA
+ * @type vector
+ * @default { x: 0, y: 0 }
+ */
+
+ /**
+ * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position.
+ *
+ * @property pointB
+ * @type vector
+ * @default { x: 0, y: 0 }
+ */
+
+ /**
+ * A `Number` that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`.
+ * A value of `1` means the constraint should be very stiff.
+ * A value of `0.2` means the constraint acts like a soft spring.
+ *
+ * @property stiffness
+ * @type number
+ * @default 1
+ */
+
+ /**
+ * A `Number` that specifies the target resting length of the constraint.
+ * It is calculated automatically in `Constraint.create` from intial positions of the `constraint.bodyA` and `constraint.bodyB`.
+ *
+ * @property length
+ * @type number
+ */
+
})();
; // End src/constraint/Constraint.js
@@ -2467,6 +3144,9 @@ var Constraint = {};
// Begin src/constraint/MouseConstraint.js
/**
+* 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 [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
@@ -2478,7 +3158,9 @@ var MouseConstraint = {};
(function() {
/**
- * Description
+ * Creates a new mouse constraint.
+ * All properties have default values, and many are pre-calculated automatically based on other properties.
+ * See the properites section below for detailed information on what you can pass via the `options` object.
* @method create
* @param {engine} engine
* @param {} options
@@ -2519,7 +3201,8 @@ var MouseConstraint = {};
};
/**
- * Description
+ * Updates the given mouse constraint.
+ * @private
* @method update
* @param {MouseConstraint} mouseConstraint
* @param {body[]} bodies
@@ -2553,6 +3236,51 @@ var MouseConstraint = {};
}
};
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * A `String` denoting the type of object.
+ *
+ * @property type
+ * @type string
+ * @default "constraint"
+ */
+
+ /**
+ * The `Mouse` instance in use.
+ *
+ * @property mouse
+ * @type mouse
+ * @default engine.input.mouse
+ */
+
+ /**
+ * The `Body` that is currently being moved by the user, or `null` if no body.
+ *
+ * @property dragBody
+ * @type body
+ * @default null
+ */
+
+ /**
+ * The `Vector` offset at which the drag started relative to the `dragBody`, if any.
+ *
+ * @property dragPoint
+ * @type body
+ * @default null
+ */
+
+ /**
+ * The `Constraint` object that is used to move the body during interaction.
+ *
+ * @property constraint
+ * @type constraint
+ */
+
})();
; // End src/constraint/MouseConstraint.js
@@ -2571,6 +3299,7 @@ var Common = {};
(function() {
Common._nextId = 0;
+ Common._seed = 0;
/**
* Description
@@ -2694,7 +3423,7 @@ var Common = {};
*/
Common.shuffle = function(array) {
for (var i = array.length - 1; i > 0; i--) {
- var j = Math.floor(Math.random() * (i + 1));
+ var j = Math.floor(Common.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
@@ -2709,7 +3438,7 @@ var Common = {};
* @return {object} A random choice object from the array
*/
Common.choose = function(choices) {
- return choices[Math.floor(Math.random() * choices.length)];
+ return choices[Math.floor(Common.random() * choices.length)];
};
/**
@@ -2784,7 +3513,9 @@ var Common = {};
* @return {number} A random number between min and max inclusive
*/
Common.random = function(min, max) {
- return min + Math.random() * (max - min);
+ min = (typeof min !== "undefined") ? min : 0;
+ max = (typeof max !== "undefined") ? max : 1;
+ return min + _seededRandom() * (max - min);
};
/**
@@ -2840,6 +3571,12 @@ var Common = {};
return Common._nextId++;
};
+ var _seededRandom = function() {
+ // https://gist.github.com/ngryman/3830489
+ Common._seed = (Common._seed * 9301 + 49297) % 233280;
+ return Common._seed / 233280;
+ };
+
})();
; // End src/core/Common.js
@@ -2848,14 +3585,15 @@ var Common = {};
// Begin src/core/Engine.js
/**
+* The `Matter.Engine` module contains methods for creating and manipulating engines.
+* An engine is a controller that manages updating and rendering the simulation of the world.
+*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
* @class Engine
*/
-// TODO: viewports
-
var Engine = {};
(function() {
@@ -2869,10 +3607,12 @@ var Engine = {};
|| function(callback){ window.setTimeout(function() { callback(Common.now()); }, _delta); };
/**
- * Description
+ * 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 properites section below for detailed information on what you can pass via the `options` object.
* @method create
* @param {HTMLElement} element
- * @param {object} options
+ * @param {object} [options]
* @return {engine} engine
*/
Engine.create = function(element, options) {
@@ -3027,8 +3767,7 @@ var Engine = {};
* @method update
* @param {engine} engine
* @param {number} delta
- * @param {number} correction
- * @return engine
+ * @param {number} [correction]
*/
Engine.update = function(engine, delta, correction) {
correction = (typeof correction !== 'undefined') ? correction : 1;
@@ -3147,7 +3886,7 @@ var Engine = {};
};
/**
- * Description
+ * 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
@@ -3171,7 +3910,7 @@ var Engine = {};
};
/**
- * Description
+ * Clears the engine including the world, pairs and broadphase.
* @method clear
* @param {engine} engine
*/
@@ -3387,6 +4126,127 @@ var Engine = {};
* @param {} event.name The name of the event
*/
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * A flag that specifies whether the engine is running or not.
+ *
+ * @property enabled
+ * @type boolean
+ * @default true
+ */
+
+ /**
+ * 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 `timing.delta`.
+ *
+ * @property timing.timestamp
+ * @type number
+ * @default 0
+ */
+
+ /**
+ * A `Number` that specifies the time step between updates in milliseconds.
+ * If `engine.timing.isFixed` is set to `true`, then `delta` is fixed.
+ * If it is `false`, then `delta` can dynamically change to maintain the correct apparant simulation speed.
+ *
+ * @property timing.delta
+ * @type number
+ * @default 1000 / 60
+ */
+
+ /**
+ * A `Number` that specifies the time correction factor to apply to the current timestep.
+ * It is automatically handled when using `Engine.run`, but is also only optional even if you use your own game loop.
+ * The value is defined as `delta / lastDelta`, i.e. the percentage change of `delta` between steps.
+ * This value is always `1` (no correction) when frame rate is constant or `engine.timing.isFixed` is `true`.
+ * If the framerate and hence `delta` are changing, then correction should be applied to the current update to account for the change.
+ * See the paper on Time Corrected Verlet for more information.
+ *
+ * @property timing.correction
+ * @type number
+ * @default 1
+ */
+
+ /**
+ * An instance of a `Render` controller. The default value is a `Matter.Render` instance created by `Engine.create`.
+ * One may also develop a custom renderer module based on `Matter.Render` and pass an instance of it to `Engine.create` via `options.render`.
+ *
+ * A minimal custom renderer object must define at least three functions: `create`, `clear` and `world` (see `Matter.Render`).
+ * It is also possible to instead pass the _module_ reference via `options.render.controller` and `Engine.create` will instantiate one for you.
+ *
+ * @property render
+ * @type render
+ * @default a Matter.Render instance
+ */
+
+ /**
+ * A `World` composite object that will contain all simulated bodies and constraints.
+ *
+ * @property world
+ * @type world
+ * @default a Matter.World instance
+ */
+
})();
; // End src/core/Engine.js
@@ -3406,7 +4266,7 @@ var Events = {};
(function() {
/**
- * Subscribes a callback function to the given object's eventName
+ * Subscribes a callback function to the given object's `eventName`.
* @method on
* @param {} object
* @param {string} eventNames
@@ -3427,7 +4287,7 @@ var Events = {};
};
/**
- * Removes the given event callback. If no callback, clears all callbacks in eventNames. If no eventNames, clears all events.
+ * Removes the given event callback. If no callback, clears all callbacks in `eventNames`. If no `eventNames`, clears all events.
* @method off
* @param {} object
* @param {string} eventNames
@@ -3463,7 +4323,7 @@ var Events = {};
};
/**
- * Fires all the callbacks subscribed to the given object's eventName, in the order they subscribed, if any
+ * Fires all the callbacks subscribed to the given object's `eventName`, in the order they subscribed, if any.
* @method trigger
* @param {} object
* @param {string} eventNames
@@ -3910,6 +4770,9 @@ var Sleeping = {};
// Begin src/factory/Bodies.js
/**
+* The `Matter.Bodies` module contains factory methods for creating rigid body models
+* with commonly used body configurations (such as rectangles, circles and other polygons).
+*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
@@ -3923,13 +4786,15 @@ var Bodies = {};
(function() {
/**
- * Description
+ * Creates a new rigid body model with a rectangle hull.
+ * The options parameter is an object that specifies any properties you wish to override the defaults.
+ * See the properites section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
* @method rectangle
* @param {number} x
* @param {number} y
* @param {number} width
* @param {number} height
- * @param {object} options
+ * @param {object} [options]
* @return {body} A new rectangle body
*/
Bodies.rectangle = function(x, y, width, height, options) {
@@ -3952,14 +4817,16 @@ var Bodies = {};
};
/**
- * Description
+ * Creates a new rigid body model with a trapezoid hull.
+ * The options parameter is an object that specifies any properties you wish to override the defaults.
+ * See the properites section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
* @method trapezoid
* @param {number} x
* @param {number} y
* @param {number} width
* @param {number} height
* @param {number} slope
- * @param {object} options
+ * @param {object} [options]
* @return {body} A new trapezoid body
*/
Bodies.trapezoid = function(x, y, width, height, slope, options) {
@@ -3989,12 +4856,14 @@ var Bodies = {};
};
/**
- * Description
+ * Creates a new rigid body model with a circle hull.
+ * The options parameter is an object that specifies any properties you wish to override the defaults.
+ * See the properites section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
* @method circle
* @param {number} x
* @param {number} y
* @param {number} radius
- * @param {object} options
+ * @param {object} [options]
* @param {number} maxSides
* @return {body} A new circle body
*/
@@ -4018,13 +4887,15 @@ var Bodies = {};
};
/**
- * Description
+ * Creates a new rigid body model with a regular polygon hull with the given number of sides.
+ * The options parameter is an object that specifies any properties you wish to override the defaults.
+ * See the properites section of the `Matter.Body` module for detailed information on what you can pass via the `options` object.
* @method polygon
* @param {number} x
* @param {number} y
* @param {number} sides
* @param {number} radius
- * @param {object} options
+ * @param {object} [options]
* @return {body} A new regular polygon body
*/
Bodies.polygon = function(x, y, sides, radius, options) {
@@ -4576,6 +5447,10 @@ var Bounds = {};
// Begin src/geometry/Vector.js
/**
+* The `Matter.Vector` module contains methods for creating and manipulating vectors.
+* Vectors are the basis of all the geometry related operations in the engine.
+* A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`.
+*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
@@ -4589,7 +5464,17 @@ var Vector = {};
(function() {
/**
- * Description
+ * Returns a new vector with `x` and `y` copied from the given `vector`.
+ * @method clone
+ * @param {vector} vector
+ * @return {vector} A new cloned vector
+ */
+ Vector.clone = function(vector) {
+ return { x: vector.x, y: vector.y };
+ };
+
+ /**
+ * Returns the magnitude (length) of a vector.
* @method magnitude
* @param {vector} vector
* @return {number} The magnitude of the vector
@@ -4599,7 +5484,7 @@ var Vector = {};
};
/**
- * Description
+ * Returns the magnitude (length) of a vector (therefore saving a `sqrt` operation).
* @method magnitudeSquared
* @param {vector} vector
* @return {number} The squared magnitude of the vector
@@ -4609,11 +5494,11 @@ var Vector = {};
};
/**
- * Description
+ * Rotates the vector about (0, 0) by specified angle.
* @method rotate
* @param {vector} vector
* @param {number} angle
- * @return {vector} A new vector rotated
+ * @return {vector} A new vector rotated about (0, 0)
*/
Vector.rotate = function(vector, angle) {
var cos = Math.cos(angle), sin = Math.sin(angle);
@@ -4624,7 +5509,7 @@ var Vector = {};
};
/**
- * Description
+ * Rotates the vector about a specified point by specified angle.
* @method rotateAbout
* @param {vector} vector
* @param {number} angle
@@ -4640,7 +5525,7 @@ var Vector = {};
};
/**
- * Description
+ * Normalises a vector (such that its magnitude is `1`).
* @method normalise
* @param {vector} vector
* @return {vector} A new vector normalised
@@ -4653,7 +5538,7 @@ var Vector = {};
};
/**
- * Description
+ * Returns the dot-product of two vectors.
* @method dot
* @param {vector} vectorA
* @param {vector} vectorB
@@ -4664,7 +5549,7 @@ var Vector = {};
};
/**
- * Description
+ * Returns the cross-product of two vectors.
* @method cross
* @param {vector} vectorA
* @param {vector} vectorB
@@ -4675,29 +5560,29 @@ var Vector = {};
};
/**
- * Description
+ * Adds the two vectors.
* @method add
* @param {vector} vectorA
* @param {vector} vectorB
- * @return {vector} A new vector added
+ * @return {vector} A new vector of vectorA and vectorB added
*/
Vector.add = function(vectorA, vectorB) {
return { x: vectorA.x + vectorB.x, y: vectorA.y + vectorB.y };
};
/**
- * Description
+ * Subtracts the two vectors.
* @method sub
* @param {vector} vectorA
* @param {vector} vectorB
- * @return {vector} A new vector subtracted
+ * @return {vector} A new vector of vectorA and vectorB subtracted
*/
Vector.sub = function(vectorA, vectorB) {
return { x: vectorA.x - vectorB.x, y: vectorA.y - vectorB.y };
};
/**
- * Description
+ * Multiplies a vector and a scalar.
* @method mult
* @param {vector} vector
* @param {number} scalar
@@ -4708,7 +5593,7 @@ var Vector = {};
};
/**
- * Description
+ * Divides a vector and a scalar.
* @method div
* @param {vector} vector
* @param {number} scalar
@@ -4719,10 +5604,10 @@ var Vector = {};
};
/**
- * Description
+ * Returns the perpendicular vector. Set `negate` to true for the perpendicular in the opposite direction.
* @method perp
* @param {vector} vector
- * @param {bool} negate
+ * @param {bool} [negate=false]
* @return {vector} The perpendicular vector
*/
Vector.perp = function(vector, negate) {
@@ -4731,7 +5616,7 @@ var Vector = {};
};
/**
- * Description
+ * Negates both components of a vector such that it points in the opposite direction.
* @method neg
* @param {vector} vector
* @return {vector} The negated vector
@@ -4741,7 +5626,7 @@ var Vector = {};
};
/**
- * Returns the angle in radians between the two vectors relative to the x-axis
+ * Returns the angle in radians between the two vectors relative to the x-axis.
* @method angle
* @param {vector} vectorA
* @param {vector} vectorB
@@ -4759,6 +5644,10 @@ var Vector = {};
// Begin src/geometry/Vertices.js
/**
+* The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices.
+* A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`.
+* A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull).
+*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
*
@@ -4772,37 +5661,58 @@ var Vertices = {};
(function() {
/**
- * Description
+ * Creates a new set of `Matter.Body` compatible vertices.
+ * The `points` argument accepts an array of `Matter.Vector` points orientated around the origin `(0, 0)`, for example:
+ *
+ * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]
+ *
+ * The `Vertices.create` method returns a new array of vertices, which are similar to Matter.Vector objects,
+ * but with some additional references required for efficient collision detection routines.
+ *
+ * Note that the `body` argument is not optional, a `Matter.Body` reference must be provided.
+ *
* @method create
- * @param {vertices} vertices
+ * @param {vector[]} points
* @param {body} body
*/
- Vertices.create = function(vertices, body) {
- for (var i = 0; i < vertices.length; i++) {
- vertices[i].index = i;
- vertices[i].body = body;
+ Vertices.create = function(points, body) {
+ var vertices = [];
+
+ for (var i = 0; i < points.length; i++) {
+ var point = points[i],
+ vertex = {};
+
+ vertex.x = point.x;
+ vertex.y = point.y;
+ vertex.index = i;
+ vertex.body = body;
+
+ vertices.push(vertex);
}
- };
-
- /**
- * Description
- * @method fromPath
- * @param {string} path
- * @return {vertices} vertices
- */
- Vertices.fromPath = function(path) {
- var pathPattern = /L\s*([\-\d\.]*)\s*([\-\d\.]*)/ig,
- vertices = [];
-
- path.replace(pathPattern, function(match, x, y) {
- vertices.push({ x: parseFloat(x, 10), y: parseFloat(y, 10) });
- });
return vertices;
};
/**
- * Description
+ * Parses a _simple_ SVG-style path into a `Matter.Vertices` object for the given `Matter.Body`.
+ * @method fromPath
+ * @param {string} path
+ * @param {body} body
+ * @return {vertices} vertices
+ */
+ Vertices.fromPath = function(path, body) {
+ var pathPattern = /L\s*([\-\d\.]*)\s*([\-\d\.]*)/ig,
+ points = [];
+
+ path.replace(pathPattern, function(match, x, y) {
+ points.push({ x: parseFloat(x, 10), y: parseFloat(y, 10) });
+ });
+
+ return Vertices.create(points, body);
+ };
+
+ /**
+ * Returns the centre (centroid) of the set of vertices.
* @method centre
* @param {vertices} vertices
* @return {vector} The centre point
@@ -4825,7 +5735,7 @@ var Vertices = {};
};
/**
- * Description
+ * Returns the area of the set of vertices.
* @method area
* @param {vertices} vertices
* @param {bool} signed
@@ -4847,11 +5757,11 @@ var Vertices = {};
};
/**
- * Description
+ * Returns the moment of inertia (second moment of area) of the set of vertices given the total mass.
* @method inertia
* @param {vertices} vertices
* @param {number} mass
- * @return {number} The polygon's moment of inertia, using second moment of area
+ * @return {number} The polygon's moment of inertia
*/
Vertices.inertia = function(vertices, mass) {
var numerator = 0,
@@ -4873,7 +5783,7 @@ var Vertices = {};
};
/**
- * Description
+ * Translates the set of vertices in-place.
* @method translate
* @param {vertices} vertices
* @param {vector} vector
@@ -4891,11 +5801,13 @@ var Vertices = {};
vertices[i].x += vector.x;
vertices[i].y += vector.y;
}
- }
+ }
+
+ return vertices;
};
/**
- * Description
+ * Rotates the set of vertices in-place.
* @method rotate
* @param {vertices} vertices
* @param {number} angle
@@ -4916,10 +5828,12 @@ var Vertices = {};
vertice.x = point.x + (dx * cos - dy * sin);
vertice.y = point.y + (dx * sin + dy * cos);
}
+
+ return vertices;
};
/**
- * Description
+ * Returns `true` if the `point` is inside the set of `vertices`.
* @method contains
* @param {vertices} vertices
* @param {vector} point
@@ -4938,7 +5852,7 @@ var Vertices = {};
};
/**
- * Scales the vertices from a point (default is centre)
+ * Scales the vertices from a point (default is centre) in-place.
* @method scale
* @param {vertices} vertices
* @param {number} scaleX
@@ -5046,23 +5960,27 @@ var Vertices = {};
// Begin src/render/Render.js
/**
-* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
-* and [DemoMobile.js](https://github.com/liabru/matter-js/blob/master/demo/js/DemoMobile.js) for usage examples.
+* The `Matter.Render` module is the default `render.controller` used by a `Matter.Engine`.
+* This renderer is HTML5 canvas based and supports a number of drawing options including sprites and viewports.
+*
+* It is possible develop a custom renderer module based on `Matter.Render` and pass an instance of it to `Engine.create` via `options.render`.
+* A minimal custom renderer object must define at least three functions: `create`, `clear` and `world` (see `Matter.Render`).
+*
+* See also `Matter.RenderPixi` for an alternate WebGL, scene-graph based renderer.
*
* @class Render
*/
-// TODO: viewports
-// TODO: two.js, pixi.js
-
var Render = {};
(function() {
/**
- * Description
+ * Creates a new renderer. 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 properites section below for detailed information on what you can pass via the `options` object.
* @method create
- * @param {object} options
+ * @param {object} [options]
* @return {render} A new renderer
*/
Render.create = function(options) {
@@ -5150,7 +6068,8 @@ var Render = {};
};
/**
- * Description
+ * Renders the given `engine`'s `Matter.World` object.
+ * This is the entry point for all rendering and should be called every time the scene changes.
* @method world
* @param {engine} engine
*/
@@ -5260,6 +6179,7 @@ var Render = {};
/**
* Description
+ * @private
* @method debug
* @param {engine} engine
* @param {RenderingContext} context
@@ -5316,6 +6236,7 @@ var Render = {};
/**
* Description
+ * @private
* @method constraints
* @param {constraint[]} constraints
* @param {RenderingContext} context
@@ -5354,6 +6275,7 @@ var Render = {};
/**
* Description
+ * @private
* @method bodyShadows
* @param {engine} engine
* @param {body[]} bodies
@@ -5403,6 +6325,7 @@ var Render = {};
/**
* Description
+ * @private
* @method bodies
* @param {engine} engine
* @param {body[]} bodies
@@ -5479,6 +6402,7 @@ var Render = {};
/**
* Optimised method for drawing body wireframes in one pass
+ * @private
* @method bodyWireframes
* @param {engine} engine
* @param {body[]} bodies
@@ -5513,6 +6437,7 @@ var Render = {};
/**
* Draws body bounds
+ * @private
* @method bodyBounds
* @param {engine} engine
* @param {body[]} bodies
@@ -5544,6 +6469,7 @@ var Render = {};
/**
* Draws body angle indicators and axes
+ * @private
* @method bodyAxes
* @param {engine} engine
* @param {body[]} bodies
@@ -5591,6 +6517,7 @@ var Render = {};
/**
* Draws body positions
+ * @private
* @method bodyPositions
* @param {engine} engine
* @param {body[]} bodies
@@ -5638,6 +6565,7 @@ var Render = {};
/**
* Draws body velocity
+ * @private
* @method bodyVelocity
* @param {engine} engine
* @param {body[]} bodies
@@ -5667,6 +6595,7 @@ var Render = {};
/**
* Draws body ids
+ * @private
* @method bodyIds
* @param {engine} engine
* @param {body[]} bodies
@@ -5689,6 +6618,7 @@ var Render = {};
/**
* Description
+ * @private
* @method collisions
* @param {engine} engine
* @param {pair[]} pairs
@@ -5755,6 +6685,7 @@ var Render = {};
/**
* Description
+ * @private
* @method grid
* @param {engine} engine
* @param {grid} grid
@@ -5793,6 +6724,7 @@ var Render = {};
/**
* Description
+ * @private
* @method inspector
* @param {inspector} inspector
* @param {RenderingContext} context
@@ -5914,6 +6846,90 @@ var Render = {};
return image;
};
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * A back-reference to the `Matter.Render` module.
+ *
+ * @property controller
+ * @type render
+ */
+
+ /**
+ * A reference to the element where the canvas is to be inserted (if `render.canvas` has not been specified)
+ *
+ * @property element
+ * @type HTMLElement
+ * @default null
+ */
+
+ /**
+ * The canvas element to render to. If not specified, one will be created if `render.element` has been specified.
+ *
+ * @property canvas
+ * @type HTMLCanvasElement
+ * @default null
+ */
+
+ /**
+ * The configuration options of the renderer.
+ *
+ * @property options
+ * @type {}
+ */
+
+ /**
+ * The target width in pixels of the `render.canvas` to be created.
+ *
+ * @property options.width
+ * @type number
+ * @default 800
+ */
+
+ /**
+ * The target height in pixels of the `render.canvas` to be created.
+ *
+ * @property options.height
+ * @type number
+ * @default 600
+ */
+
+ /**
+ * A flag that specifies if `render.bounds` should be used when rendering.
+ *
+ * @property options.hasBounds
+ * @type boolean
+ * @default false
+ */
+
+ /**
+ * A `Bounds` object that specifies the drawing view region.
+ * Rendering will be automatically transformed and scaled to fit within the canvas size (`render.options.width` and `render.options.height`).
+ * This allows for creating views that can pan or zoom around the scene.
+ * You must also set `render.options.hasBounds` to `true` to enable bounded rendering.
+ *
+ * @property bounds
+ * @type bounds
+ */
+
+ /**
+ * The 2d rendering context from the `render.canvas` element.
+ *
+ * @property context
+ * @type CanvasRenderingContext2D
+ */
+
+ /**
+ * The sprite texture cache.
+ *
+ * @property textures
+ * @type {}
+ */
+
})();
; // End src/render/Render.js
diff --git a/build/matter.min.js b/build/matter.min.js
index fcc56b2..1eb2b1c 100644
--- a/build/matter.min.js
+++ b/build/matter.min.js
@@ -1,8 +1,8 @@
/**
-* matter.min.js 0.8.0-edge 2014-05-04
+* matter.min.js 0.8.0-edge 2014-06-09
* http://brm.io/matter-js/
* License: MIT
*/
-!function(){var a={},b={};!function(){var a=1;b.create=function(a){var b={id:o.nextId(),type:"body",label:"Body",angle:0,vertices:z.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},speed:0,angularSpeed:0,velocity:{x:0,y:0},angularVelocity:0,isStatic:!1,isSleeping:!1,motion:0,sleepThreshold:60,density:.001,restitution:0,friction:.1,frictionAir:.01,groupId:0,slop:.05,timeScale:1,render:{visible:!0,sprite:{xScale:1,yScale:1},lineWidth:1.5}},d=o.extend(b,a);return c(d),d},b.nextGroupId=function(){return a++};var c=function(a){a.axes=a.axes||w.fromVertices(a.vertices),a.area=z.area(a.vertices),a.bounds=x.create(a.vertices),a.mass=a.mass||a.density*a.area,a.inverseMass=1/a.mass,a.inertia=a.inertia||z.inertia(a.vertices,a.mass),a.inverseInertia=1/a.inertia,a.positionPrev=a.positionPrev||{x:a.position.x,y:a.position.y},a.anglePrev=a.anglePrev||a.angle,a.render.fillStyle=a.render.fillStyle||(a.isStatic?"#eeeeee":o.choose(["#556270","#4ECDC4","#C7F464","#FF6B6B","#C44D58"])),a.render.strokeStyle=a.render.strokeStyle||o.shadeColor(a.render.fillStyle,-20),z.create(a.vertices,a);var c=z.centre(a.vertices);z.translate(a.vertices,a.position),z.translate(a.vertices,c,-1),z.rotate(a.vertices,a.angle,a.position),w.rotate(a.axes,a.angle),x.update(a.bounds,a.vertices,a.velocity),b.setStatic(a,a.isStatic),t.set(a,a.isSleeping)};b.setStatic=function(a,b){a.isStatic=b,b&&(a.restitution=0,a.friction=1,a.mass=a.inertia=a.density=1/0,a.inverseMass=a.inverseInertia=0,a.render.lineWidth=1,a.positionPrev.x=a.position.x,a.positionPrev.y=a.position.y,a.anglePrev=a.angle,a.angularVelocity=0,a.speed=0,a.angularSpeed=0,a.motion=0)},b.resetForcesAll=function(a){for(var b=0;bf.max.x||h.bounds.max.yf.max.y||b.update(h,c,d,e)}},b.update=function(a,b,c,d){var e=Math.pow(b*c*a.timeScale,2),f=1-a.frictionAir*c*a.timeScale,g=a.position.x-a.positionPrev.x,h=a.position.y-a.positionPrev.y;a.velocity.x=g*f*d+a.force.x/a.mass*e,a.velocity.y=h*f*d+a.force.y/a.mass*e,a.positionPrev.x=a.position.x,a.positionPrev.y=a.position.y,a.position.x+=a.velocity.x,a.position.y+=a.velocity.y,a.angularVelocity=(a.angle-a.anglePrev)*f*d+a.torque/a.inertia*e,a.anglePrev=a.angle,a.angle+=a.angularVelocity,a.speed=y.magnitude(a.velocity),a.angularSpeed=Math.abs(a.angularVelocity),z.translate(a.vertices,a.velocity),0!==a.angularVelocity&&(z.rotate(a.vertices,a.angularVelocity,a.position),w.rotate(a.axes,a.angularVelocity)),x.update(a.bounds,a.vertices,a.velocity)},b.applyForce=function(a,b,c){a.force.x+=c.x,a.force.y+=c.y;var d={x:b.x-a.position.x,y:b.y-a.position.y};a.torque+=(d.x*c.y-d.y*c.x)*a.inverseInertia},b.translate=function(a,b){a.positionPrev.x+=b.x,a.positionPrev.y+=b.y,a.position.x+=b.x,a.position.y+=b.y,z.translate(a.vertices,b),x.update(a.bounds,a.vertices,a.velocity)},b.rotate=function(a,b){a.anglePrev+=b,a.angle+=b,z.rotate(a.vertices,b,a.position),w.rotate(a.axes,b),x.update(a.bounds,a.vertices,a.velocity)},b.scale=function(a,b,c,d){z.scale(a.vertices,b,c,d),a.axes=w.fromVertices(a.vertices),a.area=z.area(a.vertices),a.mass=a.density*a.area,a.inverseMass=1/a.mass,z.translate(a.vertices,{x:-a.position.x,y:-a.position.y}),a.inertia=z.inertia(a.vertices,a.mass),a.inverseInertia=1/a.inertia,z.translate(a.vertices,{x:a.position.x,y:a.position.y}),x.update(a.bounds,a.vertices,a.velocity)}}();var c={};!function(){c.create=function(a){return o.extend({id:o.nextId(),type:"composite",parent:null,isModified:!1,bodies:[],constraints:[],composites:[],label:"Composite"},a)},c.setModified=function(a,b,d,e){if(a.isModified=b,d&&a.parent&&c.setModified(a.parent,b,d,e),e)for(var f=0;fq.bounds.width||u.bounds.max.y<0||u.bounds.min.y>q.bounds.height)){var v=b(c,u);if(!u.region||v.id!==u.region.id||k){s.broadphaseTests+=1,(!u.region||k)&&(u.region=v);var w=a(v,u.region);for(m=w.startCol;m<=w.endCol;m++)for(n=w.startRow;n<=w.endRow;n++){p=d(m,n),o=r[p];var x=m>=v.startCol&&m<=v.endCol&&n>=v.startRow&&n<=v.endRow,y=m>=u.region.startCol&&m<=u.region.endCol&&n>=u.region.startRow&&n<=u.region.endRow;!x&&y&&y&&o&&i(c,o,u),(u.region===v||x&&!y||k)&&(o||(o=e(r,p)),f(c,o,u))}u.region=v,t=!0}}}t&&(c.pairsList=j(c))},g.clear=function(a){a.buckets={},a.pairs={},a.pairsList=[]};var a=function(a,b){var d=Math.min(a.startCol,b.startCol),e=Math.max(a.endCol,b.endCol),f=Math.min(a.startRow,b.startRow),g=Math.max(a.endRow,b.endRow);return c(d,e,f,g)},b=function(a,b){var d=b.bounds,e=Math.floor(d.min.x/a.bucketWidth),f=Math.floor(d.max.x/a.bucketWidth),g=Math.floor(d.min.y/a.bucketHeight),h=Math.floor(d.max.y/a.bucketHeight);return c(e,f,g,h)},c=function(a,b,c,d){return{id:a+","+b+","+c+","+d,startCol:a,endCol:b,startRow:c,endRow:d}},d=function(a,b){return a+","+b},e=function(a,b){var c=a[b]=[];return c},f=function(a,b,c){for(var d=0;d0?d.push(c):delete a.pairs[b[e]];return d}}();var h={};!function(){h.create=function(a,b){var c=a.bodyA,d=a.bodyB,e={id:h.id(c,d),bodyA:c,bodyB:d,contacts:{},activeContacts:[],separation:0,isActive:!0,timeCreated:b,timeUpdated:b,inverseMass:c.inverseMass+d.inverseMass,friction:Math.min(c.friction,d.friction),restitution:Math.max(c.restitution,d.restitution),slop:Math.max(c.slop,d.slop)};return h.update(e,a,b),e},h.update=function(a,b,c){var d=a.contacts,f=b.supports,g=a.activeContacts;if(a.collision=b,g.length=0,b.collided){for(var i=0;ia&&j.push(g);for(g=0;gD*g.friction*e&&(E=D*g.friction*e*B);var F=y.cross(s,k),G=y.cross(t,k),H=n/(g.inverseMass+i.inverseInertia*F*F+j.inverseInertia*G*G);if(C*=H,E*=H,0>x&&x*x>a*e)q.normalImpulse=0,q.tangentImpulse=0;else{var I=q.normalImpulse;q.normalImpulse=Math.min(q.normalImpulse+C,0),C=q.normalImpulse-I;var J=q.tangentImpulse;q.tangentImpulse=o.clamp(q.tangentImpulse+E,-A,A),E=q.tangentImpulse-J}d.x=k.x*C+l.x*E,d.y=k.y*C+l.y*E,i.isStatic||i.isSleeping||(i.positionPrev.x+=d.x*i.inverseMass,i.positionPrev.y+=d.y*i.inverseMass,i.anglePrev+=y.cross(s,d)*i.inverseInertia),j.isStatic||j.isSleeping||(j.positionPrev.x-=d.x*j.inverseMass,j.positionPrev.y-=d.y*j.inverseMass,j.anglePrev-=y.cross(t,d)*j.inverseInertia)}}}}}();var l={};!function(){l.collides=function(b,d,e){var f,g,h,i,j=e,k=!1;if(j){var l=b.speed*b.speed+b.angularSpeed*b.angularSpeed+d.speed*d.speed+d.angularSpeed*d.angularSpeed;k=j&&j.collided&&.2>l,i=j}else i={collided:!1,bodyA:b,bodyB:d};if(j&&k){var m=[j.bodyA.axes[j.axisNumber]];if(h=a(j.bodyA.vertices,j.bodyB.vertices,m),i.reused=!0,h.overlap<=0)return i.collided=!1,i}else{if(f=a(b.vertices,d.vertices,b.axes),f.overlap<=0)return i.collided=!1,i;if(g=a(d.vertices,b.vertices,d.axes),g.overlap<=0)return i.collided=!1,i;f.overlap0&&(i.normal=y.neg(i.normal)),i.tangent=y.perp(i.normal),i.penetration={x:i.normal.x*i.depth,y:i.normal.y*i.depth};var n=c(b,d,i.normal),o=[n[0]];if(z.contains(b.vertices,n[1]))o.push(n[1]);else{var p=c(d,b,y.neg(i.normal));z.contains(d.vertices,p[0])&&o.push(p[0]),o.length<2&&z.contains(d.vertices,p[1])&&o.push(p[1])}return i.supports=o,i.supportCorrected=y.sub(n[0],i.penetration),i};var a=function(a,c,d){for(var e,f,g={},h={},i={overlap:Number.MAX_VALUE},j=0;j=e)return i.overlap=e,i;ee?e=g:d>g&&(d=g)}a.min=d,a.max=e},c=function(a,b,c){for(var d,e,f=Number.MAX_VALUE,g={x:0,y:0},h=b.vertices,i=a.position,j=h[0],k=h[1],l=0;ld&&(f=d,j=e);var m=j.index-1>=0?j.index-1:h.length-1;e=h[m],g.x=e.x-i.x,g.y=e.y-i.y,f=-y.dot(c,g),k=e;var n=(j.index+1)%h.length;return e=h[n],g.x=e.x-i.x,g.y=e.y-i.y,d=-y.dot(c,g),f>d&&(f=d,k=e),[j,k]}}();var m={};!function(){var a=1e-6,b=.001;m.create=function(b){var c=b;c.bodyA&&!c.pointA&&(c.pointA={x:0,y:0}),c.bodyB&&!c.pointB&&(c.pointB={x:0,y:0});var d=c.bodyA?y.add(c.bodyA.position,c.pointA):c.pointA,e=c.bodyB?y.add(c.bodyB.position,c.pointB):c.pointB,f=y.magnitude(y.sub(d,e));c.length=c.length||f||a;var g={visible:!0,lineWidth:2,strokeStyle:"#666"};return c.render=o.extend(g,c.render),c.id=c.id||o.nextId(),c.label=c.label||"Constraint",c.type="constraint",c.stiffness=c.stiffness||1,c.angularStiffness=c.angularStiffness||0,c.angleA=c.bodyA?c.bodyA.angle:c.angleA,c.angleB=c.bodyB?c.bodyB.angle:c.angleB,c},m.solveAll=function(a,b){for(var c=0;c0&&(B=0);var C,D={x:n.x*B,y:n.y*B};e&&!e.isStatic&&(C=y.cross(s,D)*e.inverseInertia*(1-c.angularStiffness),t.set(e,!1),C=o.clamp(C,-.01,.01),e.constraintImpulse.x-=p.x,e.constraintImpulse.y-=p.y,e.constraintImpulse.angle+=C,e.position.x-=p.x,e.position.y-=p.y,e.angle+=C),f&&!f.isStatic&&(C=y.cross(u,D)*f.inverseInertia*(1-c.angularStiffness),t.set(f,!1),C=o.clamp(C,-.01,.01),f.constraintImpulse.x+=p.x,f.constraintImpulse.y+=p.y,f.constraintImpulse.angle-=C,f.position.x+=p.x,f.position.y+=p.y,f.angle-=C)}}},m.postSolveAll=function(a){for(var b=0;b>16)+d,f=(c>>8&255)+d,g=(255&c)+d;return"#"+(16777216+65536*(255>e?1>e?0:e:255)+256*(255>f?1>f?0:f:255)+(255>g?1>g?0:g:255)).toString(16).slice(1)},o.shuffle=function(a){for(var b=a.length-1;b>0;b--){var c=Math.floor(Math.random()*(b+1)),d=a[b];a[b]=a[c],a[c]=d}return a},o.choose=function(a){return a[Math.floor(Math.random()*a.length)]},o.isElement=function(a){try{return a instanceof HTMLElement}catch(b){return"object"==typeof a&&1===a.nodeType&&"object"==typeof a.style&&"object"==typeof a.ownerDocument}},o.clamp=function(a,b,c){return b>a?b:a>c?c:a},o.sign=function(a){return 0>a?-1:1},o.now=function(){var a=window.performance;return a?(a.now=a.now||a.webkitNow||a.msNow||a.oNow||a.mozNow,+a.now()):+new Date},o.random=function(a,b){return a+Math.random()*(b-a)},o.colorToNumber=function(a){return a=a.replace("#",""),3==a.length&&(a=a.charAt(0)+a.charAt(0)+a.charAt(1)+a.charAt(1)+a.charAt(2)+a.charAt(2)),parseInt(a,16)},o.log=function(a,b){if(console&&console.log){var c;switch(b){case"warn":c="color: coral";break;case"error":c="color: red"}console.log("%c [Matter] "+b+": "+a,c)}},o.nextId=function(){return o._nextId++}}();var p={};!function(){var a=60,e=a,h=1e3/a,j=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(function(){a(o.now())},h)};p.create=function(b,c){c=o.isElement(b)?c:b,b=o.isElement(b)?b:null;var e={enabled:!0,positionIterations:6,velocityIterations:4,constraintIterations:2,enableSleeping:!1,timeScale:1,input:{},events:[],timing:{fps:a,timestamp:0,delta:h,correction:1,deltaMin:1e3/a,deltaMax:1e3/(.5*a),timeScale:1,isFixed:!1},render:{element:b,controller:A}},j=o.extend(e,c);return j.render=j.render.controller.create(j.render),j.world=d.create(j.world),j.pairs=i.create(),j.metrics=j.metrics||r.create(),j.input.mouse=j.input.mouse||s.create(j.render.canvas),j.broadphase=j.broadphase||{current:"grid",grid:{controller:g,instance:g.create(),detector:f.collisions},bruteForce:{detector:f.bruteForce}},j},p.run=function(a){var b,c=0,d=0,f=[],g=1;!function h(i){if(j(h),a.enabled){var k,m,o=a.timing,r={timestamp:i};q.trigger(a,"beforeTick",r),o.isFixed?k=o.delta:(k=i-b||o.delta,b=i,f.push(k),f=f.slice(-e),k=Math.min.apply(null,f),k=ko.deltaMax?o.deltaMax:k,m=k/o.delta,o.delta=k),0!==g&&(m*=o.timeScale/g),0===o.timeScale&&(m=0),g=o.timeScale,d+=1,i-c>=1e3&&(o.fps=d*((i-c)/1e3),c=i,d=0),q.trigger(a,"tick",r),a.world.isModified&&a.render.controller.clear(a.render),p.update(a,k,m),n(a),l(a),p.render(a),q.trigger(a,"afterTick",r)}}()},p.update=function(a,d,e){e="undefined"!=typeof e?e:1;var f,g=a.world,h=a.timing,j=a.broadphase[a.broadphase.current],l=[];h.timestamp+=d*h.timeScale,h.correction=e;var n={timestamp:a.timing.timestamp};q.trigger(a,"beforeUpdate",n);var o=c.allBodies(g),p=c.allConstraints(g);for(r.reset(a.metrics),a.enableSleeping&&t.update(o),b.applyGravityAll(o,g.gravity),b.updateAll(o,d,h.timeScale,e,g.bounds),f=0;f0&&q.trigger(a,"collisionStart",{pairs:b.collisionStart}),b.collisionActive.length>0&&q.trigger(a,"collisionActive",{pairs:b.collisionActive}),b.collisionEnd.length>0&&q.trigger(a,"collisionEnd",{pairs:b.collisionEnd})}}();var q={};!function(){q.on=function(a,b,c){for(var d,e=b.split(" "),f=0;f0||e.force.y>0)t.set(e,!1);else{var g=Math.min(e.motion,f),h=Math.max(e.motion,f);e.motion=c*g+(1-c)*h,e.sleepThreshold>0&&e.motion=e.sleepThreshold&&t.set(e,!0)):e.sleepCounter>0&&(e.sleepCounter-=1)}}},t.afterCollisions=function(b){for(var c=0;ca&&t.set(h,!1)}}}},t.set=function(a,b){b?(a.isSleeping=!0,a.sleepCounter=a.sleepThreshold,a.positionImpulse.x=0,a.positionImpulse.y=0,a.positionPrev.x=a.position.x,a.positionPrev.y=a.position.y,a.anglePrev=a.angle,a.speed=0,a.angularSpeed=0,a.motion=0):(a.isSleeping=!1,a.sleepCounter=0)}}();var u={};!function(){u.rectangle=function(a,c,d,e,f){f=f||{};var g={label:"Rectangle Body",position:{x:a,y:c},vertices:z.fromPath("L 0 0 L "+d+" 0 L "+d+" "+e+" L 0 "+e)};if(f.chamfer){var h=f.chamfer;g.vertices=z.chamfer(g.vertices,h.radius,h.quality,h.qualityMin,h.qualityMax),delete f.chamfer}return b.create(o.extend({},g,f))},u.trapezoid=function(a,c,d,e,f,g){g=g||{},f*=.5;var h=(1-2*f)*d,i=d*f,j=i+h,k=j+i,l={label:"Trapezoid Body",position:{x:a,y:c},vertices:z.fromPath("L 0 0 L "+i+" "+-e+" L "+j+" "+-e+" L "+k+" 0")};
-if(g.chamfer){var m=g.chamfer;l.vertices=z.chamfer(l.vertices,m.radius,m.quality,m.qualityMin,m.qualityMax),delete g.chamfer}return b.create(o.extend({},l,g))},u.circle=function(a,b,c,d,e){d=d||{},d.label="Circle Body",e=e||25;var f=Math.ceil(Math.max(10,Math.min(e,c)));return f%2===1&&(f+=1),d.circleRadius=c,u.polygon(a,b,f,c,d)},u.polygon=function(a,c,d,e,f){if(f=f||{},3>d)return u.circle(a,c,e,f);for(var g=2*Math.PI/d,h="",i=.5*g,j=0;d>j;j+=1){var k=i+j*g,l=Math.cos(k)*e,m=Math.sin(k)*e;h+="L "+l.toFixed(3)+" "+m.toFixed(3)+" "}var n={label:"Polygon Body",position:{x:a,y:c},vertices:z.fromPath(h)};if(f.chamfer){var p=f.chamfer;n.vertices=z.chamfer(n.vertices,p.radius,p.quality,p.qualityMin,p.qualityMax),delete f.chamfer}return b.create(o.extend({},n,f))}}();var v={};!function(){v.stack=function(a,d,e,f,g,h,i){for(var j,k=c.create({label:"Stack"}),l=a,m=d,n=0,o=0;f>o;o++){for(var p=0,q=0;e>q;q++){var r=i(l,m,q,o,j,n);if(r){var s=r.bounds.max.y-r.bounds.min.y,t=r.bounds.max.x-r.bounds.min.x;s>p&&(p=s),b.translate(r,{x:.5*t,y:.5*s}),l=r.bounds.max.x+g,c.addBody(k,r),j=r,n+=1}}m+=p+h,l=a}return k},v.chain=function(a,b,d,e,f,g){for(var h=a.bodies,i=1;ig;g++){for(h=0;b>h;h++)h>0&&(i=l[h-1+g*b],j=l[h+g*b],c.addConstraint(a,m.create(o.extend({bodyA:i,bodyB:j},f))));for(h=0;b>h;h++)g>0&&(i=l[h+(g-1)*b],j=l[h+g*b],c.addConstraint(a,m.create(o.extend({bodyA:i,bodyB:j},f))),e&&h>0&&(k=l[h-1+(g-1)*b],c.addConstraint(a,m.create(o.extend({bodyA:k,bodyB:j},f)))),e&&b-1>h&&(k=l[h+1+(g-1)*b],c.addConstraint(a,m.create(o.extend({bodyA:k,bodyB:j},f)))))}return a.label+=" Mesh",a},v.pyramid=function(a,c,d,e,f,g,h){return v.stack(a,c,d,e,f,g,function(c,g,i,j,k,l){var m=Math.min(e,Math.ceil(d/2)),n=k?k.bounds.max.x-k.bounds.min.x:0;if(!(j>m)){j=m-j;var o=j,p=d-1-j;if(!(o>i||i>p)){1===l&&b.translate(k,{x:(i+(d%2===1?1:-1))*n,y:0});var q=k?i*n:0;return h(a+q+i*f,g,i,j,k,l)}}})},v.newtonsCradle=function(a,b,d,e,f){for(var g=c.create({label:"Newtons Cradle"}),h=0;d>h;h++){var i=1.9,j=u.circle(a+h*e*i,b+f,e,{inertia:99999,restitution:1,friction:0,frictionAir:1e-4,slop:.01}),k=m.create({pointA:{x:a+h*e*i,y:b},bodyB:j});c.addBody(g,j),c.addConstraint(g,k)}return g},v.car=function(a,d,e,f,g){var h=b.nextGroupId(),i=-20,j=.5*-e+i,k=.5*e-i,l=0,n=c.create({label:"Car"}),o=u.trapezoid(a,d,e,f,.3,{groupId:h,friction:.01,chamfer:{radius:10}}),p=u.circle(a+j,d+l,g,{groupId:h,restitution:.5,friction:.9,density:.01}),q=u.circle(a+k,d+l,g,{groupId:h,restitution:.5,friction:.9,density:.01}),r=m.create({bodyA:o,pointA:{x:j,y:l},bodyB:p,stiffness:.5}),s=m.create({bodyA:o,pointA:{x:k,y:l},bodyB:q,stiffness:.5});return c.addBody(n,o),c.addBody(n,p),c.addBody(n,q),c.addConstraint(n,r),c.addConstraint(n,s),n},v.softBody=function(a,b,c,d,e,f,g,h,i,j){i=o.extend({inertia:1/0},i),j=o.extend({stiffness:.4},j);var k=v.stack(a,b,c,d,e,f,function(a,b){return u.circle(a,b,h,i)});return v.mesh(k,c,d,g,j),k.label="Soft Body",k}}();var w={};!function(){w.fromVertices=function(a){for(var b={},c=0;ca.max.x&&(a.max.x=e.x),e.xa.max.y&&(a.max.y=e.y),e.y0?a.max.x+=c.x:a.min.x+=c.x,c.y>0?a.max.y+=c.y:a.min.y+=c.y)},x.contains=function(a,b){return b.x>=a.min.x&&b.x<=a.max.x&&b.y>=a.min.y&&b.y<=a.max.y},x.overlaps=function(a,b){return a.min.x<=b.max.x&&a.max.x>=b.min.x&&a.max.y>=b.min.y&&a.min.y<=b.max.y},x.translate=function(a,b){a.min.x+=b.x,a.max.x+=b.x,a.min.y+=b.y,a.max.y+=b.y},x.shift=function(a,b){var c=a.max.x-a.min.x,d=a.max.y-a.min.y;a.min.x=b.x,a.max.x=b.x+c,a.min.y=b.y,a.max.y=b.y+d}}();var y={};!function(){y.magnitude=function(a){return Math.sqrt(a.x*a.x+a.y*a.y)},y.magnitudeSquared=function(a){return a.x*a.x+a.y*a.y},y.rotate=function(a,b){var c=Math.cos(b),d=Math.sin(b);return{x:a.x*c-a.y*d,y:a.x*d+a.y*c}},y.rotateAbout=function(a,b,c){var d=Math.cos(b),e=Math.sin(b);return{x:c.x+((a.x-c.x)*d-(a.y-c.y)*e),y:c.y+((a.x-c.x)*e+(a.y-c.y)*d)}},y.normalise=function(a){var b=y.magnitude(a);return 0===b?{x:0,y:0}:{x:a.x/b,y:a.y/b}},y.dot=function(a,b){return a.x*b.x+a.y*b.y},y.cross=function(a,b){return a.x*b.y-a.y*b.x},y.add=function(a,b){return{x:a.x+b.x,y:a.y+b.y}},y.sub=function(a,b){return{x:a.x-b.x,y:a.y-b.y}},y.mult=function(a,b){return{x:a.x*b,y:a.y*b}},y.div=function(a,b){return{x:a.x/b,y:a.y/b}},y.perp=function(a,b){return b=b===!0?-1:1,{x:b*-a.y,y:b*a.x}},y.neg=function(a){return{x:-a.x,y:-a.y}},y.angle=function(a,b){return Math.atan2(b.y-a.y,b.x-a.x)}}();var z={};!function(){z.create=function(a,b){for(var c=0;c0)return!1}return!0},z.scale=function(a,b,c,d){if(1===b&&1===c)return a;d=d||z.centre(a);for(var e,f,g=0;g=0?g-1:a.length-1],i=a[g],j=a[(g+1)%a.length],k=b[gv;v++)f.push(y.add(y.rotate(p,u*v),r))}else f.push(i)}return f}}();var A={};!function(){A.create=function(b){var c={controller:A,element:null,canvas:null,options:{width:800,height:600,background:"#fafafa",wireframeBackground:"#222",hasBounds:!1,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showShadows:!1}},d=o.extend(c,b);return d.canvas=d.canvas||a(d.options.width,d.options.height),d.context=d.canvas.getContext("2d"),d.textures={},d.bounds=d.bounds||{min:{x:0,y:0},max:{x:d.options.width,y:d.options.height}},A.setBackground(d,d.options.background),o.isElement(d.element)?d.element.appendChild(d.canvas):o.log('No "render.element" passed, "render.canvas" was not inserted into document.',"warn"),d},A.clear=function(){},A.setBackground=function(a,b){if(a.currentBackground!==b){var c=b;/(jpg|gif|png)$/.test(b)&&(c="url("+b+")"),a.canvas.style.background=c,a.canvas.style.backgroundSize="contain",a.currentBackground=b}},A.world=function(a){var b,d=a.render,e=a.world,f=d.canvas,g=d.context,h=d.options,i=c.allBodies(e),j=c.allConstraints(e),k=[],l=[];h.wireframes?A.setBackground(d,h.wireframeBackground):A.setBackground(d,h.background),g.globalCompositeOperation="source-in",g.fillStyle="transparent",g.fillRect(0,0,f.width,f.height),g.globalCompositeOperation="source-over";var m=d.bounds.max.x-d.bounds.min.x,n=d.bounds.max.y-d.bounds.min.y,o=m/d.options.width,p=n/d.options.height;if(h.hasBounds){for(b=0;b=500){var k="";k+="fps: "+Math.round(a.timing.fps)+j,a.metrics.extended&&(k+="delta: "+a.timing.delta.toFixed(3)+j,k+="correction: "+a.timing.correction.toFixed(3)+j,k+="bodies: "+i.length+j,a.broadphase.controller===g&&(k+="buckets: "+a.metrics.buckets+j),k+="\n",k+="collisions: "+a.metrics.collisions+j,k+="pairs: "+a.pairs.list.length+j,k+="broad: "+a.metrics.broadEff+j,k+="mid: "+a.metrics.midEff+j,k+="narrow: "+a.metrics.narrowEff+j),f.debugString=k,f.debugTimestamp=a.timing.timestamp}if(f.debugString){d.font="12px Arial",d.fillStyle=h.wireframes?"rgba(255,255,255,0.5)":"rgba(0,0,0,0.5)";for(var l=f.debugString.split("\n"),m=0;m0){var l=d.activeContacts[0].vertex.x,m=d.activeContacts[0].vertex.y;2===d.activeContacts.length&&(l=(d.activeContacts[0].vertex.x+d.activeContacts[1].vertex.x)/2,m=(d.activeContacts[0].vertex.y+d.activeContacts[1].vertex.y)/2),h.moveTo(l-8*e.normal.x,m-8*e.normal.y),h.lineTo(l,m)}h.strokeStyle=i.wireframes?"rgba(255,165,0,0.7)":"orange",h.lineWidth=1,h.stroke()},A.grid=function(a,b,c){var d=c,e=a.render.options;d.strokeStyle=e.wireframes?"rgba(255,180,0,0.1)":"rgba(255,180,0,0.5)",d.beginPath();for(var f=o.keys(b.buckets),g=0;gf.max.x||h.bounds.max.yf.max.y||b.update(h,c,d,e)}},b.update=function(a,b,c,d){var e=Math.pow(b*c*a.timeScale,2),f=1-a.frictionAir*c*a.timeScale,g=a.position.x-a.positionPrev.x,h=a.position.y-a.positionPrev.y;a.velocity.x=g*f*d+a.force.x/a.mass*e,a.velocity.y=h*f*d+a.force.y/a.mass*e,a.positionPrev.x=a.position.x,a.positionPrev.y=a.position.y,a.position.x+=a.velocity.x,a.position.y+=a.velocity.y,a.angularVelocity=(a.angle-a.anglePrev)*f*d+a.torque/a.inertia*e,a.anglePrev=a.angle,a.angle+=a.angularVelocity,a.speed=y.magnitude(a.velocity),a.angularSpeed=Math.abs(a.angularVelocity),z.translate(a.vertices,a.velocity),0!==a.angularVelocity&&(z.rotate(a.vertices,a.angularVelocity,a.position),w.rotate(a.axes,a.angularVelocity)),x.update(a.bounds,a.vertices,a.velocity)},b.applyForce=function(a,b,c){a.force.x+=c.x,a.force.y+=c.y;var d={x:b.x-a.position.x,y:b.y-a.position.y};a.torque+=(d.x*c.y-d.y*c.x)*a.inverseInertia}}();var c={};!function(){c.create=function(a){return o.extend({id:o.nextId(),type:"composite",parent:null,isModified:!1,bodies:[],constraints:[],composites:[],label:"Composite"},a)},c.setModified=function(a,b,d,e){if(a.isModified=b,d&&a.parent&&c.setModified(a.parent,b,d,e),e)for(var f=0;fq.bounds.width||u.bounds.max.y<0||u.bounds.min.y>q.bounds.height)){var v=b(c,u);if(!u.region||v.id!==u.region.id||k){s.broadphaseTests+=1,(!u.region||k)&&(u.region=v);var w=a(v,u.region);for(m=w.startCol;m<=w.endCol;m++)for(n=w.startRow;n<=w.endRow;n++){p=d(m,n),o=r[p];var x=m>=v.startCol&&m<=v.endCol&&n>=v.startRow&&n<=v.endRow,y=m>=u.region.startCol&&m<=u.region.endCol&&n>=u.region.startRow&&n<=u.region.endRow;!x&&y&&y&&o&&i(c,o,u),(u.region===v||x&&!y||k)&&(o||(o=e(r,p)),f(c,o,u))}u.region=v,t=!0}}}t&&(c.pairsList=j(c))},g.clear=function(a){a.buckets={},a.pairs={},a.pairsList=[]};var a=function(a,b){var d=Math.min(a.startCol,b.startCol),e=Math.max(a.endCol,b.endCol),f=Math.min(a.startRow,b.startRow),g=Math.max(a.endRow,b.endRow);return c(d,e,f,g)},b=function(a,b){var d=b.bounds,e=Math.floor(d.min.x/a.bucketWidth),f=Math.floor(d.max.x/a.bucketWidth),g=Math.floor(d.min.y/a.bucketHeight),h=Math.floor(d.max.y/a.bucketHeight);return c(e,f,g,h)},c=function(a,b,c,d){return{id:a+","+b+","+c+","+d,startCol:a,endCol:b,startRow:c,endRow:d}},d=function(a,b){return a+","+b},e=function(a,b){var c=a[b]=[];return c},f=function(a,b,c){for(var d=0;d0?d.push(c):delete a.pairs[b[e]];return d}}();var h={};!function(){h.create=function(a,b){var c=a.bodyA,d=a.bodyB,e={id:h.id(c,d),bodyA:c,bodyB:d,contacts:{},activeContacts:[],separation:0,isActive:!0,timeCreated:b,timeUpdated:b,inverseMass:c.inverseMass+d.inverseMass,friction:Math.min(c.friction,d.friction),restitution:Math.max(c.restitution,d.restitution),slop:Math.max(c.slop,d.slop)};return h.update(e,a,b),e},h.update=function(a,b,c){var d=a.contacts,f=b.supports,g=a.activeContacts;if(a.collision=b,g.length=0,b.collided){for(var i=0;ia&&j.push(g);for(g=0;gD*g.friction*e&&(E=D*g.friction*e*B);var F=y.cross(s,k),G=y.cross(t,k),H=n/(g.inverseMass+i.inverseInertia*F*F+j.inverseInertia*G*G);if(C*=H,E*=H,0>x&&x*x>a*e)q.normalImpulse=0,q.tangentImpulse=0;else{var I=q.normalImpulse;q.normalImpulse=Math.min(q.normalImpulse+C,0),C=q.normalImpulse-I;var J=q.tangentImpulse;q.tangentImpulse=o.clamp(q.tangentImpulse+E,-A,A),E=q.tangentImpulse-J}d.x=k.x*C+l.x*E,d.y=k.y*C+l.y*E,i.isStatic||i.isSleeping||(i.positionPrev.x+=d.x*i.inverseMass,i.positionPrev.y+=d.y*i.inverseMass,i.anglePrev+=y.cross(s,d)*i.inverseInertia),j.isStatic||j.isSleeping||(j.positionPrev.x-=d.x*j.inverseMass,j.positionPrev.y-=d.y*j.inverseMass,j.anglePrev-=y.cross(t,d)*j.inverseInertia)}}}}}();var l={};!function(){l.collides=function(b,d,e){var f,g,h,i,j=e,k=!1;if(j){var l=b.speed*b.speed+b.angularSpeed*b.angularSpeed+d.speed*d.speed+d.angularSpeed*d.angularSpeed;k=j&&j.collided&&.2>l,i=j}else i={collided:!1,bodyA:b,bodyB:d};if(j&&k){var m=[j.bodyA.axes[j.axisNumber]];if(h=a(j.bodyA.vertices,j.bodyB.vertices,m),i.reused=!0,h.overlap<=0)return i.collided=!1,i}else{if(f=a(b.vertices,d.vertices,b.axes),f.overlap<=0)return i.collided=!1,i;if(g=a(d.vertices,b.vertices,d.axes),g.overlap<=0)return i.collided=!1,i;f.overlap0&&(i.normal=y.neg(i.normal)),i.tangent=y.perp(i.normal),i.penetration={x:i.normal.x*i.depth,y:i.normal.y*i.depth};var n=c(b,d,i.normal),o=[n[0]];if(z.contains(b.vertices,n[1]))o.push(n[1]);else{var p=c(d,b,y.neg(i.normal));z.contains(d.vertices,p[0])&&o.push(p[0]),o.length<2&&z.contains(d.vertices,p[1])&&o.push(p[1])}return i.supports=o,i.supportCorrected=y.sub(n[0],i.penetration),i};var a=function(a,c,d){for(var e,f,g={},h={},i={overlap:Number.MAX_VALUE},j=0;j=e)return i.overlap=e,i;ee?e=g:d>g&&(d=g)}a.min=d,a.max=e},c=function(a,b,c){for(var d,e,f=Number.MAX_VALUE,g={x:0,y:0},h=b.vertices,i=a.position,j=h[0],k=h[1],l=0;ld&&(f=d,j=e);var m=j.index-1>=0?j.index-1:h.length-1;e=h[m],g.x=e.x-i.x,g.y=e.y-i.y,f=-y.dot(c,g),k=e;var n=(j.index+1)%h.length;return e=h[n],g.x=e.x-i.x,g.y=e.y-i.y,d=-y.dot(c,g),f>d&&(f=d,k=e),[j,k]}}();var m={};!function(){var a=1e-6,b=.001;m.create=function(b){var c=b;c.bodyA&&!c.pointA&&(c.pointA={x:0,y:0}),c.bodyB&&!c.pointB&&(c.pointB={x:0,y:0});var d=c.bodyA?y.add(c.bodyA.position,c.pointA):c.pointA,e=c.bodyB?y.add(c.bodyB.position,c.pointB):c.pointB,f=y.magnitude(y.sub(d,e));c.length=c.length||f||a;var g={visible:!0,lineWidth:2,strokeStyle:"#666"};return c.render=o.extend(g,c.render),c.id=c.id||o.nextId(),c.label=c.label||"Constraint",c.type="constraint",c.stiffness=c.stiffness||1,c.angularStiffness=c.angularStiffness||0,c.angleA=c.bodyA?c.bodyA.angle:c.angleA,c.angleB=c.bodyB?c.bodyB.angle:c.angleB,c},m.solveAll=function(a,b){for(var c=0;c0&&(B=0);var C,D={x:n.x*B,y:n.y*B};e&&!e.isStatic&&(C=y.cross(s,D)*e.inverseInertia*(1-c.angularStiffness),t.set(e,!1),C=o.clamp(C,-.01,.01),e.constraintImpulse.x-=p.x,e.constraintImpulse.y-=p.y,e.constraintImpulse.angle+=C,e.position.x-=p.x,e.position.y-=p.y,e.angle+=C),f&&!f.isStatic&&(C=y.cross(u,D)*f.inverseInertia*(1-c.angularStiffness),t.set(f,!1),C=o.clamp(C,-.01,.01),f.constraintImpulse.x+=p.x,f.constraintImpulse.y+=p.y,f.constraintImpulse.angle-=C,f.position.x+=p.x,f.position.y+=p.y,f.angle-=C)}}},m.postSolveAll=function(a){for(var b=0;b>16)+d,f=(c>>8&255)+d,g=(255&c)+d;return"#"+(16777216+65536*(255>e?1>e?0:e:255)+256*(255>f?1>f?0:f:255)+(255>g?1>g?0:g:255)).toString(16).slice(1)},o.shuffle=function(a){for(var b=a.length-1;b>0;b--){var c=Math.floor(o.random()*(b+1)),d=a[b];a[b]=a[c],a[c]=d}return a},o.choose=function(a){return a[Math.floor(o.random()*a.length)]},o.isElement=function(a){try{return a instanceof HTMLElement}catch(b){return"object"==typeof a&&1===a.nodeType&&"object"==typeof a.style&&"object"==typeof a.ownerDocument}},o.clamp=function(a,b,c){return b>a?b:a>c?c:a},o.sign=function(a){return 0>a?-1:1},o.now=function(){var a=window.performance;return a?(a.now=a.now||a.webkitNow||a.msNow||a.oNow||a.mozNow,+a.now()):+new Date},o.random=function(b,c){return b="undefined"!=typeof b?b:0,c="undefined"!=typeof c?c:1,b+a()*(c-b)},o.colorToNumber=function(a){return a=a.replace("#",""),3==a.length&&(a=a.charAt(0)+a.charAt(0)+a.charAt(1)+a.charAt(1)+a.charAt(2)+a.charAt(2)),parseInt(a,16)},o.log=function(a,b){if(console&&console.log){var c;switch(b){case"warn":c="color: coral";break;case"error":c="color: red"}console.log("%c [Matter] "+b+": "+a,c)}},o.nextId=function(){return o._nextId++};var a=function(){return o._seed=(9301*o._seed+49297)%233280,o._seed/233280}}();var p={};!function(){var a=60,e=a,h=1e3/a,j=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(function(){a(o.now())},h)};p.create=function(b,c){c=o.isElement(b)?c:b,b=o.isElement(b)?b:null;var e={enabled:!0,positionIterations:6,velocityIterations:4,constraintIterations:2,enableSleeping:!1,timeScale:1,input:{},events:[],timing:{fps:a,timestamp:0,delta:h,correction:1,deltaMin:1e3/a,deltaMax:1e3/(.5*a),timeScale:1,isFixed:!1},render:{element:b,controller:A}},j=o.extend(e,c);return j.render=j.render.controller.create(j.render),j.world=d.create(j.world),j.pairs=i.create(),j.metrics=j.metrics||r.create(),j.input.mouse=j.input.mouse||s.create(j.render.canvas),j.broadphase=j.broadphase||{current:"grid",grid:{controller:g,instance:g.create(),detector:f.collisions},bruteForce:{detector:f.bruteForce}},j},p.run=function(a){var b,c=0,d=0,f=[],g=1;!function h(i){if(j(h),a.enabled){var k,m,o=a.timing,r={timestamp:i};q.trigger(a,"beforeTick",r),o.isFixed?k=o.delta:(k=i-b||o.delta,b=i,f.push(k),f=f.slice(-e),k=Math.min.apply(null,f),k=ko.deltaMax?o.deltaMax:k,m=k/o.delta,o.delta=k),0!==g&&(m*=o.timeScale/g),0===o.timeScale&&(m=0),g=o.timeScale,d+=1,i-c>=1e3&&(o.fps=d*((i-c)/1e3),c=i,d=0),q.trigger(a,"tick",r),a.world.isModified&&a.render.controller.clear(a.render),p.update(a,k,m),n(a),l(a),p.render(a),q.trigger(a,"afterTick",r)}}()},p.update=function(a,d,e){e="undefined"!=typeof e?e:1;var f,g=a.world,h=a.timing,j=a.broadphase[a.broadphase.current],l=[];h.timestamp+=d*h.timeScale,h.correction=e;var n={timestamp:a.timing.timestamp};q.trigger(a,"beforeUpdate",n);var o=c.allBodies(g),p=c.allConstraints(g);for(r.reset(a.metrics),a.enableSleeping&&t.update(o),b.applyGravityAll(o,g.gravity),b.updateAll(o,d,h.timeScale,e,g.bounds),f=0;f0&&q.trigger(a,"collisionStart",{pairs:b.collisionStart}),b.collisionActive.length>0&&q.trigger(a,"collisionActive",{pairs:b.collisionActive}),b.collisionEnd.length>0&&q.trigger(a,"collisionEnd",{pairs:b.collisionEnd})}}();var q={};!function(){q.on=function(a,b,c){for(var d,e=b.split(" "),f=0;f0||e.force.y>0)t.set(e,!1);else{var g=Math.min(e.motion,f),h=Math.max(e.motion,f);e.motion=c*g+(1-c)*h,e.sleepThreshold>0&&e.motion=e.sleepThreshold&&t.set(e,!0)):e.sleepCounter>0&&(e.sleepCounter-=1)}}},t.afterCollisions=function(b){for(var c=0;ca&&t.set(h,!1)}}}},t.set=function(a,b){b?(a.isSleeping=!0,a.sleepCounter=a.sleepThreshold,a.positionImpulse.x=0,a.positionImpulse.y=0,a.positionPrev.x=a.position.x,a.positionPrev.y=a.position.y,a.anglePrev=a.angle,a.speed=0,a.angularSpeed=0,a.motion=0):(a.isSleeping=!1,a.sleepCounter=0)}}();var u={};!function(){u.rectangle=function(a,c,d,e,f){f=f||{};var g={label:"Rectangle Body",position:{x:a,y:c},vertices:z.fromPath("L 0 0 L "+d+" 0 L "+d+" "+e+" L 0 "+e)};if(f.chamfer){var h=f.chamfer;g.vertices=z.chamfer(g.vertices,h.radius,h.quality,h.qualityMin,h.qualityMax),delete f.chamfer}return b.create(o.extend({},g,f))},u.trapezoid=function(a,c,d,e,f,g){g=g||{},f*=.5;var h=(1-2*f)*d,i=d*f,j=i+h,k=j+i,l={label:"Trapezoid Body",position:{x:a,y:c},vertices:z.fromPath("L 0 0 L "+i+" "+-e+" L "+j+" "+-e+" L "+k+" 0")};if(g.chamfer){var m=g.chamfer;l.vertices=z.chamfer(l.vertices,m.radius,m.quality,m.qualityMin,m.qualityMax),delete g.chamfer}return b.create(o.extend({},l,g))},u.circle=function(a,b,c,d,e){d=d||{},d.label="Circle Body",e=e||25;var f=Math.ceil(Math.max(10,Math.min(e,c)));return f%2===1&&(f+=1),d.circleRadius=c,u.polygon(a,b,f,c,d)},u.polygon=function(a,c,d,e,f){if(f=f||{},3>d)return u.circle(a,c,e,f);for(var g=2*Math.PI/d,h="",i=.5*g,j=0;d>j;j+=1){var k=i+j*g,l=Math.cos(k)*e,m=Math.sin(k)*e;h+="L "+l.toFixed(3)+" "+m.toFixed(3)+" "}var n={label:"Polygon Body",position:{x:a,y:c},vertices:z.fromPath(h)};if(f.chamfer){var p=f.chamfer;n.vertices=z.chamfer(n.vertices,p.radius,p.quality,p.qualityMin,p.qualityMax),delete f.chamfer}return b.create(o.extend({},n,f))}}();var v={};!function(){v.stack=function(a,d,e,f,g,h,i){for(var j,k=c.create({label:"Stack"}),l=a,m=d,n=0,o=0;f>o;o++){for(var p=0,q=0;e>q;q++){var r=i(l,m,q,o,j,n);if(r){var s=r.bounds.max.y-r.bounds.min.y,t=r.bounds.max.x-r.bounds.min.x;s>p&&(p=s),b.translate(r,{x:.5*t,y:.5*s}),l=r.bounds.max.x+g,c.addBody(k,r),j=r,n+=1}}m+=p+h,l=a}return k},v.chain=function(a,b,d,e,f,g){for(var h=a.bodies,i=1;ig;g++){for(h=0;b>h;h++)h>0&&(i=l[h-1+g*b],j=l[h+g*b],c.addConstraint(a,m.create(o.extend({bodyA:i,bodyB:j},f))));for(h=0;b>h;h++)g>0&&(i=l[h+(g-1)*b],j=l[h+g*b],c.addConstraint(a,m.create(o.extend({bodyA:i,bodyB:j},f))),e&&h>0&&(k=l[h-1+(g-1)*b],c.addConstraint(a,m.create(o.extend({bodyA:k,bodyB:j},f)))),e&&b-1>h&&(k=l[h+1+(g-1)*b],c.addConstraint(a,m.create(o.extend({bodyA:k,bodyB:j},f)))))}return a.label+=" Mesh",a},v.pyramid=function(a,c,d,e,f,g,h){return v.stack(a,c,d,e,f,g,function(c,g,i,j,k,l){var m=Math.min(e,Math.ceil(d/2)),n=k?k.bounds.max.x-k.bounds.min.x:0;if(!(j>m)){j=m-j;var o=j,p=d-1-j;if(!(o>i||i>p)){1===l&&b.translate(k,{x:(i+(d%2===1?1:-1))*n,y:0});var q=k?i*n:0;return h(a+q+i*f,g,i,j,k,l)}}})},v.newtonsCradle=function(a,b,d,e,f){for(var g=c.create({label:"Newtons Cradle"}),h=0;d>h;h++){var i=1.9,j=u.circle(a+h*e*i,b+f,e,{inertia:99999,restitution:1,friction:0,frictionAir:1e-4,slop:.01}),k=m.create({pointA:{x:a+h*e*i,y:b},bodyB:j});c.addBody(g,j),c.addConstraint(g,k)}return g},v.car=function(a,d,e,f,g){var h=b.nextGroupId(),i=-20,j=.5*-e+i,k=.5*e-i,l=0,n=c.create({label:"Car"}),o=u.trapezoid(a,d,e,f,.3,{groupId:h,friction:.01,chamfer:{radius:10}}),p=u.circle(a+j,d+l,g,{groupId:h,restitution:.5,friction:.9,density:.01}),q=u.circle(a+k,d+l,g,{groupId:h,restitution:.5,friction:.9,density:.01}),r=m.create({bodyA:o,pointA:{x:j,y:l},bodyB:p,stiffness:.5}),s=m.create({bodyA:o,pointA:{x:k,y:l},bodyB:q,stiffness:.5});return c.addBody(n,o),c.addBody(n,p),c.addBody(n,q),c.addConstraint(n,r),c.addConstraint(n,s),n},v.softBody=function(a,b,c,d,e,f,g,h,i,j){i=o.extend({inertia:1/0},i),j=o.extend({stiffness:.4},j);var k=v.stack(a,b,c,d,e,f,function(a,b){return u.circle(a,b,h,i)});return v.mesh(k,c,d,g,j),k.label="Soft Body",k}}();var w={};!function(){w.fromVertices=function(a){for(var b={},c=0;ca.max.x&&(a.max.x=e.x),e.xa.max.y&&(a.max.y=e.y),e.y0?a.max.x+=c.x:a.min.x+=c.x,c.y>0?a.max.y+=c.y:a.min.y+=c.y)},x.contains=function(a,b){return b.x>=a.min.x&&b.x<=a.max.x&&b.y>=a.min.y&&b.y<=a.max.y},x.overlaps=function(a,b){return a.min.x<=b.max.x&&a.max.x>=b.min.x&&a.max.y>=b.min.y&&a.min.y<=b.max.y},x.translate=function(a,b){a.min.x+=b.x,a.max.x+=b.x,a.min.y+=b.y,a.max.y+=b.y},x.shift=function(a,b){var c=a.max.x-a.min.x,d=a.max.y-a.min.y;a.min.x=b.x,a.max.x=b.x+c,a.min.y=b.y,a.max.y=b.y+d}}();var y={};!function(){y.clone=function(a){return{x:a.x,y:a.y}},y.magnitude=function(a){return Math.sqrt(a.x*a.x+a.y*a.y)},y.magnitudeSquared=function(a){return a.x*a.x+a.y*a.y},y.rotate=function(a,b){var c=Math.cos(b),d=Math.sin(b);return{x:a.x*c-a.y*d,y:a.x*d+a.y*c}},y.rotateAbout=function(a,b,c){var d=Math.cos(b),e=Math.sin(b);return{x:c.x+((a.x-c.x)*d-(a.y-c.y)*e),y:c.y+((a.x-c.x)*e+(a.y-c.y)*d)}},y.normalise=function(a){var b=y.magnitude(a);return 0===b?{x:0,y:0}:{x:a.x/b,y:a.y/b}},y.dot=function(a,b){return a.x*b.x+a.y*b.y},y.cross=function(a,b){return a.x*b.y-a.y*b.x},y.add=function(a,b){return{x:a.x+b.x,y:a.y+b.y}},y.sub=function(a,b){return{x:a.x-b.x,y:a.y-b.y}},y.mult=function(a,b){return{x:a.x*b,y:a.y*b}},y.div=function(a,b){return{x:a.x/b,y:a.y/b}},y.perp=function(a,b){return b=b===!0?-1:1,{x:b*-a.y,y:b*a.x}},y.neg=function(a){return{x:-a.x,y:-a.y}},y.angle=function(a,b){return Math.atan2(b.y-a.y,b.x-a.x)}}();var z={};!function(){z.create=function(a,b){for(var c=[],d=0;d0)return!1}return!0},z.scale=function(a,b,c,d){if(1===b&&1===c)return a;d=d||z.centre(a);for(var e,f,g=0;g=0?g-1:a.length-1],i=a[g],j=a[(g+1)%a.length],k=b[gv;v++)f.push(y.add(y.rotate(p,u*v),r))}else f.push(i)}return f}}();var A={};!function(){A.create=function(b){var c={controller:A,element:null,canvas:null,options:{width:800,height:600,background:"#fafafa",wireframeBackground:"#222",hasBounds:!1,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showShadows:!1}},d=o.extend(c,b);return d.canvas=d.canvas||a(d.options.width,d.options.height),d.context=d.canvas.getContext("2d"),d.textures={},d.bounds=d.bounds||{min:{x:0,y:0},max:{x:d.options.width,y:d.options.height}},A.setBackground(d,d.options.background),o.isElement(d.element)?d.element.appendChild(d.canvas):o.log('No "render.element" passed, "render.canvas" was not inserted into document.',"warn"),d},A.clear=function(){},A.setBackground=function(a,b){if(a.currentBackground!==b){var c=b;/(jpg|gif|png)$/.test(b)&&(c="url("+b+")"),a.canvas.style.background=c,a.canvas.style.backgroundSize="contain",a.currentBackground=b}},A.world=function(a){var b,d=a.render,e=a.world,f=d.canvas,g=d.context,h=d.options,i=c.allBodies(e),j=c.allConstraints(e),k=[],l=[];h.wireframes?A.setBackground(d,h.wireframeBackground):A.setBackground(d,h.background),g.globalCompositeOperation="source-in",g.fillStyle="transparent",g.fillRect(0,0,f.width,f.height),g.globalCompositeOperation="source-over";var m=d.bounds.max.x-d.bounds.min.x,n=d.bounds.max.y-d.bounds.min.y,o=m/d.options.width,p=n/d.options.height;if(h.hasBounds){for(b=0;b=500){var k="";k+="fps: "+Math.round(a.timing.fps)+j,a.metrics.extended&&(k+="delta: "+a.timing.delta.toFixed(3)+j,k+="correction: "+a.timing.correction.toFixed(3)+j,k+="bodies: "+i.length+j,a.broadphase.controller===g&&(k+="buckets: "+a.metrics.buckets+j),k+="\n",k+="collisions: "+a.metrics.collisions+j,k+="pairs: "+a.pairs.list.length+j,k+="broad: "+a.metrics.broadEff+j,k+="mid: "+a.metrics.midEff+j,k+="narrow: "+a.metrics.narrowEff+j),f.debugString=k,f.debugTimestamp=a.timing.timestamp}if(f.debugString){d.font="12px Arial",d.fillStyle=h.wireframes?"rgba(255,255,255,0.5)":"rgba(0,0,0,0.5)";for(var l=f.debugString.split("\n"),m=0;m0){var l=d.activeContacts[0].vertex.x,m=d.activeContacts[0].vertex.y;2===d.activeContacts.length&&(l=(d.activeContacts[0].vertex.x+d.activeContacts[1].vertex.x)/2,m=(d.activeContacts[0].vertex.y+d.activeContacts[1].vertex.y)/2),h.moveTo(l-8*e.normal.x,m-8*e.normal.y),h.lineTo(l,m)}h.strokeStyle=i.wireframes?"rgba(255,165,0,0.7)":"orange",h.lineWidth=1,h.stroke()},A.grid=function(a,b,c){var d=c,e=a.render.options;d.strokeStyle=e.wireframes?"rgba(255,180,0,0.1)":"rgba(255,180,0,0.5)",d.beginPath();for(var f=o.keys(b.buckets),g=0;g