Show:

File: src/core/Sleeping.js

                                /**
                                * The `Matter.Sleeping` module contains methods to manage the sleeping state of bodies.
                                *
                                * @class Sleeping
                                */
                                
                                var Sleeping = {};
                                
                                module.exports = Sleeping;
                                
                                var Body = require('../body/Body');
                                var Events = require('./Events');
                                var Common = require('./Common');
                                
                                (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} delta
                                     */
                                    Sleeping.update = function(bodies, delta) {
                                        var timeScale = delta / Common._baseDelta,
                                            motionSleepThreshold = Sleeping._motionSleepThreshold;
                                        
                                        // update bodies sleeping status
                                        for (var i = 0; i < bodies.length; i++) {
                                            var body = bodies[i],
                                                speed = Body.getSpeed(body),
                                                angularSpeed = Body.getAngularSpeed(body),
                                                motion = speed * speed + angularSpeed * angularSpeed;
                                
                                            // wake up bodies if they have a force applied
                                            if (body.force.x !== 0 || body.force.y !== 0) {
                                                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 < motionSleepThreshold) {
                                                body.sleepCounter += 1;
                                                
                                                if (body.sleepCounter >= body.sleepThreshold / timeScale) {
                                                    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
                                     */
                                    Sleeping.afterCollisions = function(pairs) {
                                        var motionSleepThreshold = Sleeping._motionSleepThreshold;
                                
                                        // 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 > motionSleepThreshold) {
                                                    Sleeping.set(sleepingBody, false);
                                                }
                                            }
                                        }
                                    };
                                  
                                    /**
                                     * Set a body as sleeping or awake.
                                     * @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');
                                            }
                                        }
                                    };
                                
                                })();