mirror of
https://github.com/liabru/matter-js.git
synced 2024-11-30 10:20:52 -05:00
Added readonly body.deltaTime
Added delta property to engine update event Added delta argument to various internal functions Changed timeScale argument to use delta instead on various internal functions Fixed issues when using an engine update delta of 0 Improved time independence for friction, air friction, restitution, sleeping, collisions, constraints Removed optional correction argument from Engine.update Removed correction and timeScale from Body.update and Matter.Runner
This commit is contained in:
parent
2ec247b7af
commit
0784a5b5df
9 changed files with 114 additions and 107 deletions
|
@ -15,13 +15,13 @@ module.exports = Body;
|
||||||
var Vertices = require('../geometry/Vertices');
|
var Vertices = require('../geometry/Vertices');
|
||||||
var Vector = require('../geometry/Vector');
|
var Vector = require('../geometry/Vector');
|
||||||
var Sleeping = require('../core/Sleeping');
|
var Sleeping = require('../core/Sleeping');
|
||||||
var Render = require('../render/Render');
|
|
||||||
var Common = require('../core/Common');
|
var Common = require('../core/Common');
|
||||||
var Bounds = require('../geometry/Bounds');
|
var Bounds = require('../geometry/Bounds');
|
||||||
var Axes = require('../geometry/Axes');
|
var Axes = require('../geometry/Axes');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
Body._timeCorrection = true;
|
||||||
Body._inertiaScale = 4;
|
Body._inertiaScale = 4;
|
||||||
Body._nextCollidingGroupId = 1;
|
Body._nextCollidingGroupId = 1;
|
||||||
Body._nextNonCollidingGroupId = -1;
|
Body._nextNonCollidingGroupId = -1;
|
||||||
|
@ -95,6 +95,7 @@ var Axes = require('../geometry/Axes');
|
||||||
area: 0,
|
area: 0,
|
||||||
mass: 0,
|
mass: 0,
|
||||||
inertia: 0,
|
inertia: 0,
|
||||||
|
deltaTime: null,
|
||||||
_original: null
|
_original: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -462,8 +463,8 @@ var Axes = require('../geometry/Axes');
|
||||||
*/
|
*/
|
||||||
Body.setPosition = function(body, position) {
|
Body.setPosition = function(body, position) {
|
||||||
var delta = Vector.sub(position, body.position);
|
var delta = Vector.sub(position, body.position);
|
||||||
body.positionPrev.x += delta.x;
|
body.positionPrev.x += delta.x;
|
||||||
body.positionPrev.y += delta.y;
|
body.positionPrev.y += delta.y;
|
||||||
|
|
||||||
for (var i = 0; i < body.parts.length; i++) {
|
for (var i = 0; i < body.parts.length; i++) {
|
||||||
var part = body.parts[i];
|
var part = body.parts[i];
|
||||||
|
@ -482,7 +483,7 @@ var Axes = require('../geometry/Axes');
|
||||||
*/
|
*/
|
||||||
Body.setAngle = function(body, angle) {
|
Body.setAngle = function(body, angle) {
|
||||||
var delta = angle - body.angle;
|
var delta = angle - body.angle;
|
||||||
body.anglePrev += delta;
|
body.anglePrev += delta;
|
||||||
|
|
||||||
for (var i = 0; i < body.parts.length; i++) {
|
for (var i = 0; i < body.parts.length; i++) {
|
||||||
var part = body.parts[i];
|
var part = body.parts[i];
|
||||||
|
@ -625,26 +626,28 @@ var Axes = require('../geometry/Axes');
|
||||||
* Performs a simulation step for the given `body`, including updating position and angle using Verlet integration.
|
* Performs a simulation step for the given `body`, including updating position and angle using Verlet integration.
|
||||||
* @method update
|
* @method update
|
||||||
* @param {body} body
|
* @param {body} body
|
||||||
* @param {number} deltaTime
|
* @param {number} [deltaTime=16.666]
|
||||||
* @param {number} timeScale
|
|
||||||
* @param {number} correction
|
|
||||||
*/
|
*/
|
||||||
Body.update = function(body, deltaTime, timeScale, correction) {
|
Body.update = function(body, deltaTime) {
|
||||||
var deltaTimeSquared = Math.pow(deltaTime * timeScale * body.timeScale, 2);
|
deltaTime = (typeof deltaTime !== 'undefined' ? deltaTime : Common._timeUnit) * body.timeScale;
|
||||||
|
|
||||||
|
var deltaTimeSquared = deltaTime * deltaTime,
|
||||||
|
correction = Body._timeCorrection ? deltaTime / (body.deltaTime || deltaTime) : 1;
|
||||||
|
|
||||||
// from the previous step
|
// from the previous step
|
||||||
var frictionAir = 1 - body.frictionAir * timeScale * body.timeScale,
|
var frictionAir = 1 - body.frictionAir * (deltaTime / Common._timeUnit),
|
||||||
velocityPrevX = body.position.x - body.positionPrev.x,
|
velocityPrevX = (body.position.x - body.positionPrev.x) * correction,
|
||||||
velocityPrevY = body.position.y - body.positionPrev.y;
|
velocityPrevY = (body.position.y - body.positionPrev.y) * correction;
|
||||||
|
|
||||||
// update velocity with Verlet integration
|
// update velocity with Verlet integration
|
||||||
body.velocity.x = (velocityPrevX * frictionAir * correction) + (body.force.x / body.mass) * deltaTimeSquared;
|
body.velocity.x = (velocityPrevX * frictionAir) + (body.force.x / body.mass) * deltaTimeSquared;
|
||||||
body.velocity.y = (velocityPrevY * frictionAir * correction) + (body.force.y / body.mass) * deltaTimeSquared;
|
body.velocity.y = (velocityPrevY * frictionAir) + (body.force.y / body.mass) * deltaTimeSquared;
|
||||||
|
|
||||||
body.positionPrev.x = body.position.x;
|
body.positionPrev.x = body.position.x;
|
||||||
body.positionPrev.y = body.position.y;
|
body.positionPrev.y = body.position.y;
|
||||||
body.position.x += body.velocity.x;
|
body.position.x += body.velocity.x;
|
||||||
body.position.y += body.velocity.y;
|
body.position.y += body.velocity.y;
|
||||||
|
body.deltaTime = deltaTime;
|
||||||
|
|
||||||
// update angular velocity with Verlet integration
|
// update angular velocity with Verlet integration
|
||||||
body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;
|
body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;
|
||||||
|
@ -880,7 +883,7 @@ var Axes = require('../geometry/Axes');
|
||||||
/**
|
/**
|
||||||
* A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only.
|
* 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).
|
* 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
|
* @readOnly
|
||||||
* @property velocity
|
* @property velocity
|
||||||
* @type vector
|
* @type vector
|
||||||
|
@ -1109,6 +1112,16 @@ var Axes = require('../geometry/Axes');
|
||||||
* @default 1
|
* @default 1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A `Number` that records the last delta time value used to update this body.
|
||||||
|
* This is automatically updated by the engine inside of `Body.update`.
|
||||||
|
*
|
||||||
|
* @readOnly
|
||||||
|
* @property deltaTime
|
||||||
|
* @type number
|
||||||
|
* @default null
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
|
* An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,9 +21,10 @@ var Bounds = require('../geometry/Bounds');
|
||||||
* @method collisions
|
* @method collisions
|
||||||
* @param {pair[]} broadphasePairs
|
* @param {pair[]} broadphasePairs
|
||||||
* @param {engine} engine
|
* @param {engine} engine
|
||||||
|
* @param {number} delta
|
||||||
* @return {array} collisions
|
* @return {array} collisions
|
||||||
*/
|
*/
|
||||||
Detector.collisions = function(broadphasePairs, engine) {
|
Detector.collisions = function(broadphasePairs, engine, delta) {
|
||||||
var collisions = [],
|
var collisions = [],
|
||||||
pairsTable = engine.pairs.table;
|
pairsTable = engine.pairs.table;
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ var Bounds = require('../geometry/Bounds');
|
||||||
}
|
}
|
||||||
|
|
||||||
// narrow phase
|
// narrow phase
|
||||||
var collision = SAT.collides(partA, partB, previousCollision);
|
var collision = SAT.collides(partA, partB, previousCollision, delta);
|
||||||
|
|
||||||
// @if DEBUG
|
// @if DEBUG
|
||||||
metrics.narrowphaseTests += 1;
|
metrics.narrowphaseTests += 1;
|
||||||
|
|
|
@ -49,9 +49,9 @@ var Bounds = require('../geometry/Bounds');
|
||||||
* @method solvePosition
|
* @method solvePosition
|
||||||
* @param {pair[]} pairs
|
* @param {pair[]} pairs
|
||||||
* @param {body[]} bodies
|
* @param {body[]} bodies
|
||||||
* @param {number} timeScale
|
* @param {number} delta
|
||||||
*/
|
*/
|
||||||
Resolver.solvePosition = function(pairs, bodies, timeScale) {
|
Resolver.solvePosition = function(pairs, bodies, delta) {
|
||||||
var i,
|
var i,
|
||||||
normalX,
|
normalX,
|
||||||
normalY,
|
normalY,
|
||||||
|
@ -68,7 +68,8 @@ var Bounds = require('../geometry/Bounds');
|
||||||
bodyBtoAX,
|
bodyBtoAX,
|
||||||
bodyBtoAY,
|
bodyBtoAY,
|
||||||
positionImpulse,
|
positionImpulse,
|
||||||
impulseCoefficient = timeScale * Resolver._positionDampen;
|
timeScale = delta / Common._timeUnit,
|
||||||
|
impulseCoefficient = Resolver._positionDampen * timeScale;
|
||||||
|
|
||||||
for (i = 0; i < bodies.length; i++) {
|
for (i = 0; i < bodies.length; i++) {
|
||||||
var body = bodies[i];
|
var body = bodies[i];
|
||||||
|
@ -231,10 +232,12 @@ var Bounds = require('../geometry/Bounds');
|
||||||
* Find a solution for pair velocities.
|
* Find a solution for pair velocities.
|
||||||
* @method solveVelocity
|
* @method solveVelocity
|
||||||
* @param {pair[]} pairs
|
* @param {pair[]} pairs
|
||||||
* @param {number} timeScale
|
* @param {number} delta
|
||||||
*/
|
*/
|
||||||
Resolver.solveVelocity = function(pairs, timeScale) {
|
Resolver.solveVelocity = function(pairs, delta) {
|
||||||
var timeScaleSquared = timeScale * timeScale,
|
var timeScale = delta / Common._timeUnit,
|
||||||
|
timeScale2 = timeScale * timeScale,
|
||||||
|
timeScale3 = timeScale2 * timeScale,
|
||||||
impulse = Vector._temp[0],
|
impulse = Vector._temp[0],
|
||||||
tempA = Vector._temp[1],
|
tempA = Vector._temp[1],
|
||||||
tempB = Vector._temp[2],
|
tempB = Vector._temp[2],
|
||||||
|
@ -287,10 +290,10 @@ var Bounds = require('../geometry/Bounds');
|
||||||
var tangentImpulse = tangentVelocity,
|
var tangentImpulse = tangentVelocity,
|
||||||
maxFriction = Infinity;
|
maxFriction = Infinity;
|
||||||
|
|
||||||
if (tangentSpeed > pair.friction * pair.frictionStatic * normalForce * timeScaleSquared) {
|
if (tangentSpeed > pair.friction * pair.frictionStatic * normalForce * timeScale3) {
|
||||||
maxFriction = tangentSpeed;
|
maxFriction = tangentSpeed * timeScale;
|
||||||
tangentImpulse = Common.clamp(
|
tangentImpulse = Common.clamp(
|
||||||
pair.friction * tangentVelocityDirection * timeScaleSquared,
|
pair.friction * tangentVelocityDirection * timeScale3,
|
||||||
-maxFriction, maxFriction
|
-maxFriction, maxFriction
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -304,7 +307,7 @@ var Bounds = require('../geometry/Bounds');
|
||||||
tangentImpulse *= share;
|
tangentImpulse *= share;
|
||||||
|
|
||||||
// handle high velocity and resting collisions separately
|
// handle high velocity and resting collisions separately
|
||||||
if (normalVelocity < 0 && normalVelocity * normalVelocity > Resolver._restingThresh * timeScaleSquared) {
|
if (normalVelocity < 0 && normalVelocity * normalVelocity > Resolver._restingThresh * timeScale2) {
|
||||||
// high normal velocity so clear cached contact normal impulse
|
// high normal velocity so clear cached contact normal impulse
|
||||||
contact.normalImpulse = 0;
|
contact.normalImpulse = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -316,7 +319,7 @@ var Bounds = require('../geometry/Bounds');
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle high velocity and resting collisions separately
|
// handle high velocity and resting collisions separately
|
||||||
if (tangentVelocity * tangentVelocity > Resolver._restingThreshTangent * timeScaleSquared) {
|
if (tangentVelocity * tangentVelocity > Resolver._restingThreshTangent * timeScale2) {
|
||||||
// high tangent velocity so clear cached contact tangent impulse
|
// high tangent velocity so clear cached contact tangent impulse
|
||||||
contact.tangentImpulse = 0;
|
contact.tangentImpulse = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,23 +12,30 @@ module.exports = SAT;
|
||||||
|
|
||||||
var Vertices = require('../geometry/Vertices');
|
var Vertices = require('../geometry/Vertices');
|
||||||
var Vector = require('../geometry/Vector');
|
var Vector = require('../geometry/Vector');
|
||||||
|
var Common = require('../core/Common');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
SAT._reuseMotionThresh = 0.2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect collision between two bodies using the Separating Axis Theorem.
|
* Detect collision between two bodies using the Separating Axis Theorem.
|
||||||
* @method collides
|
* @method collides
|
||||||
* @param {body} bodyA
|
* @param {body} bodyA
|
||||||
* @param {body} bodyB
|
* @param {body} bodyB
|
||||||
* @param {collision} previousCollision
|
* @param {collision} previousCollision
|
||||||
|
* @param {number} [delta=0]
|
||||||
* @return {collision} collision
|
* @return {collision} collision
|
||||||
*/
|
*/
|
||||||
SAT.collides = function(bodyA, bodyB, previousCollision) {
|
SAT.collides = function(bodyA, bodyB, previousCollision, delta) {
|
||||||
var overlapAB,
|
var overlapAB,
|
||||||
overlapBA,
|
overlapBA,
|
||||||
minOverlap,
|
minOverlap,
|
||||||
collision,
|
collision,
|
||||||
canReusePrevCol = false;
|
canReusePrevCol = false,
|
||||||
|
timeScale = delta / Common._timeUnit;
|
||||||
|
|
||||||
|
delta = typeof delta !== 'undefined' ? delta : 0;
|
||||||
|
|
||||||
if (previousCollision) {
|
if (previousCollision) {
|
||||||
// estimate total motion
|
// estimate total motion
|
||||||
|
@ -39,7 +46,7 @@ var Vector = require('../geometry/Vector');
|
||||||
|
|
||||||
// we may be able to (partially) reuse collision result
|
// we may be able to (partially) reuse collision result
|
||||||
// but only safe if collision was resting
|
// but only safe if collision was resting
|
||||||
canReusePrevCol = previousCollision && previousCollision.collided && motion < 0.2;
|
canReusePrevCol = previousCollision && previousCollision.collided && motion < SAT._reuseMotionThresh * timeScale * timeScale;
|
||||||
|
|
||||||
// reuse collision object
|
// reuse collision object
|
||||||
collision = previousCollision;
|
collision = previousCollision;
|
||||||
|
|
|
@ -110,9 +110,11 @@ var Common = require('../core/Common');
|
||||||
* @private
|
* @private
|
||||||
* @method solveAll
|
* @method solveAll
|
||||||
* @param {constraint[]} constraints
|
* @param {constraint[]} constraints
|
||||||
* @param {number} timeScale
|
* @param {number} delta
|
||||||
*/
|
*/
|
||||||
Constraint.solveAll = function(constraints, timeScale) {
|
Constraint.solveAll = function(constraints, delta) {
|
||||||
|
var timeScale = Common.clamp(delta / Common._timeUnit, 0, 1);
|
||||||
|
|
||||||
// Solve fixed constraints first.
|
// Solve fixed constraints first.
|
||||||
for (var i = 0; i < constraints.length; i += 1) {
|
for (var i = 0; i < constraints.length; i += 1) {
|
||||||
var constraint = constraints[i],
|
var constraint = constraints[i],
|
||||||
|
@ -183,7 +185,9 @@ var Common = require('../core/Common');
|
||||||
|
|
||||||
// solve distance constraint with Gauss-Siedel method
|
// solve distance constraint with Gauss-Siedel method
|
||||||
var difference = (currentLength - constraint.length) / currentLength,
|
var difference = (currentLength - constraint.length) / currentLength,
|
||||||
stiffness = constraint.stiffness < 1 ? constraint.stiffness * timeScale : constraint.stiffness,
|
isRigid = constraint.stiffness >= 1 || constraint.length === 0,
|
||||||
|
stiffness = isRigid ? constraint.stiffness : constraint.stiffness * timeScale * timeScale,
|
||||||
|
damping = constraint.damping * timeScale,
|
||||||
force = Vector.mult(delta, difference * stiffness),
|
force = Vector.mult(delta, difference * stiffness),
|
||||||
massTotal = (bodyA ? bodyA.inverseMass : 0) + (bodyB ? bodyB.inverseMass : 0),
|
massTotal = (bodyA ? bodyA.inverseMass : 0) + (bodyB ? bodyB.inverseMass : 0),
|
||||||
inertiaTotal = (bodyA ? bodyA.inverseInertia : 0) + (bodyB ? bodyB.inverseInertia : 0),
|
inertiaTotal = (bodyA ? bodyA.inverseInertia : 0) + (bodyB ? bodyB.inverseInertia : 0),
|
||||||
|
@ -193,8 +197,8 @@ var Common = require('../core/Common');
|
||||||
normal,
|
normal,
|
||||||
normalVelocity,
|
normalVelocity,
|
||||||
relativeVelocity;
|
relativeVelocity;
|
||||||
|
|
||||||
if (constraint.damping) {
|
if (damping > 0) {
|
||||||
var zero = Vector.create();
|
var zero = Vector.create();
|
||||||
normal = Vector.div(delta, currentLength);
|
normal = Vector.div(delta, currentLength);
|
||||||
|
|
||||||
|
@ -218,9 +222,9 @@ var Common = require('../core/Common');
|
||||||
bodyA.position.y -= force.y * share;
|
bodyA.position.y -= force.y * share;
|
||||||
|
|
||||||
// apply damping
|
// apply damping
|
||||||
if (constraint.damping) {
|
if (damping > 0) {
|
||||||
bodyA.positionPrev.x -= constraint.damping * normal.x * normalVelocity * share;
|
bodyA.positionPrev.x -= damping * normal.x * normalVelocity * share;
|
||||||
bodyA.positionPrev.y -= constraint.damping * normal.y * normalVelocity * share;
|
bodyA.positionPrev.y -= damping * normal.y * normalVelocity * share;
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply torque
|
// apply torque
|
||||||
|
@ -241,9 +245,9 @@ var Common = require('../core/Common');
|
||||||
bodyB.position.y += force.y * share;
|
bodyB.position.y += force.y * share;
|
||||||
|
|
||||||
// apply damping
|
// apply damping
|
||||||
if (constraint.damping) {
|
if (damping > 0) {
|
||||||
bodyB.positionPrev.x += constraint.damping * normal.x * normalVelocity * share;
|
bodyB.positionPrev.x += damping * normal.x * normalVelocity * share;
|
||||||
bodyB.positionPrev.y += constraint.damping * normal.y * normalVelocity * share;
|
bodyB.positionPrev.y += damping * normal.y * normalVelocity * share;
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply torque
|
// apply torque
|
||||||
|
|
|
@ -10,6 +10,7 @@ module.exports = Common;
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
Common._timeUnit = 1000 / 60;
|
||||||
Common._nextId = 0;
|
Common._nextId = 0;
|
||||||
Common._seed = 0;
|
Common._seed = 0;
|
||||||
Common._nowStartTime = +(new Date());
|
Common._nowStartTime = +(new Date());
|
||||||
|
|
|
@ -97,35 +97,29 @@ var Body = require('../body/Body');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the simulation forward in time by `delta` ms.
|
* Moves the simulation forward in time by `delta` ms.
|
||||||
* The `correction` argument is an optional `Number` that specifies the time correction factor to apply to the update.
|
|
||||||
* This can help improve the accuracy of the simulation in cases where `delta` is changing between updates.
|
|
||||||
* The value of `correction` is defined as `delta / lastDelta`, i.e. the percentage change of `delta` over the last step.
|
|
||||||
* Therefore the value is always `1` (no correction) when `delta` constant (or when no correction is desired, which is the default).
|
|
||||||
* See the paper on <a href="http://lonesock.net/article/verlet.html">Time Corrected Verlet</a> for more information.
|
|
||||||
*
|
|
||||||
* Triggers `beforeUpdate` and `afterUpdate` events.
|
* Triggers `beforeUpdate` and `afterUpdate` events.
|
||||||
* Triggers `collisionStart`, `collisionActive` and `collisionEnd` events.
|
* Triggers `collisionStart`, `collisionActive` and `collisionEnd` events.
|
||||||
* @method update
|
* @method update
|
||||||
* @param {engine} engine
|
* @param {engine} engine
|
||||||
* @param {number} [delta=16.666]
|
* @param {number} [delta=16.666]
|
||||||
* @param {number} [correction=1]
|
|
||||||
*/
|
*/
|
||||||
Engine.update = function(engine, delta, correction) {
|
Engine.update = function(engine, delta) {
|
||||||
delta = delta || 1000 / 60;
|
|
||||||
correction = correction || 1;
|
|
||||||
|
|
||||||
var world = engine.world,
|
var world = engine.world,
|
||||||
timing = engine.timing,
|
timing = engine.timing,
|
||||||
broadphase = engine.broadphase,
|
broadphase = engine.broadphase,
|
||||||
broadphasePairs = [],
|
broadphasePairs,
|
||||||
i;
|
i;
|
||||||
|
|
||||||
|
delta = typeof delta !== 'undefined' ? delta : Common._timeUnit;
|
||||||
|
delta *= timing.timeScale;
|
||||||
|
|
||||||
// increment timestamp
|
// increment timestamp
|
||||||
timing.timestamp += delta * timing.timeScale;
|
timing.timestamp += delta;
|
||||||
|
|
||||||
// create an event object
|
// create an event object
|
||||||
var event = {
|
var event = {
|
||||||
timestamp: timing.timestamp
|
timestamp: timing.timestamp,
|
||||||
|
delta: delta
|
||||||
};
|
};
|
||||||
|
|
||||||
Events.trigger(engine, 'beforeUpdate', event);
|
Events.trigger(engine, 'beforeUpdate', event);
|
||||||
|
@ -141,18 +135,20 @@ var Body = require('../body/Body');
|
||||||
|
|
||||||
// if sleeping enabled, call the sleeping controller
|
// if sleeping enabled, call the sleeping controller
|
||||||
if (engine.enableSleeping)
|
if (engine.enableSleeping)
|
||||||
Sleeping.update(allBodies, timing.timeScale);
|
Sleeping.update(allBodies, delta);
|
||||||
|
|
||||||
// applies gravity to all bodies
|
// applies gravity to all bodies
|
||||||
Engine._bodiesApplyGravity(allBodies, world.gravity);
|
Engine._bodiesApplyGravity(allBodies, world.gravity);
|
||||||
|
|
||||||
// update all body position and rotation by integration
|
// update all body position and rotation by integration
|
||||||
Engine._bodiesUpdate(allBodies, delta, timing.timeScale, correction, world.bounds);
|
if (delta > 0) {
|
||||||
|
Engine._bodiesUpdate(allBodies, delta);
|
||||||
|
}
|
||||||
|
|
||||||
// update all constraints (first pass)
|
// update all constraints (first pass)
|
||||||
Constraint.preSolveAll(allBodies);
|
Constraint.preSolveAll(allBodies);
|
||||||
for (i = 0; i < engine.constraintIterations; i++) {
|
for (i = 0; i < engine.constraintIterations; i++) {
|
||||||
Constraint.solveAll(allConstraints, timing.timeScale);
|
Constraint.solveAll(allConstraints, delta);
|
||||||
}
|
}
|
||||||
Constraint.postSolveAll(allBodies);
|
Constraint.postSolveAll(allBodies);
|
||||||
|
|
||||||
|
@ -176,7 +172,7 @@ var Body = require('../body/Body');
|
||||||
}
|
}
|
||||||
|
|
||||||
// narrowphase pass: find actual collisions, then create or update collision pairs
|
// narrowphase pass: find actual collisions, then create or update collision pairs
|
||||||
var collisions = broadphase.detector(broadphasePairs, engine);
|
var collisions = broadphase.detector(broadphasePairs, engine, delta);
|
||||||
|
|
||||||
// update collision pairs
|
// update collision pairs
|
||||||
var pairs = engine.pairs,
|
var pairs = engine.pairs,
|
||||||
|
@ -186,7 +182,7 @@ var Body = require('../body/Body');
|
||||||
|
|
||||||
// wake up bodies involved in collisions
|
// wake up bodies involved in collisions
|
||||||
if (engine.enableSleeping)
|
if (engine.enableSleeping)
|
||||||
Sleeping.afterCollisions(pairs.list, timing.timeScale);
|
Sleeping.afterCollisions(pairs.list, delta);
|
||||||
|
|
||||||
// trigger collision events
|
// trigger collision events
|
||||||
if (pairs.collisionStart.length > 0)
|
if (pairs.collisionStart.length > 0)
|
||||||
|
@ -195,21 +191,21 @@ var Body = require('../body/Body');
|
||||||
// iteratively resolve position between collisions
|
// iteratively resolve position between collisions
|
||||||
Resolver.preSolvePosition(pairs.list);
|
Resolver.preSolvePosition(pairs.list);
|
||||||
for (i = 0; i < engine.positionIterations; i++) {
|
for (i = 0; i < engine.positionIterations; i++) {
|
||||||
Resolver.solvePosition(pairs.list, allBodies, timing.timeScale);
|
Resolver.solvePosition(pairs.list, allBodies, delta);
|
||||||
}
|
}
|
||||||
Resolver.postSolvePosition(allBodies);
|
Resolver.postSolvePosition(allBodies);
|
||||||
|
|
||||||
// update all constraints (second pass)
|
// update all constraints (second pass)
|
||||||
Constraint.preSolveAll(allBodies);
|
Constraint.preSolveAll(allBodies);
|
||||||
for (i = 0; i < engine.constraintIterations; i++) {
|
for (i = 0; i < engine.constraintIterations; i++) {
|
||||||
Constraint.solveAll(allConstraints, timing.timeScale);
|
Constraint.solveAll(allConstraints, delta);
|
||||||
}
|
}
|
||||||
Constraint.postSolveAll(allBodies);
|
Constraint.postSolveAll(allBodies);
|
||||||
|
|
||||||
// iteratively resolve velocity between collisions
|
// iteratively resolve velocity between collisions
|
||||||
Resolver.preSolveVelocity(pairs.list);
|
Resolver.preSolveVelocity(pairs.list);
|
||||||
for (i = 0; i < engine.velocityIterations; i++) {
|
for (i = 0; i < engine.velocityIterations; i++) {
|
||||||
Resolver.solveVelocity(pairs.list, timing.timeScale);
|
Resolver.solveVelocity(pairs.list, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// trigger collision events
|
// trigger collision events
|
||||||
|
@ -322,21 +318,16 @@ var Body = require('../body/Body');
|
||||||
* @method _bodiesUpdate
|
* @method _bodiesUpdate
|
||||||
* @private
|
* @private
|
||||||
* @param {body[]} bodies
|
* @param {body[]} bodies
|
||||||
* @param {number} deltaTime
|
* @param {number} delta The amount of time elapsed between updates
|
||||||
* The amount of time elapsed between updates
|
|
||||||
* @param {number} timeScale
|
|
||||||
* @param {number} correction
|
|
||||||
* The Verlet correction factor (deltaTime / lastDeltaTime)
|
|
||||||
* @param {bounds} worldBounds
|
|
||||||
*/
|
*/
|
||||||
Engine._bodiesUpdate = function(bodies, deltaTime, timeScale, correction, worldBounds) {
|
Engine._bodiesUpdate = function(bodies, delta) {
|
||||||
for (var i = 0; i < bodies.length; i++) {
|
for (var i = 0; i < bodies.length; i++) {
|
||||||
var body = bodies[i];
|
var body = bodies[i];
|
||||||
|
|
||||||
if (body.isStatic || body.isSleeping)
|
if (body.isStatic || body.isSleeping)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Body.update(body, deltaTime, timeScale, correction);
|
Body.update(body, delta);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -373,6 +364,7 @@ var Body = require('../body/Body');
|
||||||
* @param {} event An event object
|
* @param {} event An event object
|
||||||
* @param {} event.pairs List of affected pairs
|
* @param {} event.pairs List of affected pairs
|
||||||
* @param {number} event.timestamp The engine.timing.timestamp of the event
|
* @param {number} event.timestamp The engine.timing.timestamp of the event
|
||||||
|
* @param {number} event.delta The delta time in milliseconds value used in the update
|
||||||
* @param {} event.source The source object of the event
|
* @param {} event.source The source object of the event
|
||||||
* @param {} event.name The name of the event
|
* @param {} event.name The name of the event
|
||||||
*/
|
*/
|
||||||
|
@ -384,6 +376,7 @@ var Body = require('../body/Body');
|
||||||
* @param {} event An event object
|
* @param {} event An event object
|
||||||
* @param {} event.pairs List of affected pairs
|
* @param {} event.pairs List of affected pairs
|
||||||
* @param {number} event.timestamp The engine.timing.timestamp of the event
|
* @param {number} event.timestamp The engine.timing.timestamp of the event
|
||||||
|
* @param {number} event.delta The delta time in milliseconds value used in the update
|
||||||
* @param {} event.source The source object of the event
|
* @param {} event.source The source object of the event
|
||||||
* @param {} event.name The name of the event
|
* @param {} event.name The name of the event
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -53,13 +53,11 @@ var Common = require('./Common');
|
||||||
Runner.create = function(options) {
|
Runner.create = function(options) {
|
||||||
var defaults = {
|
var defaults = {
|
||||||
fps: 60,
|
fps: 60,
|
||||||
correction: 1,
|
|
||||||
deltaSampleSize: 60,
|
deltaSampleSize: 60,
|
||||||
counterTimestamp: 0,
|
counterTimestamp: 0,
|
||||||
frameCounter: 0,
|
frameCounter: 0,
|
||||||
deltaHistory: [],
|
deltaHistory: [],
|
||||||
timePrev: null,
|
timePrev: null,
|
||||||
timeScalePrev: 1,
|
|
||||||
frameRequestId: null,
|
frameRequestId: null,
|
||||||
isFixed: false,
|
isFixed: false,
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -100,7 +98,7 @@ var Common = require('./Common');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A game loop utility that updates the engine and renderer by one step (a 'tick').
|
* A game loop utility that updates the engine and renderer by one step (a 'tick').
|
||||||
* Features delta smoothing, time correction and fixed or dynamic timing.
|
* Features delta smoothing and fixed or dynamic timing.
|
||||||
* Triggers `beforeTick`, `tick` and `afterTick` events on the engine.
|
* Triggers `beforeTick`, `tick` and `afterTick` events on the engine.
|
||||||
* Consider just `Engine.update(engine, delta)` if you're using your own loop.
|
* Consider just `Engine.update(engine, delta)` if you're using your own loop.
|
||||||
* @method tick
|
* @method tick
|
||||||
|
@ -110,17 +108,8 @@ var Common = require('./Common');
|
||||||
*/
|
*/
|
||||||
Runner.tick = function(runner, engine, time) {
|
Runner.tick = function(runner, engine, time) {
|
||||||
var timing = engine.timing,
|
var timing = engine.timing,
|
||||||
correction = 1,
|
|
||||||
delta;
|
delta;
|
||||||
|
|
||||||
// create an event object
|
|
||||||
var event = {
|
|
||||||
timestamp: timing.timestamp
|
|
||||||
};
|
|
||||||
|
|
||||||
Events.trigger(runner, 'beforeTick', event);
|
|
||||||
Events.trigger(engine, 'beforeTick', event); // @deprecated
|
|
||||||
|
|
||||||
if (runner.isFixed) {
|
if (runner.isFixed) {
|
||||||
// fixed timestep
|
// fixed timestep
|
||||||
delta = runner.delta;
|
delta = runner.delta;
|
||||||
|
@ -133,27 +122,22 @@ var Common = require('./Common');
|
||||||
runner.deltaHistory.push(delta);
|
runner.deltaHistory.push(delta);
|
||||||
runner.deltaHistory = runner.deltaHistory.slice(-runner.deltaSampleSize);
|
runner.deltaHistory = runner.deltaHistory.slice(-runner.deltaSampleSize);
|
||||||
delta = Math.min.apply(null, runner.deltaHistory);
|
delta = Math.min.apply(null, runner.deltaHistory);
|
||||||
|
|
||||||
// limit delta
|
// limit delta
|
||||||
delta = delta < runner.deltaMin ? runner.deltaMin : delta;
|
delta = delta < runner.deltaMin ? runner.deltaMin : delta;
|
||||||
delta = delta > runner.deltaMax ? runner.deltaMax : delta;
|
delta = delta > runner.deltaMax ? runner.deltaMax : delta;
|
||||||
|
|
||||||
// correction for delta
|
|
||||||
correction = delta / runner.delta;
|
|
||||||
|
|
||||||
// update engine timing object
|
// update engine timing object
|
||||||
runner.delta = delta;
|
runner.delta = delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
// time correction for time scaling
|
// create an event object
|
||||||
if (runner.timeScalePrev !== 0)
|
var event = {
|
||||||
correction *= timing.timeScale / runner.timeScalePrev;
|
timestamp: timing.timestamp
|
||||||
|
};
|
||||||
|
|
||||||
if (timing.timeScale === 0)
|
Events.trigger(runner, 'beforeTick', event);
|
||||||
correction = 0;
|
Events.trigger(engine, 'beforeTick', event); // @deprecated
|
||||||
|
|
||||||
runner.timeScalePrev = timing.timeScale;
|
|
||||||
runner.correction = correction;
|
|
||||||
|
|
||||||
// fps counter
|
// fps counter
|
||||||
runner.frameCounter += 1;
|
runner.frameCounter += 1;
|
||||||
|
|
|
@ -9,6 +9,7 @@ var Sleeping = {};
|
||||||
module.exports = Sleeping;
|
module.exports = Sleeping;
|
||||||
|
|
||||||
var Events = require('./Events');
|
var Events = require('./Events');
|
||||||
|
var Common = require('./Common');
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
@ -20,11 +21,11 @@ var Events = require('./Events');
|
||||||
* Puts bodies to sleep or wakes them up depending on their motion.
|
* Puts bodies to sleep or wakes them up depending on their motion.
|
||||||
* @method update
|
* @method update
|
||||||
* @param {body[]} bodies
|
* @param {body[]} bodies
|
||||||
* @param {number} timeScale
|
* @param {number} delta
|
||||||
*/
|
*/
|
||||||
Sleeping.update = function(bodies, timeScale) {
|
Sleeping.update = function(bodies, delta) {
|
||||||
var timeFactor = timeScale * timeScale * timeScale;
|
var timeScale = delta / Common._timeUnit;
|
||||||
|
|
||||||
// update bodies sleeping status
|
// update bodies sleeping status
|
||||||
for (var i = 0; i < bodies.length; i++) {
|
for (var i = 0; i < bodies.length; i++) {
|
||||||
var body = bodies[i],
|
var body = bodies[i],
|
||||||
|
@ -41,11 +42,11 @@ var Events = require('./Events');
|
||||||
|
|
||||||
// biased average motion estimation between frames
|
// biased average motion estimation between frames
|
||||||
body.motion = Sleeping._minBias * minMotion + (1 - Sleeping._minBias) * maxMotion;
|
body.motion = Sleeping._minBias * minMotion + (1 - Sleeping._minBias) * maxMotion;
|
||||||
|
|
||||||
if (body.sleepThreshold > 0 && body.motion < Sleeping._motionSleepThreshold * timeFactor) {
|
if (body.sleepThreshold > 0 && body.motion < Sleeping._motionSleepThreshold * timeScale * timeScale) {
|
||||||
body.sleepCounter += 1;
|
body.sleepCounter += 1;
|
||||||
|
|
||||||
if (body.sleepCounter >= body.sleepThreshold)
|
if (body.sleepCounter >= body.sleepThreshold / timeScale)
|
||||||
Sleeping.set(body, true);
|
Sleeping.set(body, true);
|
||||||
} else if (body.sleepCounter > 0) {
|
} else if (body.sleepCounter > 0) {
|
||||||
body.sleepCounter -= 1;
|
body.sleepCounter -= 1;
|
||||||
|
@ -57,10 +58,10 @@ var Events = require('./Events');
|
||||||
* Given a set of colliding pairs, wakes the sleeping bodies involved.
|
* Given a set of colliding pairs, wakes the sleeping bodies involved.
|
||||||
* @method afterCollisions
|
* @method afterCollisions
|
||||||
* @param {pair[]} pairs
|
* @param {pair[]} pairs
|
||||||
* @param {number} timeScale
|
* @param {number} delta
|
||||||
*/
|
*/
|
||||||
Sleeping.afterCollisions = function(pairs, timeScale) {
|
Sleeping.afterCollisions = function(pairs, delta) {
|
||||||
var timeFactor = timeScale * timeScale * timeScale;
|
var timeScale = delta / Common._timeUnit;
|
||||||
|
|
||||||
// wake up bodies involved in collisions
|
// wake up bodies involved in collisions
|
||||||
for (var i = 0; i < pairs.length; i++) {
|
for (var i = 0; i < pairs.length; i++) {
|
||||||
|
@ -82,7 +83,7 @@ var Events = require('./Events');
|
||||||
var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB,
|
var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB,
|
||||||
movingBody = sleepingBody === bodyA ? bodyB : bodyA;
|
movingBody = sleepingBody === bodyA ? bodyB : bodyA;
|
||||||
|
|
||||||
if (!sleepingBody.isStatic && movingBody.motion > Sleeping._motionWakeThreshold * timeFactor) {
|
if (!sleepingBody.isStatic && movingBody.motion > Sleeping._motionWakeThreshold * timeScale * timeScale) {
|
||||||
Sleeping.set(sleepingBody, false);
|
Sleeping.set(sleepingBody, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue