0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2024-12-02 10:49:45 -05:00
liabru-matter-js/src/core/Sleeping.js

129 lines
No EOL
3.9 KiB
JavaScript

/**
* _Internal Class_, not generally used outside of the engine's internals.
*
* @class Sleeping
*/
var Sleeping = {};
module.exports = Sleeping;
var Events = require('./Events');
(function() {
Sleeping._motionWakeThreshold = 0.18;
Sleeping._motionSleepThreshold = 0.08;
Sleeping._minBias = 0.9;
/**
* Puts bodies to sleep or wakes them up depending on their motion.
* @method update
* @param {body[]} bodies
* @param {number} timeScale
*/
Sleeping.update = function(bodies, timeScale) {
var timeFactor = timeScale * timeScale * timeScale;
// update bodies sleeping status
for (var i = 0; i < bodies.length; i++) {
var body = bodies[i],
motion = body.speed * body.speed + body.angularSpeed * body.angularSpeed;
// wake up bodies if they have a force applied
if (body.force.x !== 0 || body.force.y !== 0) {
Sleeping.set(body, false);
continue;
}
var minMotion = Math.min(body.motion, motion),
maxMotion = Math.max(body.motion, motion);
// biased average motion estimation between frames
body.motion = Sleeping._minBias * minMotion + (1 - Sleeping._minBias) * maxMotion;
if (body.sleepThreshold > 0 && body.motion < Sleeping._motionSleepThreshold * timeFactor) {
body.sleepCounter += 1;
if (body.sleepCounter >= body.sleepThreshold)
Sleeping.set(body, true);
} else if (body.sleepCounter > 0) {
body.sleepCounter -= 1;
}
}
};
/**
* Given a set of colliding pairs, wakes the sleeping bodies involved.
* @method afterCollisions
* @param {pair[]} pairs
* @param {number} timeScale
*/
Sleeping.afterCollisions = function(pairs, timeScale) {
var timeFactor = timeScale * timeScale * timeScale;
// wake up bodies involved in collisions
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i];
// don't wake inactive pairs
if (!pair.isActive)
continue;
var collision = pair.collision,
bodyA = collision.bodyA.parent,
bodyB = collision.bodyB.parent;
// don't wake if at least one body is static
if ((bodyA.isSleeping && bodyB.isSleeping) || bodyA.isStatic || bodyB.isStatic)
continue;
if (bodyA.isSleeping || bodyB.isSleeping) {
var sleepingBody = (bodyA.isSleeping && !bodyA.isStatic) ? bodyA : bodyB,
movingBody = sleepingBody === bodyA ? bodyB : bodyA;
if (!sleepingBody.isStatic && movingBody.motion > Sleeping._motionWakeThreshold * timeFactor) {
Sleeping.set(sleepingBody, false);
}
}
}
};
/**
* Description
* @method set
* @param {body} body
* @param {boolean} isSleeping
*/
Sleeping.set = function(body, isSleeping) {
var wasSleeping = body.isSleeping;
if (isSleeping) {
body.isSleeping = true;
body.sleepCounter = body.sleepThreshold;
body.positionImpulse.x = 0;
body.positionImpulse.y = 0;
body.positionPrev.x = body.position.x;
body.positionPrev.y = body.position.y;
body.anglePrev = body.angle;
body.speed = 0;
body.angularSpeed = 0;
body.motion = 0;
if (!wasSleeping) {
Events.trigger(body, 'sleepStart');
}
} else {
body.isSleeping = false;
body.sleepCounter = 0;
if (wasSleeping) {
Events.trigger(body, 'sleepEnd');
}
}
};
})();