diff --git a/dist/behaviors/attractor.js b/dist/behaviors/attractor.js index cabebb3f..ba1b2b31 100644 --- a/dist/behaviors/attractor.js +++ b/dist/behaviors/attractor.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/behaviors/body-collision-detection.js b/dist/behaviors/body-collision-detection.js index 027f10c2..2121e2c1 100644 --- a/dist/behaviors/body-collision-detection.js +++ b/dist/behaviors/body-collision-detection.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * @@ -149,11 +149,8 @@ bodyB: bodyB }; - // figure out how much the bodies moved relative to each other - tmp.clone( bodyA.state.pos ).vsub( bodyA.state.old.pos ).vsub( bodyB.state.pos ).vadd( bodyB.state.old.pos ); - inc = Math.abs(tmp.proj( d )); - // let's increment the margin by half this value each iteration - inc = Math.max( 0.5 * inc, 1 ); + // inc by 1% of the smallest dim. + inc = 1e-2 * Math.min(dimA || 1, dimB || 1); // first get the min distance of between core objects support.useCore = true; @@ -243,7 +240,7 @@ }; /* - * checkPair( bodyA, bodyB ) -> Object + * checkPair( bodyA, bodyB[, disp] ) -> Object * - bodyA (Object): First body * - bodyB (Object): Second body * + (Object): Collision result diff --git a/dist/behaviors/body-impulse-response.js b/dist/behaviors/body-impulse-response.js index 71fd6001..63f1d8d1 100644 --- a/dist/behaviors/body-impulse-response.js +++ b/dist/behaviors/body-impulse-response.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * @@ -45,6 +45,26 @@ ,forceWakeupAboveOverlapThreshold: true }; + function getUid( b ){ + return b.uid; + } + + function clampMTV( totalV, mtv, into ){ + + var m, n; + n = mtv.norm(); + m = n - totalV.proj( mtv ); + m = Math.max( 0, Math.min( n, m ) ); + + if ( n === 0 ){ + into.zero(); + } else { + into.clone( mtv ).mult( m/n ); + } + + return into; + } + return { // extended @@ -53,6 +73,8 @@ parent.init.call( this ); this.options.defaults( defaults ); this.options( options ); + + this._bodyList = []; }, // no applyTo method @@ -134,38 +156,34 @@ ,impulse ,sign ,max + ,ratio ,inContact = contact ; if ( contact ){ - if ( mtv.normSq() < this.options.mtvThreshold ){ - mtv.mult( this.options.bodyExtractDropoff ); - } else if ( this.options.forceWakeupAboveOverlapThreshold ) { - // wake up bodies if necessary - bodyA.sleep( false ); - bodyB.sleep( false ); - } if ( fixedA ){ - // extract bodies - bodyB.state.pos.vadd( mtv ); - bodyB.state.old.pos.vadd( mtv ); + clampMTV( bodyB._mtvTotal, mtv, tmp ); + bodyB._mtvTotal.vadd( tmp ); } else if ( fixedB ){ - // extract bodies - bodyA.state.pos.vsub( mtv ); - bodyA.state.old.pos.vsub( mtv ); + clampMTV( bodyA._mtvTotal, mtv.negate(), tmp ); + bodyA._mtvTotal.vadd( tmp ); + mtv.negate(); } else { - // extract bodies - mtv.mult( 0.5 ); - bodyA.state.pos.vsub( mtv ); - bodyA.state.old.pos.vsub( mtv ); - bodyB.state.pos.vadd( mtv ); - bodyB.state.old.pos.vadd( mtv ); + ratio = 0.5; //bodyA.mass / ( bodyA.mass + bodyB.mass ); + mtv.mult( ratio ); + clampMTV( bodyB._mtvTotal, mtv, tmp ); + bodyB._mtvTotal.vadd( tmp ); + + mtv.clone( mtrans ).mult( ratio - 1 ); + clampMTV( bodyA._mtvTotal, mtv, tmp ); + bodyA._mtvTotal.vadd( tmp ); + } } @@ -264,6 +282,14 @@ scratch.done(); }, + // internal + _pushUniq: function( body ){ + var idx = Physics.util.sortedIndex( this._bodyList, body, getUid ); + if ( this._bodyList[ idx ] !== body ){ + this._bodyList.splice( idx, 0, body ); + } + }, + /** internal * BodyImpulseResponseBehavior#respond( data ) * - data (Object): event data @@ -274,12 +300,22 @@ var self = this ,col - ,collisions = Physics.util.shuffle(data.collisions) + ,collisions = data.collisions// Physics.util.shuffle(data.collisions) + ,i,l,b ; - for ( var i = 0, l = collisions.length; i < l; ++i ){ + for ( i = 0, l = collisions.length; i < l; ++i ){ col = collisions[ i ]; + // add bodies to list for later + this._pushUniq( col.bodyA ); + this._pushUniq( col.bodyB ); + // ensure they have mtv stat vectors + col.bodyA._mtvTotal = col.bodyA._mtvTotal || new Physics.vector(); + col.bodyB._mtvTotal = col.bodyB._mtvTotal || new Physics.vector(); + col.bodyA._oldmtvTotal = col.bodyA._oldmtvTotal || new Physics.vector(); + col.bodyB._oldmtvTotal = col.bodyB._oldmtvTotal || new Physics.vector(); + self.collideBodies( col.bodyA, col.bodyB, @@ -289,6 +325,24 @@ col.collidedPreviously ); } + + // apply mtv vectors from the average mtv vector + for ( i = 0, l = this._bodyList.length; i < l; ++i ){ + b = this._bodyList.pop(); + // clampMTV( b._oldmtvTotal, b._mtvTotal, b._mtvTotal ); + + if ( b._mtvTotal.normSq() < this.options.mtvThreshold ){ + b._mtvTotal.mult( this.options.bodyExtractDropoff ); + } else if ( this.options.forceWakeupAboveOverlapThreshold ) { + // wake up bodies if necessary + b.sleep( false ); + } + + b.state.pos.vadd( b._mtvTotal ); + b.state.old.pos.vadd( b._mtvTotal ); + b._oldmtvTotal.swap( b._mtvTotal ); + b._mtvTotal.zero(); + } } }; }); diff --git a/dist/behaviors/constant-acceleration.js b/dist/behaviors/constant-acceleration.js index 8ff811a6..2a453116 100644 --- a/dist/behaviors/constant-acceleration.js +++ b/dist/behaviors/constant-acceleration.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/behaviors/edge-collision-detection.js b/dist/behaviors/edge-collision-detection.js index 1e416edc..5d774a8f 100644 --- a/dist/behaviors/edge-collision-detection.js +++ b/dist/behaviors/edge-collision-detection.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/behaviors/interactive.js b/dist/behaviors/interactive.js index 0e9320ff..2d9ca6eb 100644 --- a/dist/behaviors/interactive.js +++ b/dist/behaviors/interactive.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/behaviors/newtonian.js b/dist/behaviors/newtonian.js index 782afddb..748aca01 100644 --- a/dist/behaviors/newtonian.js +++ b/dist/behaviors/newtonian.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * @@ -16,7 +16,7 @@ } }(this, function (Physics) { 'use strict'; - /** + /** * class NewtonianBehavior < Behavior * * `Physics.behavior('newtonian')`. @@ -54,42 +54,95 @@ }); this.options( options ); }, - + + calcPotential: function( posA, posB, out ){ + + var strength = this.options.strength + ,minDistSq = this._minDistSq + ,maxDistSq = this._maxDistSq + ,normsq + ,g + ,pos + ; + + pos = out || new Physics.vector(); + + // clone the position + pos.clone( posB ).vsub( posA ); + // get the square distance + normsq = pos.normSq(); + + if (normsq > minDistSq && normsq < maxDistSq){ + + g = strength / normsq; + return pos.normalize().mult( g ); + } + + return pos.zero(); + }, + // extended behave: function( data ){ var bodies = this.getTargets() ,body ,other - ,strength = this.options.strength - ,minDistSq = this._minDistSq - ,maxDistSq = this._maxDistSq ,scratch = Physics.scratchpad() - ,pos = scratch.vector() - ,normsq - ,g + ,potential = scratch.vector() + ,comp + ,bodyA + ,bodyB + ,posA = scratch.vector() + ,posB = scratch.vector() + ,i, j, k, m, l, ll, lll ; - for ( var j = 0, l = bodies.length; j < l; j++ ){ - + for ( j = 0, l = bodies.length; j < l; j++ ){ + body = bodies[ j ]; - for ( var i = j + 1; i < l; i++ ){ - + for ( i = j + 1; i < l; i++ ){ + other = bodies[ i ]; - // clone the position - pos.clone( other.state.pos ); - pos.vsub( body.state.pos ); - // get the square distance - normsq = pos.normSq(); - if (normsq > minDistSq && normsq < maxDistSq){ + if ( body.name === 'compound' ){ + comp = body; + } else if ( other.name === 'compound' ){ + comp = other; + other = body; + } + + if ( comp ){ + if ( other.name === 'compound' ){ + for ( k = 0, ll = comp.children.length; k < ll; k++ ){ + bodyA = comp.children[ k ]; + comp.toWorldCoords( posA.clone( bodyA.state.pos ).vadd( comp.offset ) ); + for ( m = 0, lll = other.children.length; m < lll; m++ ){ + bodyB = other.children[ m ]; + other.toWorldCoords( posB.clone( bodyB.state.pos ).vadd( other.offset ) ); + this.calcPotential( posA, posB, potential ); + comp.accelerate( potential.mult( bodyB.mass ) ); + other.accelerate( potential.mult( bodyA.mass/bodyB.mass ).negate() ); + } + } + } else { + for ( k = 0, ll = comp.children.length; k < ll; k++ ){ + bodyA = comp.children[ k ]; + comp.toWorldCoords( posA.clone( bodyA.state.pos ).vadd( comp.offset ) ); + this.calcPotential( posA, other.state.pos, potential ); + comp.accelerate( potential.mult( other.mass ) ); + other.accelerate( potential.mult( bodyA.mass/other.mass ).negate() ); + } + } - g = strength / normsq; + } else { - body.accelerate( pos.normalize().mult( g * other.mass ) ); - other.accelerate( pos.mult( body.mass/other.mass ).negate() ); + this.calcPotential( body.state.pos, other.state.pos, potential ); + body.accelerate( potential.mult( other.mass ) ); + other.accelerate( potential.mult( body.mass/other.mass ).negate() ); } + + comp = null; } } diff --git a/dist/behaviors/sweep-prune.js b/dist/behaviors/sweep-prune.js index 7e635652..4076a3e5 100644 --- a/dist/behaviors/sweep-prune.js +++ b/dist/behaviors/sweep-prune.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/behaviors/verlet-constraints.js b/dist/behaviors/verlet-constraints.js index a09b01e2..3a2b643b 100644 --- a/dist/behaviors/verlet-constraints.js +++ b/dist/behaviors/verlet-constraints.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/bodies/circle.js b/dist/bodies/circle.js index 9378fae3..d04f31ba 100644 --- a/dist/bodies/circle.js +++ b/dist/bodies/circle.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/bodies/compound.js b/dist/bodies/compound.js index aca3172d..be742341 100644 --- a/dist/bodies/compound.js +++ b/dist/bodies/compound.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/bodies/convex-polygon.js b/dist/bodies/convex-polygon.js index 4418ffee..a68736ea 100644 --- a/dist/bodies/convex-polygon.js +++ b/dist/bodies/convex-polygon.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/bodies/rectangle.js b/dist/bodies/rectangle.js index 93ba2144..22235652 100644 --- a/dist/bodies/rectangle.js +++ b/dist/bodies/rectangle.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/geometries/circle.js b/dist/geometries/circle.js index 161553c8..6ff8d95e 100644 --- a/dist/geometries/circle.js +++ b/dist/geometries/circle.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/geometries/compound.js b/dist/geometries/compound.js index aab2afc1..93589fc1 100644 --- a/dist/geometries/compound.js +++ b/dist/geometries/compound.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/geometries/convex-polygon.js b/dist/geometries/convex-polygon.js index d4213f9c..82859fb7 100644 --- a/dist/geometries/convex-polygon.js +++ b/dist/geometries/convex-polygon.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/geometries/rectangle.js b/dist/geometries/rectangle.js index 492cea01..f10b93df 100644 --- a/dist/geometries/rectangle.js +++ b/dist/geometries/rectangle.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/integrators/improved-euler.js b/dist/integrators/improved-euler.js index d99b6d8c..5c308763 100644 --- a/dist/integrators/improved-euler.js +++ b/dist/integrators/improved-euler.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/integrators/velocity-verlet-alt.js b/dist/integrators/velocity-verlet-alt.js index dd479f79..414aedf1 100644 --- a/dist/integrators/velocity-verlet-alt.js +++ b/dist/integrators/velocity-verlet-alt.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/integrators/velocity-verlet.js b/dist/integrators/velocity-verlet.js index 405eaf3c..26d74947 100644 --- a/dist/integrators/velocity-verlet.js +++ b/dist/integrators/velocity-verlet.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/physicsjs-full.js b/dist/physicsjs-full.js index ba321745..96309861 100644 --- a/dist/physicsjs-full.js +++ b/dist/physicsjs-full.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * @@ -573,6 +573,73 @@ Physics.util = {}; })(); +// --- +// inside: src/math/statistics.js + +(function(){ + + Physics.statistics = { + /** + * Physics.statistics.pushRunningAvg( v, k, m, s ) -> Array + * - v (Number): is value to push + * - k (Number): is num elements + * - m (Number): is current mean + * - s (Number): is current s value + * + (Array): Returns a 2 element array containing the next mean, and s value + * + * Push a value to a running average calculation. + * see [http://www.johndcook.com/blog/standard_deviation] + * + * Note: variance can be calculated from the "s" value by multiplying it by `1/(k-1)` + **/ + pushRunningAvg: function( v, k, m, s ){ + + var x = v - m; + + // Mk = Mk-1+ (xk – Mk-1)/k + // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). + m += x / k; + s += x * (v - m); + return [m, s]; + }, + + /** + * Physics.statistics.pushRunningVectorAvg( v, k, m[, s] ) + * - v (Physics.vector): is vector to push + * - k (Number): is num elements + * - m (Physics.vector): is current mean + * - s (Physics.vector): is current s value + * + * Push a vector to a running vector average calculation. + * see [http://www.johndcook.com/blog/standard_deviation] + * + * Calculations are done in place. The `m` and `s` parameters are altered. + * + * Note: variance can be calculated from the "s" vector by multiplying it by `1/(k-1)` + * + * If s value is ommitted it won't be used. + **/ + pushRunningVectorAvg: function( v, k, m, s ){ + var invK = 1/k + ,x = v.get(0) - m.get(0) + ,y = v.get(1) - m.get(1) + ; + + // Mk = Mk-1+ (xk – Mk-1)/k + // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). + m.add( x * invK, y * invK ); + + if ( s ){ + x *= v.get(0) - m.get(0); + y *= v.get(1) - m.get(1); + + s.add( x, y ); + } + } + }; +})(); + + // --- // inside: src/math/transform.js @@ -3524,46 +3591,13 @@ Physics.scratchpad = (function(){ view: null }; - // Running average - // http://www.johndcook.com/blog/standard_deviation - // k is num elements - // m is current mean - // s is current std deviation - // v is value to push - function pushRunningAvg( k, m, s, v ){ - - var x = v - m; - - // Mk = Mk-1+ (xk – Mk-1)/k - // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). - m += x / k; - s += x * (v - m); - } - - // Running vector average - // http://www.johndcook.com/blog/standard_deviation - // k is num elements - // m is current mean (vector) - // s is current std deviation (vector) - // v is vector to push - function pushRunningVectorAvg( k, m, s, v ){ - var invK = 1/k - ,x = v.get(0) - m.get(0) - ,y = v.get(1) - m.get(1) - ; - - // Mk = Mk-1+ (xk – Mk-1)/k - // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). - m.add( x * invK, y * invK ); - - x *= v.get(0) - m.get(0); - y *= v.get(1) - m.get(1); + var uidGen = 1; - s.add( x, y ); + var Pi2 = Math.PI * 2; + function cycleAngle( ang ){ + return ((ang % Pi2) + Pi2) % Pi2; } - var uidGen = 1; - /** related to: Physics.util.decorator * Physics.body( name[, options] ) -> Body * - name (String): The name of the body to create @@ -3857,6 +3891,8 @@ Physics.scratchpad = (function(){ ,scratch = Physics.scratchpad() ,diff = scratch.vector() ,diff2 = scratch.vector() + ,kfac + ,stats ; dt = dt || 0; @@ -3875,11 +3911,17 @@ Physics.scratchpad = (function(){ } this._sleepMeanK++; - pushRunningVectorAvg( this._sleepMeanK, this._sleepPosMean, this._sleepPosVariance, this.state.pos ); - pushRunningAvg( this._sleepMeanK, this._sleepAngPosMean, this._sleepAngPosVariance, this.state.angular.pos ); - v = this._sleepPosVariance.norm() + Math.abs(r * this._sleepAngPosVariance); + kfac = this._sleepMeanK > 1 ? 1/(this._sleepMeanK - 1) : 0; + Physics.statistics.pushRunningVectorAvg( this.state.pos, this._sleepMeanK, this._sleepPosMean, this._sleepPosVariance ); + // we take the sin because that maps the discontinuous angle to a continuous value + // then the statistics calculations work better + stats = Physics.statistics.pushRunningAvg( Math.sin(this.state.angular.pos), this._sleepMeanK, this._sleepAngPosMean, this._sleepAngPosVariance ); + this._sleepAngPosMean = stats[0]; + this._sleepAngPosVariance = stats[1]; + v = this._sleepPosVariance.norm() + Math.abs(r * Math.asin(stats[1])); + v *= kfac; limit = this.sleepVarianceLimit || (opts && opts.sleepVarianceLimit) || 0; - + // console.log(v, limit, kfac, this._sleepPosVariance.norm(), stats[1]) if ( v <= limit ){ // check idle time limit = this.sleepTimeLimit || (opts && opts.sleepTimeLimit) || 0; @@ -5000,9 +5042,9 @@ Physics.geometry.nearestPointOnLine = function nearestPointOnLine( pt, linePt1, // is sleeping disabled? sleepDisabled: false, // speed at which bodies wake up - sleepSpeedLimit: 0.1, + sleepSpeedLimit: 0.05, // variance in position below which bodies fall asleep - sleepVarianceLimit: 2, + sleepVarianceLimit: 0.02, // time (ms) before sleepy bodies fall asleep sleepTimeLimit: 500 }; @@ -7234,11 +7276,8 @@ Physics.behavior('body-collision-detection', function( parent ){ bodyB: bodyB }; - // figure out how much the bodies moved relative to each other - tmp.clone( bodyA.state.pos ).vsub( bodyA.state.old.pos ).vsub( bodyB.state.pos ).vadd( bodyB.state.old.pos ); - inc = Math.abs(tmp.proj( d )); - // let's increment the margin by half this value each iteration - inc = Math.max( 0.5 * inc, 1 ); + // inc by 1% of the smallest dim. + inc = 1e-2 * Math.min(dimA || 1, dimB || 1); // first get the min distance of between core objects support.useCore = true; @@ -7328,7 +7367,7 @@ Physics.behavior('body-collision-detection', function( parent ){ }; /* - * checkPair( bodyA, bodyB ) -> Object + * checkPair( bodyA, bodyB[, disp] ) -> Object * - bodyA (Object): First body * - bodyB (Object): Second body * + (Object): Collision result @@ -7623,6 +7662,26 @@ Physics.behavior('body-impulse-response', function( parent ){ ,forceWakeupAboveOverlapThreshold: true }; + function getUid( b ){ + return b.uid; + } + + function clampMTV( totalV, mtv, into ){ + + var m, n; + n = mtv.norm(); + m = n - totalV.proj( mtv ); + m = Math.max( 0, Math.min( n, m ) ); + + if ( n === 0 ){ + into.zero(); + } else { + into.clone( mtv ).mult( m/n ); + } + + return into; + } + return { // extended @@ -7631,6 +7690,8 @@ Physics.behavior('body-impulse-response', function( parent ){ parent.init.call( this ); this.options.defaults( defaults ); this.options( options ); + + this._bodyList = []; }, // no applyTo method @@ -7712,38 +7773,34 @@ Physics.behavior('body-impulse-response', function( parent ){ ,impulse ,sign ,max + ,ratio ,inContact = contact ; if ( contact ){ - if ( mtv.normSq() < this.options.mtvThreshold ){ - mtv.mult( this.options.bodyExtractDropoff ); - } else if ( this.options.forceWakeupAboveOverlapThreshold ) { - // wake up bodies if necessary - bodyA.sleep( false ); - bodyB.sleep( false ); - } if ( fixedA ){ - // extract bodies - bodyB.state.pos.vadd( mtv ); - bodyB.state.old.pos.vadd( mtv ); + clampMTV( bodyB._mtvTotal, mtv, tmp ); + bodyB._mtvTotal.vadd( tmp ); } else if ( fixedB ){ - // extract bodies - bodyA.state.pos.vsub( mtv ); - bodyA.state.old.pos.vsub( mtv ); + clampMTV( bodyA._mtvTotal, mtv.negate(), tmp ); + bodyA._mtvTotal.vadd( tmp ); + mtv.negate(); } else { - // extract bodies - mtv.mult( 0.5 ); - bodyA.state.pos.vsub( mtv ); - bodyA.state.old.pos.vsub( mtv ); - bodyB.state.pos.vadd( mtv ); - bodyB.state.old.pos.vadd( mtv ); + ratio = 0.5; //bodyA.mass / ( bodyA.mass + bodyB.mass ); + mtv.mult( ratio ); + clampMTV( bodyB._mtvTotal, mtv, tmp ); + bodyB._mtvTotal.vadd( tmp ); + + mtv.clone( mtrans ).mult( ratio - 1 ); + clampMTV( bodyA._mtvTotal, mtv, tmp ); + bodyA._mtvTotal.vadd( tmp ); + } } @@ -7842,6 +7899,14 @@ Physics.behavior('body-impulse-response', function( parent ){ scratch.done(); }, + // internal + _pushUniq: function( body ){ + var idx = Physics.util.sortedIndex( this._bodyList, body, getUid ); + if ( this._bodyList[ idx ] !== body ){ + this._bodyList.splice( idx, 0, body ); + } + }, + /** internal * BodyImpulseResponseBehavior#respond( data ) * - data (Object): event data @@ -7852,12 +7917,22 @@ Physics.behavior('body-impulse-response', function( parent ){ var self = this ,col - ,collisions = Physics.util.shuffle(data.collisions) + ,collisions = data.collisions// Physics.util.shuffle(data.collisions) + ,i,l,b ; - for ( var i = 0, l = collisions.length; i < l; ++i ){ + for ( i = 0, l = collisions.length; i < l; ++i ){ col = collisions[ i ]; + // add bodies to list for later + this._pushUniq( col.bodyA ); + this._pushUniq( col.bodyB ); + // ensure they have mtv stat vectors + col.bodyA._mtvTotal = col.bodyA._mtvTotal || new Physics.vector(); + col.bodyB._mtvTotal = col.bodyB._mtvTotal || new Physics.vector(); + col.bodyA._oldmtvTotal = col.bodyA._oldmtvTotal || new Physics.vector(); + col.bodyB._oldmtvTotal = col.bodyB._oldmtvTotal || new Physics.vector(); + self.collideBodies( col.bodyA, col.bodyB, @@ -7867,6 +7942,24 @@ Physics.behavior('body-impulse-response', function( parent ){ col.collidedPreviously ); } + + // apply mtv vectors from the average mtv vector + for ( i = 0, l = this._bodyList.length; i < l; ++i ){ + b = this._bodyList.pop(); + // clampMTV( b._oldmtvTotal, b._mtvTotal, b._mtvTotal ); + + if ( b._mtvTotal.normSq() < this.options.mtvThreshold ){ + b._mtvTotal.mult( this.options.bodyExtractDropoff ); + } else if ( this.options.forceWakeupAboveOverlapThreshold ) { + // wake up bodies if necessary + b.sleep( false ); + } + + b.state.pos.vadd( b._mtvTotal ); + b.state.old.pos.vadd( b._mtvTotal ); + b._oldmtvTotal.swap( b._mtvTotal ); + b._mtvTotal.zero(); + } } }; }); @@ -8573,7 +8666,7 @@ Physics.behavior('interactive', function( parent ){ // --- // inside: src/behaviors/newtonian.js -/** +/** * class NewtonianBehavior < Behavior * * `Physics.behavior('newtonian')`. @@ -8611,42 +8704,95 @@ Physics.behavior('newtonian', function( parent ){ }); this.options( options ); }, - + + calcPotential: function( posA, posB, out ){ + + var strength = this.options.strength + ,minDistSq = this._minDistSq + ,maxDistSq = this._maxDistSq + ,normsq + ,g + ,pos + ; + + pos = out || new Physics.vector(); + + // clone the position + pos.clone( posB ).vsub( posA ); + // get the square distance + normsq = pos.normSq(); + + if (normsq > minDistSq && normsq < maxDistSq){ + + g = strength / normsq; + return pos.normalize().mult( g ); + } + + return pos.zero(); + }, + // extended behave: function( data ){ var bodies = this.getTargets() ,body ,other - ,strength = this.options.strength - ,minDistSq = this._minDistSq - ,maxDistSq = this._maxDistSq ,scratch = Physics.scratchpad() - ,pos = scratch.vector() - ,normsq - ,g + ,potential = scratch.vector() + ,comp + ,bodyA + ,bodyB + ,posA = scratch.vector() + ,posB = scratch.vector() + ,i, j, k, m, l, ll, lll ; - for ( var j = 0, l = bodies.length; j < l; j++ ){ - + for ( j = 0, l = bodies.length; j < l; j++ ){ + body = bodies[ j ]; - for ( var i = j + 1; i < l; i++ ){ - + for ( i = j + 1; i < l; i++ ){ + other = bodies[ i ]; - // clone the position - pos.clone( other.state.pos ); - pos.vsub( body.state.pos ); - // get the square distance - normsq = pos.normSq(); - if (normsq > minDistSq && normsq < maxDistSq){ + if ( body.name === 'compound' ){ + comp = body; + } else if ( other.name === 'compound' ){ + comp = other; + other = body; + } - g = strength / normsq; + if ( comp ){ + if ( other.name === 'compound' ){ + for ( k = 0, ll = comp.children.length; k < ll; k++ ){ + bodyA = comp.children[ k ]; + comp.toWorldCoords( posA.clone( bodyA.state.pos ).vadd( comp.offset ) ); + for ( m = 0, lll = other.children.length; m < lll; m++ ){ + bodyB = other.children[ m ]; + other.toWorldCoords( posB.clone( bodyB.state.pos ).vadd( other.offset ) ); + this.calcPotential( posA, posB, potential ); + comp.accelerate( potential.mult( bodyB.mass ) ); + other.accelerate( potential.mult( bodyA.mass/bodyB.mass ).negate() ); + } + } + } else { + for ( k = 0, ll = comp.children.length; k < ll; k++ ){ + bodyA = comp.children[ k ]; + comp.toWorldCoords( posA.clone( bodyA.state.pos ).vadd( comp.offset ) ); + this.calcPotential( posA, other.state.pos, potential ); + comp.accelerate( potential.mult( other.mass ) ); + other.accelerate( potential.mult( bodyA.mass/other.mass ).negate() ); + } + } - body.accelerate( pos.normalize().mult( g * other.mass ) ); - other.accelerate( pos.mult( body.mass/other.mass ).negate() ); + } else { + + this.calcPotential( body.state.pos, other.state.pos, potential ); + body.accelerate( potential.mult( other.mass ) ); + other.accelerate( potential.mult( body.mass/other.mass ).negate() ); } + + comp = null; } } @@ -11208,7 +11354,9 @@ Physics.renderer('dom', function( proto ){ * strokeStyle: '0xE8900C', * lineWidth: 3, * fillStyle: '0xD5DE4C', - * angleIndicator: '0xE8900C' + * angleIndicator: '0xE8900C', + * strokeAlpha: 1, + * fillAlpha: 1 * }, * * 'convex-polygon' : { @@ -11290,6 +11438,7 @@ Physics.renderer('pixi', function( parent ){ fillStyle: colors.blue, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 }, @@ -11299,6 +11448,7 @@ Physics.renderer('pixi', function( parent ){ fillStyle: colors.violet, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 }, @@ -11308,6 +11458,7 @@ Physics.renderer('pixi', function( parent ){ fillStyle: colors.violet, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 } } @@ -11501,14 +11652,14 @@ Physics.renderer('pixi', function( parent ){ if ( styles.fillStyle && styles.fillStyle !== 'transparent' ){ graphics.beginFill( styles.fillStyle ); - graphics.fillAlpha = styles.fillAlpha || 1; + graphics.fillAlpha = styles.fillAlpha !== undefined ? styles.fillAlpha : 1; } else { graphics.beginFill(); graphics.fillAlpha = 0; } - graphics.lineStyle( styles.lineWidth || 0, styles.strokeStyle ); - graphics.alpha = styles.alpha || 1; + graphics.lineStyle( styles.lineWidth || 0, styles.strokeStyle, styles.strokeAlpha !== undefined ? styles.strokeAlpha : 1 ); + graphics.alpha = styles.alpha !== undefined ? styles.alpha : 1; } else { @@ -11697,6 +11848,9 @@ Physics.renderer('pixi', function( parent ){ view.lineStyle( styles.lineWidth, styles.angleIndicator ); view.moveTo( 0, 0 ); view.lineTo( hw, 0 ); + } + + if ( name !== 'compound' ){ view.cacheAsBitmap = true; } diff --git a/dist/physicsjs-full.min.js b/dist/physicsjs-full.min.js index 3d6497ac..ae662f39 100644 --- a/dist/physicsjs-full.min.js +++ b/dist/physicsjs-full.min.js @@ -1,11 +1,11 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * * Copyright (c) 2014 Jasper Palfree * Licensed MIT */ -!function(a,b){"object"==typeof exports?module.exports=b.call(a):"function"==typeof define&&define.amd?define(function(){return b.call(a)}):a.Physics=b.call(a)}("undefined"!=typeof window?window:this,function(){"use strict";var a=this,b=a.document,c=function f(){return f.world.apply(f,arguments)};c.util={},function(){c.aabb=function(a,b,c,d){var e={x:0,y:0,hw:0,hh:0};return void 0===a?e:(a&&void 0!==a.x&&(c=b.x,d=b.y,b=a.y,a=a.x),void 0===d&&void 0!==a&&void 0!==b?(e.hw=.5*a,e.hh=.5*b,c&&void 0!==c.x&&(e.x=c.x,e.y=c.y),e):(e.hw=.5*Math.abs(c-a),e.hh=.5*Math.abs(d-b),e.x=.5*(c+a),e.y=.5*(d+b),e))},c.aabb.contains=function(a,b){return b.x>a.x-a.hw&&b.xa.y-a.hh&&b.y=d&&f>=e||f>=c&&e>=f?(c=a.y-a.hh,d=b.y-b.hh,e=a.y+a.hh,f=b.y+b.hh,e>=d&&f>=e||f>=c&&e>=f):!1}}(),function(){var a=1e-4,b=100,d=function(a,b,c){var d=b.normSq()-b.dot(a),e=b.dot(a)-a.normSq();return 0>d?c.clone(b).negate():e>0?c.clone(a).negate():(c.clone(b).vsub(a),c.perp(a.cross(c)>0))},e=function(a){var b,d,e=a.length,f=a[e-2],g=a[e-3],h=c.scratchpad(),i=h.vector().clone(f.pt),j=h.vector().clone(g.pt).vsub(i);return j.equals(c.vector.zero)?h.done({a:f.a,b:f.b}):(b=-j.dot(i)/j.normSq(),d=1-b,h.done(0>=d?{a:g.a,b:g.b}:0>=b?{a:f.a,b:f.b}:{a:i.clone(f.a).mult(d).vadd(j.clone(g.a).mult(b)).values(),b:i.clone(f.b).mult(d).vadd(j.clone(g.b).mult(b)).values()}))},f=function(f,g,h,i){var j,k,l,m,n=!1,o=!1,p=!1,q=[],r=1,s=c.scratchpad(),t=s.vector().clone(g||c.vector.axis[0]),u=s.vector(),v=s.vector(),w=s.vector(),x=s.vector(),y=0;for(m=f(t),r=q.push(m),u.clone(m.pt),t.negate();++y;){if(u.swap(v),m=f(t),r=q.push(m),u.clone(m.pt),i&&i(q),u.equals(c.vector.zero)){n=!0;break}if(!o&&u.dot(t)<=0){if(h)break;o=!0}if(2===r)t=d(u,v,t);else if(o){if(t.normalize(),m=v.dot(t),Math.abs(m-u.dot(t))0,l^u.cross(j)>0)q.shift(),j.perp(!l),t.swap(j);else{if(!(l^k.cross(u)>0)){n=!0;break}q.splice(1,1),k.perp(l),t.swap(j)}if(y>b)return s.done(),{simplex:q,iterations:y,distance:0,maxIterationsReached:!0}}return s.done(),m={overlap:n,simplex:q,iterations:y},p!==!1&&(m.distance=p,m.closest=e(q)),m};c.gjk=f}(),function(){var a=function b(a,d,e){return this instanceof b?(this.v=new c.vector,this.o=new c.vector,a instanceof b?void this.clone(a):(a&&this.setTranslation(a),void this.setRotation(d||0,e))):new b(a,d)};a.prototype.setTranslation=function(a){return this.v.clone(a),this},a.prototype.setRotation=function(a,b){return this.cosA=Math.cos(a),this.sinA=Math.sin(a),b?this.o.clone(b):this.o.zero(),this},a.prototype.clone=function(b){return b?(this.setTranslation(b.v),this.cosA=b.cosA,this.sinA=b.sinA,this.o.clone(b.o),this):new a(this)},c.transform=a}(),function(a){var b=Math.sqrt,d=Math.min,e=Math.max,f=(Math.acos,Math.atan2),g=2*Math.PI,h=!!a.Float64Array,i=function j(a,b){return this instanceof j?(this._=h?new Float64Array(5):[],void(a&&(void 0!==a.x||a._&&a._.length)?this.clone(a):(this.recalc=!0,this.set(a,b)))):new j(a,b)};Object.defineProperties(i.prototype,{x:{get:function(){return+this._[0]},set:function(a){a=+a||0,this.recalc=a===this._[0],this._[0]=a}},y:{get:function(){return+this._[1]},set:function(a){a=+a||0,this.recalc=a===this._[1],this._[1]=a}}}),i.prototype.set=function(a,b){return this.recalc=!0,this._[0]=+a||0,this._[1]=+b||0,this},i.prototype.get=function(a){return this._[a]},i.prototype.vadd=function(a){return this.recalc=!0,this._[0]+=a._[0],this._[1]+=a._[1],this},i.prototype.vsub=function(a){return this.recalc=!0,this._[0]-=a._[0],this._[1]-=a._[1],this},i.prototype.add=function(a,b){return this.recalc=!0,this._[0]+=+a||0,this._[1]+=+b||0,this},i.prototype.sub=function(a,b){return this.recalc=!0,this._[0]-=a,this._[1]-=void 0===b?0:b,this},i.prototype.mult=function(a){return this.recalc||(this._[4]*=a*a,this._[3]*=a),this._[0]*=a,this._[1]*=a,this},i.prototype.dot=function(a){return this._[0]*a._[0]+this._[1]*a._[1]},i.prototype.cross=function(a){return-this._[0]*a._[1]+this._[1]*a._[0]},i.prototype.proj=function(a){return this.dot(a)/a.norm()},i.prototype.vproj=function(a){var b=this.dot(a)/a.normSq();return this.clone(a).mult(b)},i.prototype.angle=function(a){var b;if(this.equals(i.zero))return a?a.angle():0/0;for(b=a&&!a.equals(i.zero)?f(this._[1]*a._[0]-this._[0]*a._[1],this._[0]*a._[0]+this._[1]*a._[1]):f(this._[1],this._[0]);b>Math.PI;)b-=g;for(;b<-Math.PI;)b+=g;return b},i.prototype.angle2=function(a,b){for(var c=a._[0]-this._[0],d=a._[1]-this._[1],e=b._[0]-this._[0],h=b._[1]-this._[1],i=f(d*e-c*h,c*e+d*h);i>Math.PI;)i-=g;for(;i<-Math.PI;)i+=g;return i},i.prototype.norm=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[3]},i.prototype.normSq=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[4]},i.prototype.dist=function(a){var c,d;return b((c=a._[0]-this._[0])*c+(d=a._[1]-this._[1])*d)},i.prototype.distSq=function(a){var b,c;return(b=a._[0]-this._[0])*b+(c=a._[1]-this._[1])*c},i.prototype.perp=function(a){var b=this._[0];return a?(this._[0]=this._[1],this._[1]=-b):(this._[0]=-this._[1],this._[1]=b),this},i.prototype.normalize=function(){var a=this.norm();return 0===a?this:(a=1/a,this._[0]*=a,this._[1]*=a,this._[3]=1,this._[4]=1,this)},i.prototype.transform=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d,this._[1]-=e,this.set(this._[0]*c-this._[1]*b+d+a.v._[0],this._[0]*b+this._[1]*c+e+a.v._[1])},i.prototype.transformInv=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d+a.v._[0],this._[1]-=e+a.v._[1],this.set(this._[0]*c+this._[1]*b+d,-this._[0]*b+this._[1]*c+e)},i.prototype.rotate=function(a,b){var c,d,e=0,f=0;return"number"==typeof a?(c=Math.sin(a),d=Math.cos(a),b&&(e=b.x,f=b.y)):(c=a.sinA,d=a.cosA,e=a.o._[0],f=a.o._[1]),this._[0]-=e,this._[1]-=f,this.set(this._[0]*d-this._[1]*c+e,this._[0]*c+this._[1]*d+f)},i.prototype.rotateInv=function(a){return this.set((this._[0]-a.o._[0])*a.cosA+(this._[1]-a.o._[1])*a.sinA+a.o._[0],-(this._[0]-a.o._[0])*a.sinA+(this._[1]-a.o._[1])*a.cosA+a.o._[1])},i.prototype.translate=function(a){return this.vadd(a.v)},i.prototype.translateInv=function(a){return this.vsub(a.v)},i.prototype.clone=function(a){return a?a._?(this.recalc=a.recalc,a.recalc||(this._[3]=a._[3],this._[4]=a._[4]),this._[0]=a._[0],this._[1]=a._[1],this):this.set(a.x,a.y):new i(this)},i.prototype.swap=function(a){var b=this._;return this._=a._,a._=b,b=this.recalc,this.recalc=a.recalc,a.recalc=b,this},i.prototype.values=function(){return{x:this._[0],y:this._[1]}},i.prototype.zero=function(){return this._[3]=0,this._[4]=0,this._[0]=0,this._[1]=0,this},i.prototype.negate=function(a){return void 0!==a?(this._[a]=-this._[a],this):(this._[0]=-this._[0],this._[1]=-this._[1],this)},i.prototype.clamp=function(a,b){return this._[0]=d(e(this._[0],a.x),b.x),this._[1]=d(e(this._[1],a.y),b.y),this.recalc=!0,this},i.prototype.toString=function(){return"("+this._[0]+", "+this._[1]+")"},i.prototype.equals=function(a){return this._[0]===a._[0]&&this._[1]===a._[1]&&this._[2]===a._[2]},i.axis=[new i(1,0),new i(0,1)],i.zero=new i(0,0),c.vector=i}(this),function(a){var b=a.Physics;c.noConflict=function(){return a.Physics===c&&(a.Physics=b),c}}(this);var d=c.util.decorator=function(a,b){var d={},e={},f=function(a,b){var d,e;for(e in b)d=Object.getOwnPropertyDescriptor(b,e),d.get||d.set?Object.defineProperty(a,e,d):c.util.isFunction(d.value)&&(a[e]=d.value);return a},g=Object.getPrototypeOf;"function"!=typeof g&&(g="object"==typeof"test".__proto__?function(a){return a.__proto__}:function(a){return a.constructor.prototype});var h=Object.create;"function"!=typeof h&&(h=function(a){function b(){}return b.prototype=a,new b});var i=function(b,d){return"object"==typeof b?(e=f(e,b),void(e.type=a)):void("type"!==b&&c.util.isFunction(d)&&(e[b]=d))};i(b);var j=function(b,c,i,j){var k,l=e;if("string"!=typeof c)j=i,i=c;else{if(l=d[c],!l)throw'Error: "'+c+'" '+a+" not defined";l=l.prototype}if("function"==typeof i)k=d[b],k?k.prototype=f(k.prototype,i(g(k.prototype))):(k=d[b]=function(a){this.init&&this.init(a)},k.prototype=h(l),k.prototype=f(k.prototype,i(l,k.prototype))),k.prototype.type=a,k.prototype.name=b;else if(j=i||{},k=d[b],!k)throw'Error: "'+b+'" '+a+" not defined";return j?new k(j):void 0};return j.mixin=i,j};c.util.indexOf=function(a,b){for(var c=0,d=a.length;d>c;){if(d--,a[c]===b)return c;if(a[d]===b)return d;c++}return-1},c.util.clearArray=function(a){for(var b=a.length;b--;)a.pop();return a},c.util.throttle=function(a,b,c){var d,e,f=!1,g=function(){clearTimeout(d),f?(f=!1,d=setTimeout(g,b),a.apply(c,e)):d=!1};return c=c||null,function(){f=!0,e=arguments,d||g()}};var e=function(a,b){return c.util.isPlainObject(b)?c.util.extend({},a,b,e):void 0!==b?b:a};return c.util.options=function(a,b){var d,f={},g=[];return d=function(a,d){c.util.extend(b,a,d?e:null);for(var f=0,h=g.length;h>f;++f)g[f](b);return b},d.defaults=function(a,d){return c.util.extend(f,a,d?e:null),c.util.defaults(b,f,d?e:null),f},d.onChange=function(a){g.push(a)},b=b||d,d.defaults(a),d},c.util.pairHash=function(a,b){return a=0|a,b=0|b,(0|a)===(0|b)?-1:0|((0|a)>(0|b)?a<<16|65535&b:b<<16|65535&a)},c.util.bind=Function.prototype.bind?function(a,b,c){return c=Array.prototype.slice.call(arguments,1),Function.prototype.bind.apply(a,c)}:function(a,b,c){return c=Array.prototype.slice.call(arguments,2),function(){return a.apply(b,c.concat(Array.prototype.slice.call(arguments)))}},c.util.find=function(a,b){var c,d,e=a.length;for(c=0;e>c;c++)if(d=a[c],b(d,c,a))return d},c.util.filter=function(a,b){var c,d,e=a.length,f=[];for(c=0;e>c;c++)d=a[c],b(d,c,a)&&f.push(d);return f},function(){function a(a){c.util.clearArray(a),v.length-1?0:-1:a?0:-1}function g(a){var b=this.cache,c=typeof a;if("boolean"===c||null==a)b[a]=!0;else{"number"!==c&&"string"!==c&&(c="object");var d="number"===c?a:y+a,e=b[c]||(b[c]={});"object"===c?(e[d]||(e[d]=[])).push(a):e[d]=!0}}function h(a){var b=-1,c=a.length,e=a[0],f=a[c/2|0],h=a[c-1];if(e&&"object"==typeof e&&f&&"object"==typeof f&&h&&"object"==typeof h)return!1;var i=d();i["false"]=i["null"]=i["true"]=i.undefined=!1;var j=d();for(j.array=a,j.cache=i,j.push=g;++b=u&&k===c.util.indexOf,o=i||n?e():m;if(n){var p=h(o);k=f,o=p}for(;++jb;b++)d=a[b],e=i(0,++f),h[f]=h[e],h[e]=d;return h},c.util.isObject=function(a){return!(!a||!n[typeof a])},c.util.isFunction=j,c.util.isArray=Array.isArray||function(a){return a&&"object"==typeof a&&"number"==typeof a.length&&s.call(a)===p||!1};var C=RegExp("^"+String(s).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$");c.util.isPlainObject=Object.getPrototypeOf?function(a){if(!a||s.call(a)!==q)return!1;var b=a.valueOf,c=k(b)&&(c=Object.getPrototypeOf(b))&&Object.getPrototypeOf(c);return c?a===c||Object.getPrototypeOf(a)===c:l(a)}:l,c.util.uniq=function(a,b,c){return"boolean"!=typeof b&&null!=b&&(c=b,b=!1),m(a,b,c)};var D=function(a,b,c){var d,e=a,f=e;if(!e)return f;var g,h=arguments,i=0,j="number"==typeof c?2:h.length;for(j>2&&"function"==typeof h[j-1]&&(g=h[--j]);++id;){var f=d+e>>>1;c(a[f])=b.maxScratches)throw f},a.prototype={done:function(a){this._active=!1;for(var b=0;j>b;++b)this[b]=0;return h.push(this),a}},b=function k(b){if(b)return k.fn(b);var c=h.pop()||new a;return c._active=!0,c},b.maxScratches=100,b.maxIndex=20,b.fn=function(b){for(var c=[],d=0,e=b.length;e>d;d++)c.push(d);c="a"+c.join(",a");var f=new Function("fn, scratches, Scratch","return function("+c+"){ var scratch = scratches.pop() || new Scratch( scratches );scratch._active = true;return scratch.done( fn(scratch, "+c+") );};");return f(b,h,a)},b.register=function(c,f,h){var i=a.prototype,k=j++,l="_"+c+"Stack",m=h&&h.useFactory;if(c in i)throw g;a.prototype[c]=function(){var a=this[l]||(this[l]=[]),c=0|this[k];if(this[k]=c+1,!this._active)throw d;if(c>=b.maxIndex)throw e;return a[c]||(a[c]=m?f():new f)}},b.register("vector",c.vector),b.register("transform",c.transform),b}(),function(){function a(a){return a._priority_}var b=1;c.scratchpad.register("event",function(){return{}},{useFactory:!0});var d=function e(){return this instanceof e?void 0:new e};d.prototype={on:function(d,e,f,g){var h,i,j;if(this._topics=this._topics||(this._topics={}),c.util.isObject(d)){for(var k in d)this.on(k,d[k],e,f);return this}return h=this._topics[d]||(this._topics[d]=[]),i=e,c.util.isObject(f)?(e=c.util.bind(e,f),e._bindfn_=i,e._one_=i._one_,e._scope_=f):void 0===g&&(g=f),e._priority_=void 0===g?b:g,j=c.util.sortedIndex(h,e,a),h.splice(j,0,e),this},off:function(a,b,d){var e,f;if(!this._topics)return this;if(a===!0)return this._topics={},this;if(c.util.isObject(a)){for(var g in a)this.off(g,a[g]);return this}if(e=this._topics[a],!e)return this;if(b===!0)return this._topics[a]=[],this;for(var h=0,i=e.length;i>h;h++)if(f=e[h],!(f._bindfn_!==b&&f!==b||d&&f._scope_!==d)){e.splice(h,1);break}return this},emit:function(a,b){if(!this._topics)return this;var d,e,f=this._topics[a],g=f&&f.length,h=c.scratchpad();if(!g)return h.done(this);for(e=h.event(),e.topic=a,e.handler=d;g--;)d=f[g],d(b,e),d._one_&&f.splice(g,1);return h.done(this)},one:function(a,b,d){if(c.util.isObject(a)){for(var e in a)this.one(e,a[e],b,d);return this}return b._one_=!0,this.on(a,b,d),this}},c.util.pubsub=d}(),function(a){function b(){return l&&l.now?l.now()+l.timing.navigationStart:Date.now()}function d(){var c;a.requestAnimationFrame(d),j&&(c=b(),c&&k.emit("tick",c))}function e(){return j=!0,this}function f(){return j=!1,this}function g(a){return k.on("tick",a),this}function h(a){return k.off("tick",a),this}function i(){return!!j}var j=!0,k=c.util.pubsub(),l=a.performance;a.requestAnimationFrame?d():j=!1,c.util.ticker={now:b,start:e,stop:f,on:g,off:h,isActive:i}}(this),function(){var a=function(){return!0},b=c.util.indexOf,d=function(a,b){return function(c){return a(c[b])}},e=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){if(c.util.isArray(a)){if(f=e.length,f!==a.length)return!1;for(;f>g;){if(f--,-1===b(a,e[g])||-1===b(a,e[f]))return!1;g++}return!0}return b(e,a)>-1}return e===a}},f=function(a,b){var c=e(a,b);return function(a){return!c(a)}},g=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){for(f=e.length;f>g;){if(f--,b(a,e[g])>-1||b(a,e[f])>-1)return!0;g++}return!1}return b(a,e)>-1}},h=function(a,b){var c=g(a,b);return function(a){return!c(a)}},i=function(a){return a=new c.vector(a),function(b){var d=b.aabb();return c.aabb.contains(d,a)}},j=function(a){return a.next?function(b){for(var c=a;c;){if(!c(b))return!1;c=c.next}return!0}:a},k=function(a){return a.next?function(b){for(var c=a;c;){if(c(b))return!0;c=c.next}return!1}:a},l={$eq:e,$ne:f,$in:g,$nin:h,$at:i},m=function n(b,f){var g,h,i,m,o,p;if(f){if("$or"===f||"$and"===f){for(g=0,h=b.length;h>g;++g)p=n(b[g]),o=o?o.next=p:m=p;return"$or"===f?k(m):j(m)}if(g=l[f])return g(b);throw"Unknown query operation: "+f}for(g in b)i=b[g],p="$"===g[0]?n(i,g):c.util.isPlainObject(i)?d(n(i),g):e(i,g),o=o?o.next=p:m=p;return j(m||a)};c.query=m}(this),function(){var a={priority:0};c.behavior=d("behavior",{init:function(b){this.options=c.util.options(a),this.options(b)},applyTo:function(a){return this._targets=a===!0?null:c.util.uniq(a),this},getTargets:function(){return this._targets||(this._world?this._world._bodies:[])},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},connect:function(a){this.behave&&a.on("integrate:positions",this.behave,this,this.options.priority)},disconnect:function(a){this.behave&&a.off("integrate:positions",this.behave,this)},behave:null})}(),function(){function a(a,b,c,d){var e=d-b;b+=e/a,c+=e*(d-b)}function b(a,b,c,d){var e=1/a,f=d.get(0)-b.get(0),g=d.get(1)-b.get(1);b.add(f*e,g*e),f*=d.get(0)-b.get(0),g*=d.get(1)-b.get(1),c.add(f,g)}var e={hidden:!1,treatment:"dynamic",mass:1,restitution:1,cof:.8,view:null},f=1;c.body=d("body",{init:function(a){var b=this,d=c.vector;if(this.options=c.util.options(e,this),this.options.onChange(function(a){b.offset=new d(a.offset)}),this.options(a),this.state={pos:new d(this.x,this.y),vel:new d(this.vx,this.vy),acc:new d,angular:{pos:this.angle||0,vel:this.angularVelocity||0,acc:0},old:{pos:new d,vel:new d,acc:new d,angular:{pos:0,vel:0,acc:0}}},this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean=new d,this._sleepPosVariance=new d,this._sleepMeanK=0,delete this.x,delete this.y,delete this.vx,delete this.vy,delete this.angle,delete this.angularVelocity,0===this.mass)throw"Error: Bodies must have non-zero mass";this.uid=f++,this.geometry=c.geometry("point")},sleep:function(a){return a===!0?this.asleep=!0:a===!1?(this.asleep=!1,this._sleepMeanK=0,this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean.zero(),this._sleepPosVariance.zero(),this.sleepIdleTime=0):a&&!this.asleep&&this.sleepCheck(a),this.asleep},sleepCheck:function(d){var e=this._world&&this._world.options;if(!(this.sleepDisabled||e&&e.sleepDisabled)){{var f,g,h,i,j=c.scratchpad();j.vector(),j.vector()}if(d=d||0,i=this.geometry.aabb(),h=Math.max(i.hw,i.hh),this.asleep&&(g=this.state.vel.norm()+Math.abs(h*this.state.angular.vel),f=this.sleepSpeedLimit||e&&e.sleepSpeedLimit||0,g>=f))return this.sleep(!1),j.done();this._sleepMeanK++,b(this._sleepMeanK,this._sleepPosMean,this._sleepPosVariance,this.state.pos),a(this._sleepMeanK,this._sleepAngPosMean,this._sleepAngPosVariance,this.state.angular.pos),g=this._sleepPosVariance.norm()+Math.abs(h*this._sleepAngPosVariance),f=this.sleepVarianceLimit||e&&e.sleepVarianceLimit||0,f>=g?(f=this.sleepTimeLimit||e&&e.sleepTimeLimit||0,this.sleepIdleTime=(this.sleepIdleTime||0)+d,this.sleepIdleTime>f&&(this.asleep=!0)):this.sleep(!1),j.done()}},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},accelerate:function(a){return"dynamic"===this.treatment&&this.state.acc.vadd(a),this},applyForce:function(a,b){if("dynamic"!==this.treatment)return this;var d,e=c.scratchpad(),f=e.vector();return b&&this.moi&&(d=this.state,f.clone(b),this.state.angular.acc-=f.cross(a)/this.moi),this.accelerate(f.clone(a).mult(1/this.mass)),e.done(),this},getGlobalOffset:function(a){return a=a||new c.vector,a.clone(this.offset).rotate(this.state.angular.pos),a},aabb:function(){var a=this.state.angular.pos,b=c.scratchpad(),d=b.vector(),e=this.geometry.aabb(a);return this.getGlobalOffset(d),e.x+=this.state.pos._[0]+d._[0],e.y+=this.state.pos._[1]+d._[1],b.done(e)},toBodyCoords:function(a){return a.vsub(this.state.pos).rotate(-this.state.angular.pos)},toWorldCoords:function(a){return a.rotate(this.state.angular.pos).vadd(this.state.pos)},recalc:function(){return this}}),c.body.getCOM=function(a,b){var d,e,f,g=a&&a.length,h=0;if(b=b||new c.vector,!g)return b.zero();if(1===g)return b.clone(a[0].state.pos);for(b.zero(),f=0;g>f;f++)d=a[f],e=d.state.pos,b.add(e._[0]*d.mass,e._[1]*d.mass),h+=d.mass;return b.mult(1/h),b}}(),function(){c.geometry=d("geometry",{init:function(a){this.options=c.util.options(),this.options(a),this._aabb=new c.aabb},aabb:function(){return c.aabb.clone(this._aabb)},getFarthestHullPoint:function(a,b){return b=b||new c.vector,b.set(0,0)},getFarthestCorePoint:function(a,b){return b=b||new c.vector,b.set(0,0)}})}(),c.geometry.regularPolygonVertices=function(a,b){var c,d=[],e=2*Math.PI/a,f=0;for(c=0;a>c;c++)d.push({x:b*Math.cos(f),y:b*Math.sin(f)}),f+=e;return d},c.geometry.isPolygonConvex=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=b.vector(),g=!0,h=!1,i=a.length;if(!a||!i)return!1;if(3>i)return b.done(),g;d.clone(a[0]).vsub(f.clone(a[i-1]));for(var j=1;i>=j;++j){if(e.clone(a[j%i]).vsub(f.clone(a[(j-1)%i])),h===!1)h=d.cross(e);else if(h>0^d.cross(e)>0){g=!1;break}e.swap(d)}return b.done(),g},c.geometry.getPolygonMOI=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=0,h=0,i=a.length;if(2>i)return d.done(),0;if(2===i)return b=f.clone(a[1]).distSq(e.clone(a[0])),d.done(),b/12;e.clone(a[0]);for(var j=1;i>j;++j)f.clone(a[j]),b=Math.abs(f.cross(e)),g+=b*(f.normSq()+f.dot(e)+e.normSq()),h+=b,e.swap(f);return d.done(),g/(6*h)},c.geometry.isPointInPolygon=function(a,b){var d=c.scratchpad(),e=d.vector().clone(a),f=d.vector(),g=d.vector(),h=0,i=b.length;if(2>i)return h=e.equals(f.clone(b[0])),d.done(),h;if(2===i)return h=e.angle(f.clone(b[0])),h+=e.angle(f.clone(b[1])),d.done(),Math.abs(h)===Math.PI;f.clone(b[0]).vsub(e);for(var j=1;i>=j;++j)g.clone(b[j%i]).vsub(e),h+=g.angle(f),f.swap(g);return d.done(),Math.abs(h)>1e-6},c.geometry.getPolygonArea=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=0,g=a.length;if(3>g)return b.done(),0;d.clone(a[g-1]);for(var h=0;g>h;++h)e.clone(a[h]),f+=d.cross(e),d.swap(e);return b.done(),f/2},c.geometry.getPolygonCentroid=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=new c.vector,h=a.length;if(2>h)return d.done(),new c.vector(a[0]);if(2===h)return d.done(),new c.vector((a[1].x+a[0].x)/2,(a[1].y+a[0].y)/2);e.clone(a[h-1]);for(var i=0;h>i;++i)f.clone(a[i]),b=e.cross(f),e.vadd(f).mult(b),g.vadd(e),e.swap(f);return b=1/(6*c.geometry.getPolygonArea(a)),d.done(),g.mult(b)},c.geometry.nearestPointOnLine=function(a,b,d){var e,f,g=c.scratchpad(),h=g.vector().clone(a),i=g.vector().clone(b).vsub(h),j=g.vector().clone(d).vsub(h).vsub(i);return j.equals(c.vector.zero)?(g.done(),new c.vector(b)):(e=-j.dot(i)/j.normSq(),f=1-e,0>=f?(g.done(),new c.vector(d)):0>=e?(g.done(),new c.vector(b)):(h=new c.vector(d).mult(e).vadd(i.clone(b).mult(f)),g.done(),h))},function(){var a={drag:0};c.integrator=d("integrator",{init:function(b){this.options=c.util.options(a),this.options(b)},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},integrate:function(a,b){var c=this._world;return this.integrateVelocities(a,b),c&&c.emit("integrate:velocities",{bodies:a,dt:b}),this.integratePositions(a,b),c&&c.emit("integrate:positions",{bodies:a,dt:b}),this},connect:null,disconnect:null,integrateVelocities:function(){throw"The integrator.integrateVelocities() method must be overriden"},integratePositions:function(){throw"The integrator.integratePositions() method must be overriden"}})}(),function(){var e={meta:!1,metaRefresh:200,width:600,height:600,autoResize:!0};c.renderer=d("renderer",{init:function(d){var f=this,g="string"==typeof d.el?b.getElementById(d.el):d.el;this.options=c.util.options(e),this.options(d),this.el=g?g:b.body,this.container=g&&g.parentNode?g.parentNode:b.body,this.drawMeta=c.util.throttle(c.util.bind(this.drawMeta,this),this.options.metaRefresh),a.addEventListener("resize",c.util.throttle(function(){f.options.autoResize&&f.resize()}),100)},resize:function(a,b){void 0===a&&void 0===b&&(a=this.container.offsetWidth,b=this.container.offsetHeight),this.width=a||0,this.height=b||0},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},render:function(a,b){var c,d;this.beforeRender&&this.beforeRender(),this._world.emit("beforeRender",{renderer:this,bodies:a,meta:b}),this.options.meta&&this.drawMeta(b),this._interpolateTime=b.interpolateTime;for(var e=0,f=a.length;f>e;++e)c=a[e],d=c.view||(c.view=this.createView(c.geometry,c.styles)),c.hidden||this.drawBody(c,d);return this},createView:function(){throw"You must override the renderer.createView() method."},drawMeta:function(){throw"You must override the renderer.drawMeta() method."},drawBody:function(){throw"You must override the renderer.drawBody() method."}})}(),function(){var a=function e(a,b,c){for(var d,f,g=function(){return e(a,b,c)};d=a.shift();)if(f=d.apply(b,c),f&&f.then)return f.then(g)},b={timestep:6,maxIPF:4,webworker:!1,integrator:"verlet",sleepDisabled:!1,sleepSpeedLimit:.1,sleepVarianceLimit:2,sleepTimeLimit:500},d=function f(a,b){return this instanceof f?void this.init(a,b):new f(a,b)};d.prototype=c.util.extend({},c.util.pubsub.prototype,{init:function(d,e){var f=this;(c.util.isFunction(d)||c.util.isArray(d))&&(e=d,d={}),this._meta={fps:0,ipf:0},this._bodies=[],this._behaviors=[],this._integrator=null,this._renderer=null,this._paused=!1,this._warp=1,this._time=0,this.options=c.util.options(b),this.options.onChange(function(a){f.timestep(a.timestep)}),this.options(d),this.add(c.integrator(this.options.integrator)),c.util.isFunction(e)?a([e],this,[this,c]):c.util.isArray(e)&&a(e,this,[this,c])},options:null,add:function(a){var b=0,d=a&&a.length||0,e=c.util.isArray(a)?a[0]:a;if(!e)return this;do switch(e.type){case"behavior":this.addBehavior(e);break;case"integrator":this.integrator(e);break;case"renderer":this.renderer(e);break;case"body":this.addBody(e);break;default:throw'Error: failed to add item of unknown type "'+e.type+'" to world'}while(++b-1},integrator:function(a){return void 0===a?this._integrator:this._integrator===a?this:(this._integrator&&(this._integrator.setWorld(null),this.emit("remove:integrator",{integrator:this._integrator})),a&&(this._integrator=a,this._integrator.setWorld(this),this.emit("add:integrator",{integrator:this._integrator})),this)},renderer:function(a){return void 0===a?this._renderer:this._renderer===a?this:(this._renderer&&(this._renderer.setWorld(null),this.emit("remove:renderer",{renderer:this._renderer})),a&&(this._renderer=a,this._renderer.setWorld(this),this.emit("add:renderer",{renderer:this._renderer})),this)},timestep:function(a){return a?(this._dt=+a.toPrecision(4),this._maxJump=a*this.options.maxIPF,this):this._dt},wakeUpAll:function(){var a=0,b=this._bodies.length;for(a=0;b>a;a++)this._bodies[a].sleep(!1)},addBehavior:function(a){return this.has(a)?this:(a.setWorld(this),this._behaviors.push(a),this.emit("add:behavior",{behavior:a}),this)},getBehaviors:function(){return[].concat(this._behaviors)},removeBehavior:function(a){var b=this._behaviors;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:behavior",{behavior:a});break}return this},addBody:function(a){return this.has(a)?this:(a.setWorld(this),this._bodies.push(a),this.emit("add:body",{body:a}),this)},getBodies:function(){return[].concat(this._bodies)},removeBody:function(a){var b=this._bodies;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:body",{body:a});break}return this},findOne:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.find(b._bodies,d)||!1},find:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.filter(b._bodies,d)},iterate:function(a){this._integrator.integrate(this._bodies,a)},step:function(a){var b,d,e,f=this._time,g=this._warp,h=1/g,i=this._dt,j=i*h,k=this._maxJump*h,l=this._meta;if(this._paused||void 0===this._animTime)return this._animTime=a||this._animTime||c.util.ticker.now(),this._paused||this.emit("step",l),this;if(a=a||this._animTime+j,b=a-this._animTime,b>k&&(this._animTime=a-k,b=k),d=b*g,e=f+d-i,this.emit("beforeStep"),e>=f)for(;e>=f;)f+=i,this._animTime+=j,this._time=f,this.iterate(i);return l.fps=1e3/(a-this._lastTime),l.ipf=(d/i).toFixed(2),l.interpolateTime=i+e-f,this._lastTime=a,this.emit("step",l),this},warp:function(a){return void 0===a?this._warp:(this._warp=a||1,this)},render:function(){if(!this._renderer)throw"No renderer added to world";return this._renderer.render(this._bodies,this._meta),this.emit("render",{bodies:this._bodies,meta:this._meta,renderer:this._renderer}),this},pause:function(){return this._paused=!0,this.emit("pause"),this},unpause:function(){return this._paused=!1,this.emit("unpause"),this},isPaused:function(){return!!this._paused},destroy:function(){var a=this;a.pause(),this.emit("destroy"),a.off(!0),a.remove(a.getBodies()),a.remove(a.getBehaviors()),a.integrator(null),a.renderer(null)}}),c.world=d}(),c.integrator("verlet",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=b*b,e=1-this.options.drag,f=null,g=this.prevDt||b,h=.5*(d+b*g),i=0,j=a.length;j>i;++i)f=a[i],c=f.state,"static"===f.treatment||f.sleep(b)?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(c.vel.equals(c.old.vel)&&f.started()?c.vel.clone(c.pos).vsub(c.old.pos):(c.old.pos.clone(c.pos).vsub(c.vel),c.vel.mult(b)),e&&c.vel.mult(e),c.vel.vadd(c.acc.mult(h)),c.vel.mult(1/b),c.old.vel.clone(c.vel),c.acc.zero(),c.angular.vel===c.old.angular.vel&&f.started()?c.angular.vel=c.angular.pos-c.old.angular.pos:(c.old.angular.pos=c.angular.pos-c.angular.vel,c.angular.vel*=b),c.angular.vel+=c.angular.acc*h,c.angular.vel/=b,c.old.angular.vel=c.angular.vel,c.angular.acc=0,f.started(!0)) -},integratePositions:function(a,b){for(var c,d=null,e=this.prevDt||b,f=b/e,g=0,h=a.length;h>g;++g)d=a[g],c=d.state,"static"===d.treatment||d.sleep()||(c.vel.mult(b*f),c.old.pos.clone(c.pos),c.pos.vadd(c.vel),c.vel.mult(1/(b*f)),c.old.vel.clone(c.vel),c.angular.vel*=b*f,c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel,c.angular.vel/=b*f,c.old.angular.vel=c.angular.vel);this.prevDt=b}}}),c.geometry("point",function(){}),c.body("point",function(a){return{init:function(b){a.init.call(this,b),this.moi=0}}}),c.geometry("circle",function(a){var b={radius:1};return{init:function(d){a.init.call(this,d),this.options.defaults(b),this.options.onChange(function(a){this.radius=a.radius}),this.options(d),this._aabb=c.aabb(),this.radius=this.options.radius},aabb:function(){var a=this.radius;return this._aabb.hw!==a&&(this._aabb=c.aabb(-a,-a,a,a)),c.aabb.clone(this._aabb)},getFarthestHullPoint:function(a,b){return b=b||new c.vector,b.clone(a).normalize().mult(this.radius)},getFarthestCorePoint:function(a,b,d){return b=b||new c.vector,b.clone(a).normalize().mult(this.radius-d)}}}),c.geometry("compound",function(a){var b={};return{init:function(c){a.init.call(this,c),this.options.defaults(b),this.options(c),this.children=[]},addChild:function(a,b,d){return this._aabb=null,this.children.push({g:a,pos:new c.vector(b),angle:d}),this},clear:function(){return this._aabb=null,this.children=[],this},aabb:function(a){if(!a&&this._aabb)return c.aabb.clone(this._aabb);var b,d,e,f=c.scratchpad(),g=c.vector();a=a||0;for(var h=0,i=this.children.length;i>h;h++)d=this.children[h],b=d.g.aabb(a+d.angle),g.clone(d.pos),a&&g.rotate(a),b.x+=g._[0],b.y+=g._[1],e=e?c.aabb.union(e,b,!0):b;return a||(this._aabb=c.aabb.clone(e)),f.done(e)},getFarthestHullPoint:function(a,b){var d,e,f=this.children.length,g=c.scratchpad(),h=g.vector(),i=0,j=0;for(b=b||new c.vector,e=0;f>e;e++)d=this.children[e],d.g.getFarthestHullPoint(a.rotate(-d.angle),h),i=h.rotate(d.angle).vadd(d.pos).proj(a.rotate(d.angle)),i>j&&(j=i,b.swap(h));return g.done(b)},getFarthestCorePoint:function(a,b,d){var e,f,g=this.children.length,h=c.scratchpad(),i=h.vector(),j=0,k=0;for(b=b||new c.vector,f=0;g>f;f++)e=this.children[f],e.g.getFarthestCorePoint(a.rotate(-e.angle),i,d),j=i.rotate(e.angle).vadd(e.pos).proj(a.rotate(e.angle)),j>k&&(k=j,b.swap(i));return h.done(b)}}}),c.geometry("convex-polygon",function(a){var b="Error: The vertices specified do not match that of a _convex_ polygon.",d={};return{init:function(b){var c=this;a.init.call(this,b),this.options.defaults(d),this.options.onChange(function(a){c.setVertices(a.vertices||[])}),this.options(b),c.setVertices(this.options.vertices||[])},setVertices:function(a){var d=c.scratchpad(),e=d.transform(),f=this.vertices=[];if(!c.geometry.isPolygonConvex(a))throw b;e.setRotation(0),e.setTranslation(c.geometry.getPolygonCentroid(a).negate());for(var g=0,h=a.length;h>g;++g)f.push(new c.vector(a[g]).translate(e));return this._area=c.geometry.getPolygonArea(f),this._aabb=!1,d.done(this)},aabb:function(a){if(!a&&this._aabb)return c.aabb.clone(this._aabb);var b,d=c.scratchpad(),e=d.vector(),f=d.transform().setRotation(a||0),g=d.vector().set(1,0).rotateInv(f),h=d.vector().set(0,1).rotateInv(f),i=this.getFarthestHullPoint(g,e).proj(g),j=-this.getFarthestHullPoint(g.negate(),e).proj(g),k=this.getFarthestHullPoint(h,e).proj(h),l=-this.getFarthestHullPoint(h.negate(),e).proj(h);return b=c.aabb(j,l,i,k),a||(this._aabb=c.aabb.clone(b)),d.done(),b},getFarthestHullPoint:function(a,b,d){var e,f,g,h=this.vertices,i=h.length,j=2;if(b=b||new c.vector,2>i)return d&&(d.idx=0),b.clone(h[0]);if(f=h[0].dot(a),e=h[1].dot(a),2===i)return g=e>=f?1:0,d&&(d.idx=g),b.clone(h[g]);if(e>=f){for(;i>j&&e>=f;)f=e,e=h[j].dot(a),j++;return e>=f&&j++,g=j-2,d&&(d.idx=j-2),b.clone(h[g])}for(j=i;j>1&&f>=e;)j--,e=f,f=h[j].dot(a);return g=(j+1)%i,d&&(d.idx=g),b.clone(h[g])},getFarthestCorePoint:function(a,b,d){var e,f=c.scratchpad(),g=f.vector(),h=f.vector(),i=this.vertices,j=i.length,k=this._area>0,l={};return b=this.getFarthestHullPoint(a,b,l),g.clone(i[(l.idx+1)%j]).vsub(b).normalize().perp(k),h.clone(i[(l.idx-1+j)%j]).vsub(b).normalize().perp(!k),e=d/(1+g.dot(h)),b.vadd(g.vadd(h).mult(e)),f.done(),b}}}),c.geometry("rectangle",function(a){var b={};return{init:function(c){var d=this;a.init.call(this,c),this.options.defaults(b),this.options.onChange(function(){d.width=d.options.width||1,d.height=d.options.height||1}),this.options(c)},aabb:function(a){if(!a)return c.aabb(this.width,this.height);var b=c.scratchpad(),d=b.vector(),e=b.transform().setRotation(a||0),f=b.vector().set(1,0).rotateInv(e),g=b.vector().set(0,1).rotateInv(e),h=this.getFarthestHullPoint(f,d).proj(f),i=-this.getFarthestHullPoint(f.negate(),d).proj(f),j=this.getFarthestHullPoint(g,d).proj(g),k=-this.getFarthestHullPoint(g.negate(),d).proj(g);return b.done(),c.aabb(i,k,h,j)},getFarthestHullPoint:function(a,b){b=b||new c.vector;var d=a.x,e=a.y;return d=0===d?0:0>d?.5*-this.width:.5*this.width,e=0===e?0:0>e?.5*-this.height:.5*this.height,b.set(d,e)},getFarthestCorePoint:function(a,b,c){var d,e;return b=this.getFarthestHullPoint(a,b),d=b.x,e=b.y,b.x=0===d?0:0>d?d+c:d-c,b.y=0===e?0:0>e?e+c:e-c,b}}}),c.body("circle",function(a){var b={radius:1};return{init:function(d){a.init.call(this,d),d=c.util.extend({},b,d),this.geometry=c.geometry("circle",{radius:d.radius}),this.recalc()},recalc:function(){a.recalc.call(this),this.moi=this.mass*this.geometry.radius*this.geometry.radius/2}}}),c.body("compound",function(a){return{init:function(b){a.init.call(this,b),this.mass=0,this.moi=0,this.children=[],this.geometry=c.geometry("compound"),this.addChildren(b.children)},connect:function(){if(this.mass<=0)throw"Can not add empty compound body to world."},addChild:function(a){return this.addChildren([a]),this},addChildren:function(a){var b,d,e,f=this,g=c.scratchpad(),h=g.vector().zero(),i=a&&a.length,j=0;if(!i)return g.done(this);for(e=0;i>e;e++)b=a[e],b._world&&b._world.remove(b),this.children.push(b),this.geometry.addChild(b.geometry,new c.vector(b.offset).rotate(b.state.angular.pos).vadd(b.state.pos),b.state.angular.pos),d=b.state.pos,h.add(d._[0]*b.mass,d._[1]*b.mass),j+=b.mass;return this.mass+=j,h.mult(1/this.mass),this.offset.vsub(h),this._world&&this._world.one("render",function(){f.view=null}),this.recalc(),g.done(this)},clear:function(){return this._aabb=null,this.moi=0,this.mass=0,this.offset.zero(),this.children=[],this.geometry.clear(),this},refreshGeometry:function(){this.geometry.clear();for(var a,b=0,d=this.children.length;d>b;b++)a=this.children[b],this.geometry.addChild(a.geometry,new c.vector(a.state.pos).vadd(a.offset),a.state.angular.pos);return this},recalc:function(){a.recalc.call(this);for(var b,c=0,d=0,e=this.children.length;e>d;d++)b=this.children[d],b.recalc(),c+=b.moi+b.mass*b.state.pos.normSq();return this.moi=c,this}}}),c.body("convex-polygon",function(a){var b={};return{init:function(d){a.init.call(this,d),d=c.util.extend({},b,d),this.geometry=c.geometry("convex-polygon",{vertices:d.vertices}),this.recalc()},recalc:function(){a.recalc.call(this),this.moi=c.geometry.getPolygonMOI(this.geometry.vertices)}}}),c.body("rectangle",function(a){var b={};return{init:function(d){a.init.call(this,d),d=c.util.extend({},b,d),this.geometry=c.geometry("rectangle",{width:d.width,height:d.height}),this.recalc()},recalc:function(){var b=this.geometry.width,c=this.geometry.height;a.recalc.call(this),this.moi=(b*b+c*c)*this.mass/12}}}),c.behavior("attractor",function(a){var b={pos:null,strength:1,order:2,max:!1,min:!1};return{init:function(d){var e=this;this._pos=new c.vector,a.init.call(this),this.options.defaults(b),this.options.onChange(function(a){e._maxDist=a.max===!1?1/0:a.max,e._minDist=a.min?a.min:10,e.position(a.pos)}),this.options(d)},position:function(a){var b=this;return a?(this._pos.clone(a),b):this._pos.values()},behave:function(){for(var a,b,d,e=this.getTargets(),f=this.options.order,g=this.options.strength,h=this._minDist,i=this._maxDist,j=c.scratchpad(),k=j.vector(),l=0,m=e.length;m>l;l++)a=e[l],k.clone(this._pos),k.vsub(a.state.pos),b=k.norm(),b>h&&i>b&&(d=g/Math.pow(b,f),a.accelerate(k.normalize().mult(d)));j.done()}}}),c.behavior("body-collision-detection",function(a){var b=[],d=function(a,d){var e=c.util.pairHash(a.uid,d.uid),f=b[e];return f||(f=b[e]=function(b){var c=f.tA,e=f.tB,g=f.tmpv1,h=f.tmpv2;return f.useCore?(g=a.geometry.getFarthestCorePoint(b.rotateInv(c),g,f.marginA),h=d.geometry.getFarthestCorePoint(b.rotate(c).rotateInv(e).negate(),h,f.marginB)):(g=a.geometry.getFarthestHullPoint(b.rotateInv(c),g),h=d.geometry.getFarthestHullPoint(b.rotate(c).rotateInv(e).negate(),h)),g.vadd(a.offset).transform(c),h.vadd(d.offset).transform(e),b.negate().rotate(e),{a:g.values(),b:h.values(),pt:g.vsub(h).values()}},f.tA=new c.transform,f.tB=new c.transform,f.tmpv1=new c.vector,f.tmpv2=new c.vector),f.useCore=!1,f.margin=0,f.tA.setRotation(a.state.angular.pos).setTranslation(a.state.pos),f.tB.setRotation(d.state.angular.pos).setTranslation(d.state.pos),f.bodyA=a,f.bodyB=d,f},e=function(a,b){var e,f,g,h,i=c.scratchpad(),j=i.vector(),k=i.vector(),l=i.vector(),m=!1,n=a.aabb(),o=Math.min(n.hw,n.hh),p=b.aabb(),q=Math.min(p.hw,p.hh);if(g=d(a,b),j.clone(a.state.pos).vadd(a.getGlobalOffset(l)).vsub(b.state.pos).vsub(b.getGlobalOffset(l)),f=c.gjk(g,j,!0),f.overlap){for(m={bodyA:a,bodyB:b},k.clone(a.state.pos).vsub(a.state.old.pos).vsub(b.state.pos).vadd(b.state.old.pos),h=Math.abs(k.proj(j)),h=Math.max(.5*h,1),g.useCore=!0,g.marginA=0,g.marginB=0;(f.overlap||0===f.distance)&&(g.marginA=e)return i.done(!1);m.overlap=e,m.norm=j.clone(f.closest.b).vsub(k.clone(f.closest.a)).normalize().values(),m.mtv=j.mult(e).values(),m.pos=j.clone(m.norm).mult(g.marginA).vadd(k.clone(f.closest.a)).vsub(a.state.pos).values()}return i.done(m)},f=function(a,b){var d,e=c.scratchpad(),f=e.vector(),g=e.vector(),h=!1;return f.clone(b.state.pos).vadd(b.getGlobalOffset(g)).vsub(a.state.pos).vsub(a.getGlobalOffset(g)),d=f.norm()-(a.geometry.radius+b.geometry.radius),f.equals(c.vector.zero)&&f.set(1,0),0>=d&&(h={bodyA:a,bodyB:b,norm:f.normalize().values(),mtv:f.mult(-d).values(),pos:f.mult(-a.geometry.radius/d).vadd(g).values(),overlap:-d}),e.done(h)},g=function i(a,b){if(!("static"!==a.treatment&&"kinematic"!==a.treatment||"static"!==b.treatment&&"kinematic"!==b.treatment))return!1;if("circle"===a.geometry.name&&"circle"===b.geometry.name)return f(a,b);if("compound"===a.geometry.name||"compound"===b.geometry.name){var d,g,h,j,k="compound"===a.geometry.name,l=k?a:b,m=k?b:a,n=[],o=c.scratchpad(),p=(o.vector(),o.vector()),q=m.aabb();for(h=0,j=l.children.length;j>h;h++){if(g=l.children[h],p.clone(g.state.pos),g.offset.vadd(p.vadd(l.offset).rotate(-g.state.angular.pos)),g.state.pos.clone(l.state.pos),g.state.angular.pos+=l.state.angular.pos,c.aabb.overlap(q,g.aabb()))if(d=i(m,g),d instanceof Array)for(var r,s=0,t=d.length;t>s;s++)r=d[s],r.bodyA===g?r.bodyA=l:r.bodyB=l,n.push(r);else d&&(d.bodyA===g?d.bodyA=l:d.bodyB=l,n.push(d));g.state.angular.pos-=l.state.angular.pos,g.offset.vsub(p),g.state.pos.clone(p.rotate(g.state.angular.pos).vsub(l.offset))}return o.done(n)}return e(a,b)},h={check:"collisions:candidates",channel:"collisions:detected"};return{init:function(b){a.init.call(this),this.options.defaults(h),this.options(b)},connect:function(a){this.options.check===!0?a.on("integrate:velocities",this.checkAll,this):a.on(this.options.check,this.check,this)},disconnect:function(a){this.options.check===!0?a.off("integrate:velocities",this.checkAll,this):a.off(this.options.check,this.check,this)},check:function(a){for(var b,d,e,f=a.candidates,h=this.getTargets(),i=[],j=this.prevContacts||{},k={},l=c.util.pairHash,m=0,n=f.length;n>m;++m)if(b=f[m],h===this._world._bodies||c.util.indexOf(h,b.bodyA)>-1&&c.util.indexOf(h,b.bodyB)>-1)if(d=g(b.bodyA,b.bodyB),d instanceof Array)for(var o,p=0,q=d.length;q>p;p++)o=d[p],o&&(e=l(b.bodyA.uid,b.bodyB.uid),k[e]=!0,o.collidedPreviously=j[e],i.push(o));else d&&(e=l(b.bodyA.uid,b.bodyB.uid),k[e]=!0,d.collidedPreviously=j[e],i.push(d));this.prevContacts=k,i.length&&this._world.emit(this.options.channel,{collisions:i})},checkAll:function(a){for(var b,d,e,f,h=this.getTargets(),i=(a.dt,[]),j=this.prevContacts||{},k={},l=c.util.pairHash,m=0,n=h.length;n>m;m++){b=h[m];for(var o=m+1;n>o;o++)if(d=h[o],e=g(b,d),e instanceof Array)for(var p,q=0,r=e.length;r>q;q++)p=e[q],p&&(f=l(b.uid,d.uid),k[f]=!0,p.collidedPreviously=j[f],i.push(p));else e&&(f=l(b.uid,d.uid),k[f]=!0,e.collidedPreviously=j[f],i.push(e))}this.prevContacts=k,i.length&&this._world.emit(this.options.channel,{collisions:i})}}}),c.behavior("body-impulse-response",function(a){var b={check:"collisions:detected",mtvThreshold:1,bodyExtractDropoff:.5,forceWakeupAboveOverlapThreshold:!0};return{init:function(c){a.init.call(this),this.options.defaults(b),this.options(c)},applyTo:!1,connect:function(a){a.on(this.options.check,this.respond,this)},disconnect:function(a){a.off(this.options.check,this.respond,this)},collideBodies:function(a,b,d,e,f,g){var h="static"===a.treatment||"kinematic"===a.treatment,i="static"===b.treatment||"kinematic"===b.treatment,j=c.scratchpad(),k=j.vector().clone(f);if(h&&i)return void j.done();var l,m,n,o=h?0:1/a.moi,p=i?0:1/b.moi,q=h?0:1/a.mass,r=i?0:1/b.mass,s=a.restitution*b.restitution,t=a.cof*b.cof,u=j.vector().clone(d),v=j.vector().clone(u).perp(),w=j.vector(),x=j.vector().clone(e),y=j.vector().clone(e).vadd(a.state.pos).vsub(b.state.pos),z=a.state.angular.vel,A=b.state.angular.vel,B=j.vector().clone(b.state.vel).vadd(w.clone(y).perp().mult(A)).vsub(a.state.vel).vsub(w.clone(x).perp().mult(z)),C=x.proj(u),D=x.proj(v),E=y.proj(u),F=y.proj(v),G=B.proj(u),H=B.proj(v);return g&&(k.normSq()=0?void j.done():(o=1/0===o?0:o,p=1/0===p?0:p,l=-((1+s)*G)/(q+r+o*D*D+p*F*F),h?(b.state.vel.vadd(u.mult(l*r)),b.state.angular.vel-=l*p*F):i?(a.state.vel.vsub(u.mult(l*q)),a.state.angular.vel+=l*o*D):(b.state.vel.vadd(u.mult(l*r)),b.state.angular.vel-=l*p*F,a.state.vel.vsub(u.mult(q*b.mass)),a.state.angular.vel+=l*o*D),t&&H&&(n=Math.abs(H)/(q+r+o*C*C+p*E*E),m=0>H?-1:1,l=t*Math.abs(l),l=Math.min(l,n),l*=m,h?(b.state.vel.vsub(v.mult(l*r)),b.state.angular.vel-=l*p*E):i?(a.state.vel.vadd(v.mult(l*q)),a.state.angular.vel+=l*o*C):(b.state.vel.vsub(v.mult(l*r)),b.state.angular.vel-=l*p*E,a.state.vel.vadd(v.mult(q*b.mass)),a.state.angular.vel+=l*o*C)),a.sleep()&&a.sleepCheck(),b.sleep()&&b.sleepCheck(),void j.done())},respond:function(a){for(var b,d=this,e=c.util.shuffle(a.collisions),f=0,g=e.length;g>f;++f)b=e[f],d.collideBodies(b.bodyA,b.bodyB,b.norm,b.pos,b.mtv,b.collidedPreviously)}}}),c.behavior("constant-acceleration",function(a){var b={acc:{x:0,y:4e-4}};return{init:function(d){a.init.call(this),this.options.defaults(b),this.options(d),this._acc=new c.vector,this.setAcceleration(this.options.acc),delete this.options.acc},setAcceleration:function(a){return this._acc.clone(a),this},behave:function(){for(var a=this.getTargets(),b=0,c=a.length;c>b;++b)a[b].accelerate(this._acc)}}}),c.behavior("edge-collision-detection",function(a){var b=function(a,b,d){var e,f=a.aabb(),g=c.scratchpad(),h=a.getGlobalOffset(g.vector()),i=g.transform(),j=g.vector(),k=g.vector(),l=!1,m=[];return e=f.x+f.hw-b.max.x,e>=0&&(j.set(1,0).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:1,y:0},mtv:{x:e,y:0},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),e=f.y+f.hh-b.max.y,e>=0&&(j.set(0,1).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:0,y:1},mtv:{x:0,y:e},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),e=b.min.x-(f.x-f.hw),e>=0&&(j.set(-1,0).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:-1,y:0},mtv:{x:-e,y:0},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),e=b.min.y-(f.y-f.hh),e>=0&&(j.set(0,-1).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:0,y:-1},mtv:{x:0,y:-e},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),g.done(),m},d=function(a,c,d){return b(a,c,d)},e={aabb:null,restitution:.99,cof:1,channel:"collisions:detected"};return{init:function(b){a.init.call(this),this.options.defaults(e),this.options(b),this.setAABB(this.options.aabb),this.restitution=this.options.restitution,this.body=c.body("point",{treatment:"static",restitution:this.options.restitution,cof:this.options.cof})},setAABB:function(a){if(!a)throw"Error: aabb not set";return this._edges={min:{x:a.x-a.hw,y:a.y-a.hh},max:{x:a.x+a.hw,y:a.y+a.hh}},this},connect:function(a){a.on("integrate:positions",this.checkAll,this,2)},disconnect:function(a){a.off("integrate:positions",this.checkAll,this,2)},checkAll:function(a){for(var b,e,f,g=this.getTargets(),h=(a.dt,[]),i=this._edges,j=this.body,k=this.prevContacts||{},l={},m=c.util.pairHash,n=0,o=g.length;o>n;n++)if(b=g[n],"dynamic"===b.treatment&&(e=d(b,i,j))){f=m(b.uid,j.uid);for(var p=0,q=e.length;q>p;p++)l[f]=!0,e[p].collidedPreviously=k[f];h.push.apply(h,e)}this.prevContacts=l,h.length&&this._world.emit(this.options.channel,{collisions:h})}}}),c.behavior("interactive",function(d){if(!b)return{};var e={el:null,moveThrottle:10,minVel:{x:-5,y:-5},maxVel:{x:5,y:5}},f=function(a){var b=0,c=0;if(a.offsetParent)do b+=a.offsetLeft,c+=a.offsetTop;while(a=a.offsetParent);return{left:b,top:c}};return{init:function(a){var g=this;if(d.init.call(this),this.options.defaults(e),this.options(a),this.bodyData={},this.bodyDataByUID={},this.el="string"==typeof this.options.el?b.getElementById(this.options.el):this.options.el,!this.el)throw"No DOM element specified";g.grab=function(a){var b,d,e,h,i,j,k,l;if(g._world)for(a.changedTouches||(a.changedTouches=[a]),i=f(a.target),k=0,l=a.changedTouches.length;l>k;k++)h=a.changedTouches[k],e=h.identifier||h.pointerId||"mouse",b={idx:e,x:h.pageX-i.left,y:h.pageY-i.top},d=g._world.findOne({$at:new c.vector(b),$in:g.getTargets()}),d?(d.state.vel.zero(),d.state.angular.vel=0,d.isGrabbed=!0,j=g.bodyData[e]||{},j.body=d,d.sleep(!1),j.time=c.util.ticker.now(),j.treatment=g.bodyDataByUID[d.uid]?g.bodyDataByUID[d.uid].treatment:d.treatment,d.treatment="kinematic",j.pos=j.pos||new c.vector,j.pos.clone(b),j.offset=j.offset||new c.vector,j.offset.clone(b).vsub(d.state.pos),j.oldPos=j.oldPos||new c.vector,j.oldPos.clone(b),b.body=d,g.bodyData[e]=j,g.bodyDataByUID[d.uid]=j,g._world.emit("interact:grab",b)):g._world.emit("interact:poke",b)},g.move=c.util.throttle(function(a){var b,d,e,h,i,j,k,l;if(g._world)for(a.changedTouches||(a.changedTouches=[a]),i=f(g.el),k=0,l=a.changedTouches.length;l>k;k++)h=a.changedTouches[k],e=h.identifier||h.pointerId||"mouse",b={idx:e,x:h.pageX-i.left,y:h.pageY-i.top},j=g.bodyData[e],j&&(d=j.body,d.sleep(!1),j.time=c.util.ticker.now(),j.oldPos.clone(j.pos),j.pos.clone(b),b.body=d),g._world.emit("interact:move",b)},g.options.moveThrottle),g.release=function(a){var b,d,e,h,i,j,k,l,m;if(g._world)for(a.changedTouches||(a.changedTouches=[a]),l=0,m=a.changedTouches.length;m>l;l++)i=f(g.el),h=a.changedTouches[l],e=h.identifier||h.pointerId||"mouse",b={idx:e,x:h.pageX-i.left,y:h.pageY-i.top},j=g.bodyData[e],j&&(d=j.body,d.sleep(!1),j.pos.clone(b),k=Math.max(c.util.ticker.now()-j.time,g.options.moveThrottle),d.treatment=j.treatment,d.state.vel.clone(j.pos).vsub(j.oldPos).mult(1/k),d.state.vel.clamp(g.options.minVel,g.options.maxVel),d.isGrabbed=!1,b.body=d,delete d.isGrabbed),g._world.emit("interact:release",b),delete g.bodyData[e]}},connect:function(b){b.on("integrate:positions",this.behave,this),a.PointerEvent?(this.el.addEventListener("pointerdown",this.grab),a.addEventListener("pointermove",this.move),a.addEventListener("pointerup",this.release)):(this.el.addEventListener("mousedown",this.grab),this.el.addEventListener("touchstart",this.grab),a.addEventListener("mousemove",this.move),a.addEventListener("touchmove",this.move),a.addEventListener("mouseup",this.release),a.addEventListener("touchend",this.release))},disconnect:function(b){b.off("integrate:positions",this.behave,this),a.PointerEvent?(this.el.removeEventListener("pointerdown",this.grab),a.removeEventListener("pointermove",this.move),a.removeEventListener("pointerup",this.release)):(this.el.removeEventListener("mousedown",this.grab),this.el.removeEventListener("touchstart",this.grab),a.removeEventListener("mousemove",this.move),a.removeEventListener("touchmove",this.move),a.removeEventListener("mouseup",this.release),a.removeEventListener("touchend",this.release))},behave:function(a){var b,c,d,e=this,f=Math.max(a.dt,e.options.moveThrottle);for(var g in e.bodyData)d=e.bodyData[g],c=d.body,b=c.state,b.vel.clone(d.pos).vsub(d.offset).vsub(b.pos).mult(1/f)}}}),c.behavior("newtonian",function(a){var b={strength:1,max:!1,min:!1};return{init:function(c){var d=this;a.init.call(this),this.options.defaults(b),this.options.onChange(function(a){d._maxDistSq=a.max===!1?1/0:a.max*a.max,d._minDistSq=a.min?a.min*a.min:100*a.strength}),this.options(c)},behave:function(){for(var a,b,d,e,f=this.getTargets(),g=this.options.strength,h=this._minDistSq,i=this._maxDistSq,j=c.scratchpad(),k=j.vector(),l=0,m=f.length;m>l;l++){a=f[l];for(var n=l+1;m>n;n++)b=f[n],k.clone(b.state.pos),k.vsub(a.state.pos),d=k.normSq(),d>h&&i>d&&(e=g/d,a.accelerate(k.normalize().mult(e*b.mass)),b.accelerate(k.mult(a.mass/b.mass).negate()))}j.done()}}}),c.behavior("sweep-prune",function(a){var b=1,d=function(){return b++},e={x:0,y:1},f=2,g=c.util.pairHash;return{init:function(b){a.init.call(this),this.options.defaults({channel:"collisions:candidates"}),this.options(b),this.encounters=[],this.candidates=[],this.clear()},clear:function(){this.tracked=[],this.pairs=[],this.intervalLists=[];for(var a=0;f>a;++a)this.intervalLists[a]=[]},connect:function(a){a.on("add:body",this.trackBody,this),a.on("remove:body",this.untrackBody,this),a.on("integrate:positions",this.sweep,this,1);for(var b=a.getBodies(),c=0,d=b.length;d>c;++c)this.trackBody({body:b[c]})},disconnect:function(a){a.off("add:body",this.trackBody,this),a.off("remove:body",this.untrackBody,this),a.off("integrate:positions",this.sweep,this,1),this.clear()},broadPhase:function(){return this.updateIntervals(),this.sortIntervalLists(),this._world&&this._world.emit("sweep-prune:intervals",this.intervalLists),this.checkOverlaps()},sortIntervalLists:function(){for(var a,b,c,d,e,g,h,i,j,k=0;f>k;++k)for(a=this.intervalLists[k],c=0,b=a.length,j=k;++c0&&(i>g||i===g&&h.type&&!e.type);)a[d]=h,d--,h=a[d-1],i=h&&h.val.get(j);a[d]=e}},getPair:function(a,b,c){var d=g(a.id,b.id);if(d===!1)return null;var e=this.pairs[d];if(!e){if(!c)return null;e=this.pairs[d]={bodyA:a.body,bodyB:b.body,flag:1}}return c&&(e.flag=1),e},checkOverlaps:function(){var a,b,d,g,h,i,j,k,l,m=1<q;++q)for(a=0===q,h=this.intervalLists[q],j=0,i=h.length;i>j;j++)if(g=h[j],b=g.tracker,g.type)for(k=o,k=o-1;k>=0;k--)d=n[k],d===b?(o-1>k?n[k]=n.pop():n.pop(),o--):(l=this.getPair(b,d,a),l&&l.flag=0;)a=d[e],b=a.interval,c=a.body.aabb(),b.min.val.clone(c).sub(c.hw,c.hh),b.max.val.clone(c).add(c.hw,c.hh)},trackBody:function(a){var b=a.body,e={id:d(),body:b},g={min:{type:!1,val:new c.vector,tracker:e},max:{type:!0,val:new c.vector,tracker:e}};e.interval=g,this.tracked.push(e);for(var h=0;f>h;++h)this.intervalLists[h].push(g.min,g.max)},untrackBody:function(a){for(var b,c,d,e,g=a.body,h=this.tracked,i=0,j=h.length;j>i;++i)if(d=h[i],d.body===g){h.splice(i,1);for(var k=0;f>k;++k){e=0,b=this.intervalLists[k];for(var l=0,m=b.length;m>l;++l)if(c=b[l],c===d.interval.min||c===d.interval.max){if(b.splice(l,1),l--,j--,e>0)break;e++}}break}},sweep:function(){var a,b=this;a=b.broadPhase(),a.length&&this._world.emit(this.options.channel,{candidates:a})}}}),c.behavior("verlet-constraints",function(a){var b=2*Math.PI,d={iterations:2};return{init:function(b){a.init.call(this),this.options.defaults(d),this.options(b),this._distanceConstraints=[],this._angleConstraints=[]},connect:function(a){var b=a.integrator();if(b&&b.name.indexOf("verlet")<0)throw'The rigid constraint manager needs a world with a "verlet" compatible integrator.';a.on("integrate:positions",this.resolve,this)},disconnect:function(a){a.off("integrate:positions",this.resolve,this)},drop:function(){return this._distanceConstraints=[],this._angleConstraints=[],this},distanceConstraint:function(a,b,d,e){var f;return a&&b?(f={id:c.util.uniqueId("dis-constraint"),type:"dis",bodyA:a,bodyB:b,stiffness:d||.5,targetLength:e||b.state.pos.dist(a.state.pos)},f.targetLengthSq=f.targetLength*f.targetLength,this._distanceConstraints.push(f),f):!1},angleConstraint:function(a,b,d,e,f){var g;return a&&b?(g={id:c.util.uniqueId("ang-constraint"),type:"ang",bodyA:a,bodyB:b,bodyC:d,stiffness:e||.5,targetAngle:f||b.state.pos.angle2(a.state.pos,d.state.pos)},this._angleConstraints.push(g),g):!1},remove:function(a){var b,d,e,f,g;if(e=c.util.isObject(a),d=e?a.type:a.substr(0,3),b="ang"===d?this._angleConstraints:this._distanceConstraints,e){for(f=0,g=b.length;g>f;++f)if(b[f]===a)return b.splice(f,1),this}else for(f=0,g=b.length;g>f;++f)if(b[f].id===a)return b.splice(f,1),this;return this},resolveAngleConstraints:function(a){for(var d,e,f,g,h=this._angleConstraints,i=c.scratchpad(),j=i.transform(),k=0,l=h.length;l>k;++k)d=h[k],e=d.bodyB.state.pos.angle2(d.bodyA.state.pos,d.bodyC.state.pos),f=e-d.targetAngle,f&&(f<=-Math.PI?f+=b:f>=Math.PI&&(f-=b),j.setTranslation(d.bodyB.state.pos),f*=-a*d.stiffness,"dynamic"===d.bodyA.treatment&&"dynamic"===d.bodyB.treatment&&"dynamic"===d.bodyC.treatment&&(g=1/(d.bodyA.mass+d.bodyB.mass+d.bodyC.mass)),"dynamic"===d.bodyA.treatment&&(e="dynamic"===d.bodyB.treatment&&"dynamic"===d.bodyC.treatment?f*(d.bodyB.mass+d.bodyC.mass)*g:"dynamic"!==d.bodyB.treatment?f*d.bodyC.mass/(d.bodyC.mass+d.bodyA.mass):f*d.bodyB.mass/(d.bodyB.mass+d.bodyA.mass),j.setRotation(e),d.bodyA.state.pos.translateInv(j),d.bodyA.state.pos.rotate(j),d.bodyA.state.pos.translate(j)),"dynamic"===d.bodyC.treatment&&(e="dynamic"===d.bodyA.treatment&&"dynamic"===d.bodyB.treatment?-f*(d.bodyB.mass+d.bodyA.mass)*g:"dynamic"!==d.bodyB.treatment?-f*d.bodyA.mass/(d.bodyC.mass+d.bodyA.mass):-f*d.bodyB.mass/(d.bodyB.mass+d.bodyC.mass),j.setRotation(e),d.bodyC.state.pos.translateInv(j),d.bodyC.state.pos.rotate(j),d.bodyC.state.pos.translate(j)),"dynamic"===d.bodyB.treatment&&(e="dynamic"===d.bodyA.treatment&&"dynamic"===d.bodyC.treatment?f*(d.bodyA.mass+d.bodyC.mass)*g:"dynamic"!==d.bodyA.treatment?f*d.bodyC.mass/(d.bodyC.mass+d.bodyB.mass):f*d.bodyA.mass/(d.bodyA.mass+d.bodyC.mass),j.setRotation(e).setTranslation(d.bodyA.state.pos),d.bodyB.state.pos.translateInv(j),d.bodyB.state.pos.rotate(j),d.bodyB.state.pos.translate(j),j.setTranslation(d.bodyC.state.pos),d.bodyB.state.pos.translateInv(j),d.bodyB.state.pos.rotateInv(j),d.bodyB.state.pos.translate(j)),d.bodyA.sleepCheck(),d.bodyB.sleepCheck(),d.bodyC.sleepCheck());i.done()},resolveDistanceConstraints:function(a){for(var b,d,e,f,g=this._distanceConstraints,h=c.scratchpad(),i=h.vector(),j=0,k=g.length;k>j;++j)b=g[j],i.clone(b.bodyB.state.pos).vsub(b.bodyA.state.pos),d=i.normSq()||1e-4*Math.random(),e=a*b.stiffness*(d-b.targetLengthSq)/d,i.mult(e),f="dynamic"!==b.bodyA.treatment||"dynamic"!==b.bodyB.treatment?1:b.bodyB.mass/(b.bodyA.mass+b.bodyB.mass),"dynamic"===b.bodyA.treatment&&("dynamic"===b.bodyB.treatment&&i.mult(f),b.bodyA.state.pos.vadd(i),"dynamic"===b.bodyB.treatment&&i.mult(1/f)),"dynamic"===b.bodyB.treatment&&("dynamic"===b.bodyA.treatment&&i.mult(1-f),b.bodyB.state.pos.vsub(i)),b.bodyA.sleepCheck(),b.bodyB.sleepCheck();h.done()},shuffleConstraints:function(){this._distanceConstraints=c.util.shuffle(this._distanceConstraints),this._angleConstraints=c.util.shuffle(this._angleConstraints)},resolve:function(){for(var a=this.options.iterations,b=1/a,c=0;a>c;c++)this.resolveDistanceConstraints(b),this.resolveAngleConstraints(b)},getConstraints:function(){return{distanceConstraints:[].concat(this._distanceConstraints),angleConstraints:[].concat(this._angleConstraints)}}}}),c.integrator("improved-euler",function(a){return{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=1-this.options.drag,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"===e.treatment||e.sleep(b)?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(c.old.vel.clone(c.vel),c.old.acc.clone(c.acc),c.vel.vadd(c.acc.mult(b)),d&&c.vel.mult(d),c.acc.zero(),c.old.angular.vel=c.angular.vel,c.angular.vel+=c.angular.acc*b,c.angular.acc=0)},integratePositions:function(a,b){for(var d,e=.5*b*b,f=null,g=c.scratchpad(),h=g.vector(),i=0,j=a.length;j>i;++i)f=a[i],d=f.state,"static"===f.treatment||f.sleep()||(d.old.pos.clone(d.pos),h.clone(d.old.vel),d.pos.vadd(h.mult(b)).vadd(d.old.acc.mult(e)),d.old.acc.zero(),d.old.angular.pos=d.angular.pos,d.angular.pos+=d.old.angular.vel*b+d.old.angular.acc*e,d.old.angular.acc=0);g.done()}}}),c.integrator("velocity-verlet-alt",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=1-this.options.drag,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"!==e.treatment?(e.started()||(c.old.acc.clone(c.acc),c.old.acc.mult(b),c.old.vel.clone(c.vel).vsub(c.old.acc),c.old.acc.mult(1/b)),d&&c.vel.mult(d),c.vel.vadd(c.old.acc.vadd(c.acc).mult(.5*b)),e.started()||(c.old.angular.acc=c.angular.acc,c.old.angular.vel=c.angular.vel-c.old.angular.acc*b),c.angular.vel+=.5*(c.angular.acc+c.old.angular.acc)*b,c.angular.acc=0,e.started(!0)):(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0)},integratePositions:function(a,b){for(var c,d=b*b,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"!==e.treatment&&(c.old.pos.clone(c.pos),c.old.vel.mult(b),c.old.acc.mult(.5*d),c.pos.vadd(c.old.vel).vadd(c.old.acc),c.old.vel.clone(c.vel),c.old.acc.clone(c.acc),c.acc.zero(),c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel*b+.5*c.old.angular.acc*d,c.old.angular.vel=c.angular.vel,c.old.angular.acc=c.angular.acc,c.angular.acc=0)}}}),c.integrator("velocity-verlet",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrate:function(a,b){var c=this._world;return this.integratePositions(a,b),c&&c.emit("integrate:positions",{bodies:a,dt:b}),this.integrateVelocities(a,b),c&&c.emit("integrate:velocities",{bodies:a,dt:b}),this},integrateVelocities:function(a,b){for(var c,d=1-this.options.drag,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"===e.treatment||e.sleep()?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(d&&c.vel.mult(d),c.old.vel.clone(c.vel),c.vel.vadd(c.old.acc.vadd(c.acc).mult(.5*b)),c.old.acc.clone(c.acc),c.acc.zero(),c.old.angular.vel=c.angular.vel,c.old.angular.acc=c.angular.acc,c.angular.vel+=.5*(c.angular.acc+c.old.angular.acc)*b,c.angular.acc=0,e.started(!0))},integratePositions:function(a,b){for(var c,d=b*b,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"===e.treatment||e.sleep(b)||(e.started()||(c.old.acc.clone(c.acc),c.old.acc.mult(b),c.old.vel.clone(c.vel).vsub(c.old.acc),c.old.acc.mult(1/b)),c.old.pos.clone(c.pos),c.old.vel.mult(b),c.old.acc.mult(.5*d),c.pos.vadd(c.old.vel).vadd(c.old.acc),c.old.vel.mult(1/b),c.old.acc.mult(2/d),e.started()||(c.old.angular.acc=c.angular.acc,c.old.angular.vel=c.angular.vel-c.old.angular.acc*b),c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel*b+.5*c.old.angular.acc*d) -}}}),c.renderer("canvas",function(a){if(!b)return{};var d=2*Math.PI,e=function(a,c){var d=b.createElement(a||"div");return c&&(d.innerHTML=c),d},f={white:"#fff",violet:"#542437",blue:"#53777A"},g={metaEl:null,styles:{point:f.blue,circle:{strokeStyle:f.blue,lineWidth:1,fillStyle:f.blue,angleIndicator:f.white},rectangle:{strokeStyle:f.violet,lineWidth:1,fillStyle:f.violet,angleIndicator:f.white},"convex-polygon":{strokeStyle:f.violet,lineWidth:1,fillStyle:f.violet,angleIndicator:f.white}},offset:{x:0,y:0}};return{init:function(d){var f=this;if(a.init.call(this,d),this.options.defaults(g,!0),this.options.onChange(function(){f.options.offset=new c.vector(f.options.offset)}),this.options(d,!0),this.hiddenCanvas=b.createElement("canvas"),this.hiddenCanvas.width=this.hiddenCanvas.height=100,!this.hiddenCanvas.getContext)throw"Canvas not supported";this.hiddenCtx=this.hiddenCanvas.getContext("2d");var h=this.el;if("CANVAS"!==h.nodeName.toUpperCase()&&(h=b.createElement("canvas"),this.el.appendChild(h),"string"==typeof this.options.el&&this.el===b.body&&(h.id=this.options.el),this.el=h),this.container=this.el.parentNode,this.ctx=h.getContext("2d"),this.els={},this.options.meta){var i=this.options.metaEl||e();i.className="pjs-meta",this.els.fps=e("span"),this.els.ipf=e("span"),i.appendChild(e("span","fps: ")),i.appendChild(this.els.fps),i.appendChild(e("br")),i.appendChild(e("span","ipf: ")),i.appendChild(this.els.ipf),h.parentNode.insertBefore(i,h)}this._layers={},this.addLayer("main",this.el),this.options.autoResize?this.resize():this.resize(this.options.width,this.options.height)},layer:function(a){return a in this._layers?this._layers[a]:null},addLayer:function(a,d,e){var f=this,g=[],h=c.util.extend({},this.options.styles),i={id:a,el:d||b.createElement("canvas"),options:c.util.options({width:this.el.width,height:this.el.height,manual:!1,autoResize:!0,follow:null,offset:null,scale:1,zIndex:1})(e)};if(a in this._layers)throw'Layer "'+a+'" already added.';return this.el.parentNode.insertBefore(i.el,this.el),i.el.style.position="absolute",i.el.style.zIndex=i.options.zIndex,i.el.className+=" pjs-layer-"+i.id,i.ctx=i.el.getContext("2d"),i.ctx.scale(1,1),i.el.width=i.options.width,i.el.height=i.options.height,i.bodies=g,i.reset=function(a){return g=a||[],i},i.addToStack=function(a){return c.util.isArray(a)?g.push.apply(g,a):g.push(a),i},i.removeFromStack=function(a){var b,d;if(c.util.isArray(a))for(b=0,d=a.length;d>b;++b)i.removeFromStack(a[b]);else b=c.util.indexOf(g,a),b>-1&&g.splice(b,1);return i},i.render=function(a){var b,d,e,j=c.scratchpad(),k=j.vector().set(0,0),l=i.options.scale,m=g.length,n=f._interpolateTime,o=m||"main"!==i.id?g:f._world._bodies;if(i.options.manual)return j.done(),i;for(i.options.offset&&("center"===i.options.offset?k.add(.5*i.el.width,.5*i.el.height).mult(1/l):k.vadd(i.options.offset).mult(1/l)),i.options.follow&&(k.vsub(i.options.follow.state.pos),k.sub(i.options.follow.state.vel.get(0)*n,i.options.follow.state.vel.get(1)*n)),a!==!1&&i.ctx.clearRect(0,0,i.el.width,i.el.height),1!==l&&(i.ctx.save(),i.ctx.scale(l,l)),e=0,m=o.length;m>e;++e)b=o[e],b.hidden||(d=b.view||(b.view=f.createView(b.geometry,b.styles||h[b.geometry.name])),f.drawBody(b,b.view,i.ctx,k));return 1!==l&&i.ctx.restore(),j.done(),i},this._layers[a]=i,i},removeLayer:function(a){var b=a.id?a.id:a,c=this._layers[b].el;return c!==this.el&&c.parentNode.removeChild(c),delete this._layers[b],this},resize:function(b,c){var d;a.resize.call(this,b,c);for(var e in this._layers)d=this._layers[e],d.options.autoResize&&(d.el.width=this.width,d.el.height=this.height);return this},setStyle:function(a,b){b=b||this.ctx,c.util.isObject(a)?(a.strokeStyle=a.lineWidth?a.strokeStyle:"rgba(0,0,0,0)",c.util.extend(b,a)):(b.fillStyle=b.strokeStyle=a,b.lineWidth=1)},drawCircle:function(a,b,c,e,f){f=f||this.ctx,f.beginPath(),this.setStyle(e,f),f.arc(a,b,c,0,d,!1),f.closePath(),f.stroke(),f.fill()},drawPolygon:function(a,b,c){var d=a[0],e=d.x,f=d.y,g=a.length;c=c||this.ctx,c.beginPath(),this.setStyle(b,c),c.moveTo(e,f);for(var h=1;g>h;++h)d=a[h],e=d.x,f=d.y,c.lineTo(e,f);g>2&&c.closePath(),c.stroke(),c.fill()},drawRect:function(a,b,c,d,e,f){var g=.5*c,h=.5*d;f=f||this.ctx,this.setStyle(e,f),f.beginPath(),f.rect(a-g,b-h,c,d),f.closePath(),f.stroke(),f.fill()},drawLine:function(a,b,c,d){var e=a.x,f=a.y;d=d||this.ctx,d.beginPath(),this.setStyle(c,d),d.moveTo(e,f),e=b.x,f=b.y,d.lineTo(e,f),d.stroke(),d.fill()},draw:function(a,b,c,d){var e=a.name,f=+(d&&d.x),g=+(d&&d.y),h=a.aabb().hw;if(c=c||this.ctx,b=b||this.options.styles[e]||this.options.styles.circle||{},c.save(),c.translate(f,g),"circle"===e)this.drawCircle(0,0,a.radius,b,c);else if("convex-polygon"===e)this.drawPolygon(a.vertices,b,c);else if("rectangle"===e)this.drawRect(0,0,a.width,a.height,b,c);else if("compound"===e)for(var i,j=0,k=a.children.length;k>j;j++)i=a.children[j],c.translate(i.pos.x,i.pos.y),c.rotate(i.angle),this.draw(i.g,b,c),c.rotate(-i.angle),c.translate(-i.pos.x,-i.pos.y);else this.drawCircle(0,0,1,b,c);return"compound"!==e&&b.angleIndicator&&(c.beginPath(),this.setStyle(b.angleIndicator,c),c.moveTo(0,0),c.lineTo(h,0),c.closePath(),c.stroke()),c.restore(),this},createView:function(a,b){var c,d=a.aabb(),e=d.hw+Math.abs(d.x),f=d.hh+Math.abs(d.y),g={x:e+1,y:f+1},h=this.hiddenCtx,i=this.hiddenCanvas;return b=b||this.options.styles[name]||this.options.styles.circle||{},b.src?(c=new Image,c.src=b.src,b.width&&(c.width=b.width),b.height&&(c.height=b.height),c):(g.x+=0|b.lineWidth,g.y+=0|b.lineWidth,i.width=2*e+2+(2*b.lineWidth|0),i.height=2*f+2+(2*b.lineWidth|0),this.draw(a,b,h,g),c=new Image(i.width,i.height),c.src=i.toDataURL("image/png"),c)},drawMeta:function(a){this.els.fps.innerHTML=a.fps.toFixed(2),this.els.ipf.innerHTML=a.ipf},drawBody:function(a,b,c,d){var e,f,g,h=a.state.pos,i=a.offset,j=a.state.vel,k=this._interpolateTime||0;d=d||this.options.offset,c=c||this.ctx,e=h._[0]+d.x+j._[0]*k,f=h._[1]+d.y+j._[1]*k,g=a.state.angular.pos+a.state.angular.vel*k,c.save(),c.translate(e,f),c.rotate(g),c.translate(i._[0],i._[1]),c.drawImage(b,-b.width/2,-b.height/2,b.width,b.height),c.restore()},render:function(a,b){this._world.emit("beforeRender",{renderer:this,meta:b}),this.options.meta&&this.drawMeta(b),this._interpolateTime=b.interpolateTime;for(var c in this._layers)this._layers[c].render();return this}}}),c.renderer("dom",function(a){if(!b)return{};var c={},d=b.createElement("div"),e=function(a){return a.replace(/(?:^|\s)\w/g,function(a){return a.toUpperCase()})},f=function(a){if(c[a])return c[a];for(var b,f=["Webkit","Moz","Ms","O"],g=0,h=f.length;h>g;++g)if(b=f[g]+e(a),b in d.style)return c[a]=b;return b in d.style?c[a]=a:!1},g="pjs-",h="px",i=f("transform"),j=f("borderRadius"),k=function(a,c){var d=b.createElement(a||"div");return c&&(d.innerHTML=c),d};return{init:function(b){a.init.call(this,b);var c=this.el;if(c.style.position="relative",c.style.overflow="hidden",c.style[i]="translateZ(0)",c.style.width=this.options.width+h,c.style.height=this.options.height+h,this.els={},b.meta){var d=k();d.className="pjs-meta",this.els.fps=k("span"),this.els.ipf=k("span"),d.appendChild(k("span","fps: ")),d.appendChild(this.els.fps),d.appendChild(k("br")),d.appendChild(k("span","ipf: ")),d.appendChild(this.els.ipf),c.appendChild(d)}this.options.autoResize?this.resize():this.resize(this.options.width,this.options.height)},resize:function(b,c){a.resize.call(this,b,c),this.el.style.width=this.width+h,this.el.style.height=this.height+h},pointProperties:function(a){a.style.width="2px",a.style.height="2px",a.style.marginLeft="-1px",a.style.marginTop="-1px",a.style[j]="50%"},circleProperties:function(a,b){var c=b.aabb();a.style.width=2*c.hw+h,a.style.height=2*c.hh+h,a.style.marginLeft=-c.hw+h,a.style.marginTop=-c.hh+h,a.style[j]="50%"},rectangleProperties:function(a,b){var c=b.aabb();a.style.width=2*c.hw+h,a.style.height=2*c.hh+h,a.style.marginLeft=-c.hw+h,a.style.marginTop=-c.hh+h},createView:function(a){var b,c=k(),d=a.name+"Properties";if(c.className=g+a.name,c.style.position="absolute",c.style.top="0px",c.style.left="0px","compound"===a.name)for(var e,f=0,h=a.children.length;h>f;f++)e=a.children[f],b=k(),b.className=g+a.name+" "+g+"child",b.style.position="absolute",b.style.top="0px",b.style.left="0px",this[e.g.name+"Properties"]&&this[e.g.name+"Properties"](b,e.g),b.style[i]="translate("+e.pos._[0]+"px,"+e.pos._[1]+"px) rotate("+e.angle+"rad)",c.appendChild(b);else this[d]&&this[d](c,a);return this.el.appendChild(c),c},connect:function(a){a.on("add:body",this.attach,this),a.on("remove:body",this.detach,this)},disconnect:function(a){a.off("add:body",this.attach,this),a.off("remove:body",this.detach,this)},detach:function(a){var b=a.nodeType&&a||a.body&&a.body.view,c=b&&b.parentNode;return b&&c&&c.removeChild(b),this},attach:function(a){var b=a.nodeType&&a||a.body&&a.body.view;return b&&this.el.appendChild(b),this},drawMeta:function(a){this.els.fps.innerHTML=a.fps.toFixed(2),this.els.ipf.innerHTML=a.ipf},drawBody:function(a,b){var c,d,e,f=a.state.pos,g=a.state.vel,h=a.offset,j=this._interpolateTime;c=f._[0]+g._[0]*j,d=f._[1]+g._[1]*j,e=a.state.angular.pos+a.state.angular.vel*j,b.style[i]="translate("+c+"px,"+d+"px) rotate("+e+"rad) translate("+h._[0]+"px,"+h._[1]+"px)"}}}),c.renderer("pixi",function(d){if(!b)return{};var e=(2*Math.PI,{white:"0xFFFFFF",violet:"0x542437",blue:"0x53777A"}),f={font:"18px monospace",fill:"black",align:"left"},g={metaEl:null,offset:{x:0,y:0},styles:{color:!1,point:e.blue,circle:{strokeStyle:e.blue,lineWidth:1,fillStyle:e.blue,angleIndicator:e.white,fillAlpha:1,alpha:1},rectangle:{strokeStyle:e.violet,lineWidth:1,fillStyle:e.violet,angleIndicator:e.white,fillAlpha:1,alpha:1},"convex-polygon":{strokeStyle:e.violet,lineWidth:1,fillStyle:e.violet,angleIndicator:e.white,fillAlpha:1,alpha:1}}};return{init:function(e){var f,h,i=this;if("undefined"==typeof PIXI)throw"PIXI not present - cannot continue";d.init.call(this,e),this.options.defaults(g,!0),this.options.onChange(function(){i.options.offset=new c.vector(i.options.offset)}),this.options(e,!0),h=!this.options.styles.color||"transparent"===this.options.styles.color,this.stage=new PIXI.Stage(this.options.styles.color),this.meta={},f=this.el&&"CANVAS"===this.el.nodeName?f:null,this.renderer=new PIXI.autoDetectRenderer(this.options.width,this.options.height,{view:f,transparent:h,resolution:a.devicePixelRatio||1}),f||(this.el=this.el||b.body,this.el.appendChild(this.renderer.view)),this.options.autoResize?this.resize():this.resize(this.options.width,this.options.height)},resize:function(a,b){d.resize.call(this,a,b),this.renderer.resize(this.width,this.height)},connect:function(a){a.on("add:body",this.attach,this),a.on("remove:body",this.detach,this)},disconnect:function(a){a.off("add:body",this.attach,this),a.off("remove:body",this.detach,this)},detach:function(a){var b=a instanceof PIXI.Graphics&&a||a.body&&a.body.view;return b&&this.stage.removeChild(b),this},attach:function(a){var b=a instanceof PIXI.Graphics&&a||a.body&&a.body.view;return b&&this.stage.addChild(b),this},loadSpriteSheets:function(a,b){if(!c.util.isArray(a))throw"Spritesheets must be defined in arrays";var d=this,e=new PIXI.AssetLoader(a);return e.load(),e.on("onComplete",function(){d.assetsLoaded=!0,b()}),d},drawBody:function(a,b){var c,d,e,f=a.state.pos,g=a.state.vel,h=a.offset,i=this._interpolateTime||0;c=f._[0]+g._[0]*i,d=f._[1]+g._[1]*i,e=a.state.angular.pos+a.state.angular.vel*i,b.position.set(c,d),b.pivot.set(-h._[0],-h._[1]),b.rotation=e},render:function(a,b){d.render.call(this,a,b),this.renderer.render(this.stage)},setStyles:function(a,b){return c.util.isObject(b)?(b.fillStyle&&"transparent"!==b.fillStyle?(a.beginFill(b.fillStyle),a.fillAlpha=b.fillAlpha||1):(a.beginFill(),a.fillAlpha=0),a.lineStyle(b.lineWidth||0,b.strokeStyle),a.alpha=b.alpha||1):(b&&"transparent"!==b?a.beginFill(b):(a.beginFill(),a.fillAlpha=0),a.lineStyle(0)),a},createCircle:function(a,b,c,d){var e=new PIXI.Graphics;return this.setStyles(e,d),e.drawCircle(a,b,c),e.endFill(),e},createRect:function(a,b,c,d,e){var f=new PIXI.Graphics;return this.setStyles(f,e),f.drawRect(a,b,c,d),f.endFill(),f},createPolygon:function(a,b){var c=a[0],d=c.x,e=c.y,f=a.length,g={x:d,y:e},h=new PIXI.Graphics;this.setStyles(h,b),h.moveTo(d,e);for(var i=1;f>i;++i)c=a[i],d=c.x,e=c.y,h.lineTo(d,e);return f>2&&h.lineTo(g.x,g.y),h.endFill(),h},createLine:function(a,b,c){var d=a.x,e=a.y,f=new PIXI.Graphics;return this.setStyles(f,c),f.moveTo(d,e),d=b.x,e=b.y,f.lineTo(d,e),f.endFill(),f},createView:function(a,b,c){var d=null,e=a.aabb(),f=e.hw+Math.abs(e.x),g=(e.hh+Math.abs(e.y),a.name);if(c=c||this.stage,b=b||this.options.styles[g]||this.options.styles.circle||{},b.src)return d=PIXI.Sprite.fromImage(b.src),d.anchor.set(.5,.5),b.anchor&&(d.anchor.x=b.anchor.x,d.anchor.y=b.anchor.y),b.width&&(d.width=b.width),b.height&&(d.height=b.height),c.addChild(d),d;if("circle"===g)d=this.createCircle(0,0,a.radius,b);else if("convex-polygon"===g)d=this.createPolygon(a.vertices,b);else if("rectangle"===g)d=this.createRect(-a.width/2,-a.height/2,a.width,a.height,b);else if("compound"===g){d=new PIXI.Graphics;for(var h,i,j=0,k=a.children.length;k>j;j++)h=a.children[j],i=this.createView(h.g,b,d),i.position.set(h.pos.x,h.pos.y),i.rotation=h.angle}else d=this.createCircle(0,0,1,b);return"compound"!==g&&b.angleIndicator&&"transparent"!==b.angleIndicator&&(d.lineStyle(b.lineWidth,b.angleIndicator),d.moveTo(0,0),d.lineTo(f,0),d.cacheAsBitmap=!0),c.addChild(d),d},drawMeta:function(a){this.meta.loaded?(this.meta.fps.setText("FPS: "+a.fps.toFixed(2)),this.meta.ipf.setText("IPF: "+a.ipf)):(this.meta.fps=new PIXI.Text("FPS: "+a.fps.toFixed(2),f),this.meta.fps.position.x=15,this.meta.fps.position.y=5,this.meta.ipf=new PIXI.Text("IPF: "+a.ipf,f),this.meta.ipf.position.x=15,this.meta.ipf.position.y=30,this.stage.addChild(this.meta.fps),this.stage.addChild(this.meta.ipf),this.meta.loaded=!0)},createDisplay:function(a,b){var c=null,d=null;switch(a){case"sprite":return d=PIXI.Texture.fromImage(b.texture),c=new PIXI.Sprite(d),b.anchor&&(c.anchor.x=b.anchor.x,c.anchor.y=b.anchor.y),b.container?b.container.addChild(c):this.stage.addChild(c),c;case"movieclip":if(!this.assetsLoaded)throw"No assets have been loaded. Use loadSpritesheet() first";var e=[],f=0;for(f;fa.x-a.hw&&b.xa.y-a.hh&&b.y=d&&f>=e||f>=c&&e>=f?(c=a.y-a.hh,d=b.y-b.hh,e=a.y+a.hh,f=b.y+b.hh,e>=d&&f>=e||f>=c&&e>=f):!1}}(),function(){var a=1e-4,b=100,d=function(a,b,c){var d=b.normSq()-b.dot(a),e=b.dot(a)-a.normSq();return 0>d?c.clone(b).negate():e>0?c.clone(a).negate():(c.clone(b).vsub(a),c.perp(a.cross(c)>0))},e=function(a){var b,d,e=a.length,f=a[e-2],g=a[e-3],h=c.scratchpad(),i=h.vector().clone(f.pt),j=h.vector().clone(g.pt).vsub(i);return j.equals(c.vector.zero)?h.done({a:f.a,b:f.b}):(b=-j.dot(i)/j.normSq(),d=1-b,h.done(0>=d?{a:g.a,b:g.b}:0>=b?{a:f.a,b:f.b}:{a:i.clone(f.a).mult(d).vadd(j.clone(g.a).mult(b)).values(),b:i.clone(f.b).mult(d).vadd(j.clone(g.b).mult(b)).values()}))},f=function(f,g,h,i){var j,k,l,m,n=!1,o=!1,p=!1,q=[],r=1,s=c.scratchpad(),t=s.vector().clone(g||c.vector.axis[0]),u=s.vector(),v=s.vector(),w=s.vector(),x=s.vector(),y=0;for(m=f(t),r=q.push(m),u.clone(m.pt),t.negate();++y;){if(u.swap(v),m=f(t),r=q.push(m),u.clone(m.pt),i&&i(q),u.equals(c.vector.zero)){n=!0;break}if(!o&&u.dot(t)<=0){if(h)break;o=!0}if(2===r)t=d(u,v,t);else if(o){if(t.normalize(),m=v.dot(t),Math.abs(m-u.dot(t))0,l^u.cross(j)>0)q.shift(),j.perp(!l),t.swap(j);else{if(!(l^k.cross(u)>0)){n=!0;break}q.splice(1,1),k.perp(l),t.swap(j)}if(y>b)return s.done(),{simplex:q,iterations:y,distance:0,maxIterationsReached:!0}}return s.done(),m={overlap:n,simplex:q,iterations:y},p!==!1&&(m.distance=p,m.closest=e(q)),m};c.gjk=f}(),function(){c.statistics={pushRunningAvg:function(a,b,c,d){var e=a-c;return c+=e/b,d+=e*(a-c),[c,d]},pushRunningVectorAvg:function(a,b,c,d){var e=1/b,f=a.get(0)-c.get(0),g=a.get(1)-c.get(1);c.add(f*e,g*e),d&&(f*=a.get(0)-c.get(0),g*=a.get(1)-c.get(1),d.add(f,g))}}}(),function(){var a=function b(a,d,e){return this instanceof b?(this.v=new c.vector,this.o=new c.vector,a instanceof b?void this.clone(a):(a&&this.setTranslation(a),void this.setRotation(d||0,e))):new b(a,d)};a.prototype.setTranslation=function(a){return this.v.clone(a),this},a.prototype.setRotation=function(a,b){return this.cosA=Math.cos(a),this.sinA=Math.sin(a),b?this.o.clone(b):this.o.zero(),this},a.prototype.clone=function(b){return b?(this.setTranslation(b.v),this.cosA=b.cosA,this.sinA=b.sinA,this.o.clone(b.o),this):new a(this)},c.transform=a}(),function(a){var b=Math.sqrt,d=Math.min,e=Math.max,f=(Math.acos,Math.atan2),g=2*Math.PI,h=!!a.Float64Array,i=function j(a,b){return this instanceof j?(this._=h?new Float64Array(5):[],void(a&&(void 0!==a.x||a._&&a._.length)?this.clone(a):(this.recalc=!0,this.set(a,b)))):new j(a,b)};Object.defineProperties(i.prototype,{x:{get:function(){return+this._[0]},set:function(a){a=+a||0,this.recalc=a===this._[0],this._[0]=a}},y:{get:function(){return+this._[1]},set:function(a){a=+a||0,this.recalc=a===this._[1],this._[1]=a}}}),i.prototype.set=function(a,b){return this.recalc=!0,this._[0]=+a||0,this._[1]=+b||0,this},i.prototype.get=function(a){return this._[a]},i.prototype.vadd=function(a){return this.recalc=!0,this._[0]+=a._[0],this._[1]+=a._[1],this},i.prototype.vsub=function(a){return this.recalc=!0,this._[0]-=a._[0],this._[1]-=a._[1],this},i.prototype.add=function(a,b){return this.recalc=!0,this._[0]+=+a||0,this._[1]+=+b||0,this},i.prototype.sub=function(a,b){return this.recalc=!0,this._[0]-=a,this._[1]-=void 0===b?0:b,this},i.prototype.mult=function(a){return this.recalc||(this._[4]*=a*a,this._[3]*=a),this._[0]*=a,this._[1]*=a,this},i.prototype.dot=function(a){return this._[0]*a._[0]+this._[1]*a._[1]},i.prototype.cross=function(a){return-this._[0]*a._[1]+this._[1]*a._[0]},i.prototype.proj=function(a){return this.dot(a)/a.norm()},i.prototype.vproj=function(a){var b=this.dot(a)/a.normSq();return this.clone(a).mult(b)},i.prototype.angle=function(a){var b;if(this.equals(i.zero))return a?a.angle():0/0;for(b=a&&!a.equals(i.zero)?f(this._[1]*a._[0]-this._[0]*a._[1],this._[0]*a._[0]+this._[1]*a._[1]):f(this._[1],this._[0]);b>Math.PI;)b-=g;for(;b<-Math.PI;)b+=g;return b},i.prototype.angle2=function(a,b){for(var c=a._[0]-this._[0],d=a._[1]-this._[1],e=b._[0]-this._[0],h=b._[1]-this._[1],i=f(d*e-c*h,c*e+d*h);i>Math.PI;)i-=g;for(;i<-Math.PI;)i+=g;return i},i.prototype.norm=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[3]},i.prototype.normSq=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[4]},i.prototype.dist=function(a){var c,d;return b((c=a._[0]-this._[0])*c+(d=a._[1]-this._[1])*d)},i.prototype.distSq=function(a){var b,c;return(b=a._[0]-this._[0])*b+(c=a._[1]-this._[1])*c},i.prototype.perp=function(a){var b=this._[0];return a?(this._[0]=this._[1],this._[1]=-b):(this._[0]=-this._[1],this._[1]=b),this},i.prototype.normalize=function(){var a=this.norm();return 0===a?this:(a=1/a,this._[0]*=a,this._[1]*=a,this._[3]=1,this._[4]=1,this)},i.prototype.transform=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d,this._[1]-=e,this.set(this._[0]*c-this._[1]*b+d+a.v._[0],this._[0]*b+this._[1]*c+e+a.v._[1])},i.prototype.transformInv=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d+a.v._[0],this._[1]-=e+a.v._[1],this.set(this._[0]*c+this._[1]*b+d,-this._[0]*b+this._[1]*c+e)},i.prototype.rotate=function(a,b){var c,d,e=0,f=0;return"number"==typeof a?(c=Math.sin(a),d=Math.cos(a),b&&(e=b.x,f=b.y)):(c=a.sinA,d=a.cosA,e=a.o._[0],f=a.o._[1]),this._[0]-=e,this._[1]-=f,this.set(this._[0]*d-this._[1]*c+e,this._[0]*c+this._[1]*d+f)},i.prototype.rotateInv=function(a){return this.set((this._[0]-a.o._[0])*a.cosA+(this._[1]-a.o._[1])*a.sinA+a.o._[0],-(this._[0]-a.o._[0])*a.sinA+(this._[1]-a.o._[1])*a.cosA+a.o._[1])},i.prototype.translate=function(a){return this.vadd(a.v)},i.prototype.translateInv=function(a){return this.vsub(a.v)},i.prototype.clone=function(a){return a?a._?(this.recalc=a.recalc,a.recalc||(this._[3]=a._[3],this._[4]=a._[4]),this._[0]=a._[0],this._[1]=a._[1],this):this.set(a.x,a.y):new i(this)},i.prototype.swap=function(a){var b=this._;return this._=a._,a._=b,b=this.recalc,this.recalc=a.recalc,a.recalc=b,this},i.prototype.values=function(){return{x:this._[0],y:this._[1]}},i.prototype.zero=function(){return this._[3]=0,this._[4]=0,this._[0]=0,this._[1]=0,this},i.prototype.negate=function(a){return void 0!==a?(this._[a]=-this._[a],this):(this._[0]=-this._[0],this._[1]=-this._[1],this)},i.prototype.clamp=function(a,b){return this._[0]=d(e(this._[0],a.x),b.x),this._[1]=d(e(this._[1],a.y),b.y),this.recalc=!0,this},i.prototype.toString=function(){return"("+this._[0]+", "+this._[1]+")"},i.prototype.equals=function(a){return this._[0]===a._[0]&&this._[1]===a._[1]&&this._[2]===a._[2]},i.axis=[new i(1,0),new i(0,1)],i.zero=new i(0,0),c.vector=i}(this),function(a){var b=a.Physics;c.noConflict=function(){return a.Physics===c&&(a.Physics=b),c}}(this);var d=c.util.decorator=function(a,b){var d={},e={},f=function(a,b){var d,e;for(e in b)d=Object.getOwnPropertyDescriptor(b,e),d.get||d.set?Object.defineProperty(a,e,d):c.util.isFunction(d.value)&&(a[e]=d.value);return a},g=Object.getPrototypeOf;"function"!=typeof g&&(g="object"==typeof"test".__proto__?function(a){return a.__proto__}:function(a){return a.constructor.prototype});var h=Object.create;"function"!=typeof h&&(h=function(a){function b(){}return b.prototype=a,new b});var i=function(b,d){return"object"==typeof b?(e=f(e,b),void(e.type=a)):void("type"!==b&&c.util.isFunction(d)&&(e[b]=d))};i(b);var j=function(b,c,i,j){var k,l=e;if("string"!=typeof c)j=i,i=c;else{if(l=d[c],!l)throw'Error: "'+c+'" '+a+" not defined";l=l.prototype}if("function"==typeof i)k=d[b],k?k.prototype=f(k.prototype,i(g(k.prototype))):(k=d[b]=function(a){this.init&&this.init(a)},k.prototype=h(l),k.prototype=f(k.prototype,i(l,k.prototype))),k.prototype.type=a,k.prototype.name=b;else if(j=i||{},k=d[b],!k)throw'Error: "'+b+'" '+a+" not defined";return j?new k(j):void 0};return j.mixin=i,j};c.util.indexOf=function(a,b){for(var c=0,d=a.length;d>c;){if(d--,a[c]===b)return c;if(a[d]===b)return d;c++}return-1},c.util.clearArray=function(a){for(var b=a.length;b--;)a.pop();return a},c.util.throttle=function(a,b,c){var d,e,f=!1,g=function(){clearTimeout(d),f?(f=!1,d=setTimeout(g,b),a.apply(c,e)):d=!1};return c=c||null,function(){f=!0,e=arguments,d||g()}};var e=function(a,b){return c.util.isPlainObject(b)?c.util.extend({},a,b,e):void 0!==b?b:a};return c.util.options=function(a,b){var d,f={},g=[];return d=function(a,d){c.util.extend(b,a,d?e:null);for(var f=0,h=g.length;h>f;++f)g[f](b);return b},d.defaults=function(a,d){return c.util.extend(f,a,d?e:null),c.util.defaults(b,f,d?e:null),f},d.onChange=function(a){g.push(a)},b=b||d,d.defaults(a),d},c.util.pairHash=function(a,b){return a=0|a,b=0|b,(0|a)===(0|b)?-1:0|((0|a)>(0|b)?a<<16|65535&b:b<<16|65535&a)},c.util.bind=Function.prototype.bind?function(a,b,c){return c=Array.prototype.slice.call(arguments,1),Function.prototype.bind.apply(a,c)}:function(a,b,c){return c=Array.prototype.slice.call(arguments,2),function(){return a.apply(b,c.concat(Array.prototype.slice.call(arguments)))}},c.util.find=function(a,b){var c,d,e=a.length;for(c=0;e>c;c++)if(d=a[c],b(d,c,a))return d},c.util.filter=function(a,b){var c,d,e=a.length,f=[];for(c=0;e>c;c++)d=a[c],b(d,c,a)&&f.push(d);return f},function(){function a(a){c.util.clearArray(a),v.length-1?0:-1:a?0:-1}function g(a){var b=this.cache,c=typeof a;if("boolean"===c||null==a)b[a]=!0;else{"number"!==c&&"string"!==c&&(c="object");var d="number"===c?a:y+a,e=b[c]||(b[c]={});"object"===c?(e[d]||(e[d]=[])).push(a):e[d]=!0}}function h(a){var b=-1,c=a.length,e=a[0],f=a[c/2|0],h=a[c-1];if(e&&"object"==typeof e&&f&&"object"==typeof f&&h&&"object"==typeof h)return!1;var i=d();i["false"]=i["null"]=i["true"]=i.undefined=!1;var j=d();for(j.array=a,j.cache=i,j.push=g;++b=u&&k===c.util.indexOf,o=i||n?e():m;if(n){var p=h(o);k=f,o=p}for(;++jb;b++)d=a[b],e=i(0,++f),h[f]=h[e],h[e]=d;return h},c.util.isObject=function(a){return!(!a||!n[typeof a])},c.util.isFunction=j,c.util.isArray=Array.isArray||function(a){return a&&"object"==typeof a&&"number"==typeof a.length&&s.call(a)===p||!1};var C=RegExp("^"+String(s).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$");c.util.isPlainObject=Object.getPrototypeOf?function(a){if(!a||s.call(a)!==q)return!1;var b=a.valueOf,c=k(b)&&(c=Object.getPrototypeOf(b))&&Object.getPrototypeOf(c);return c?a===c||Object.getPrototypeOf(a)===c:l(a)}:l,c.util.uniq=function(a,b,c){return"boolean"!=typeof b&&null!=b&&(c=b,b=!1),m(a,b,c)};var D=function(a,b,c){var d,e=a,f=e;if(!e)return f;var g,h=arguments,i=0,j="number"==typeof c?2:h.length;for(j>2&&"function"==typeof h[j-1]&&(g=h[--j]);++id;){var f=d+e>>>1;c(a[f])=b.maxScratches)throw f},a.prototype={done:function(a){this._active=!1;for(var b=0;j>b;++b)this[b]=0;return h.push(this),a}},b=function k(b){if(b)return k.fn(b);var c=h.pop()||new a;return c._active=!0,c},b.maxScratches=100,b.maxIndex=20,b.fn=function(b){for(var c=[],d=0,e=b.length;e>d;d++)c.push(d);c="a"+c.join(",a");var f=new Function("fn, scratches, Scratch","return function("+c+"){ var scratch = scratches.pop() || new Scratch( scratches );scratch._active = true;return scratch.done( fn(scratch, "+c+") );};");return f(b,h,a)},b.register=function(c,f,h){var i=a.prototype,k=j++,l="_"+c+"Stack",m=h&&h.useFactory;if(c in i)throw g;a.prototype[c]=function(){var a=this[l]||(this[l]=[]),c=0|this[k];if(this[k]=c+1,!this._active)throw d;if(c>=b.maxIndex)throw e;return a[c]||(a[c]=m?f():new f)}},b.register("vector",c.vector),b.register("transform",c.transform),b}(),function(){function a(a){return a._priority_}var b=1;c.scratchpad.register("event",function(){return{}},{useFactory:!0});var d=function e(){return this instanceof e?void 0:new e};d.prototype={on:function(d,e,f,g){var h,i,j;if(this._topics=this._topics||(this._topics={}),c.util.isObject(d)){for(var k in d)this.on(k,d[k],e,f);return this}return h=this._topics[d]||(this._topics[d]=[]),i=e,c.util.isObject(f)?(e=c.util.bind(e,f),e._bindfn_=i,e._one_=i._one_,e._scope_=f):void 0===g&&(g=f),e._priority_=void 0===g?b:g,j=c.util.sortedIndex(h,e,a),h.splice(j,0,e),this},off:function(a,b,d){var e,f;if(!this._topics)return this;if(a===!0)return this._topics={},this;if(c.util.isObject(a)){for(var g in a)this.off(g,a[g]);return this}if(e=this._topics[a],!e)return this;if(b===!0)return this._topics[a]=[],this;for(var h=0,i=e.length;i>h;h++)if(f=e[h],!(f._bindfn_!==b&&f!==b||d&&f._scope_!==d)){e.splice(h,1);break}return this},emit:function(a,b){if(!this._topics)return this;var d,e,f=this._topics[a],g=f&&f.length,h=c.scratchpad();if(!g)return h.done(this);for(e=h.event(),e.topic=a,e.handler=d;g--;)d=f[g],d(b,e),d._one_&&f.splice(g,1);return h.done(this)},one:function(a,b,d){if(c.util.isObject(a)){for(var e in a)this.one(e,a[e],b,d);return this}return b._one_=!0,this.on(a,b,d),this}},c.util.pubsub=d}(),function(a){function b(){return l&&l.now?l.now()+l.timing.navigationStart:Date.now()}function d(){var c;a.requestAnimationFrame(d),j&&(c=b(),c&&k.emit("tick",c))}function e(){return j=!0,this}function f(){return j=!1,this}function g(a){return k.on("tick",a),this}function h(a){return k.off("tick",a),this}function i(){return!!j}var j=!0,k=c.util.pubsub(),l=a.performance;a.requestAnimationFrame?d():j=!1,c.util.ticker={now:b,start:e,stop:f,on:g,off:h,isActive:i}}(this),function(){var a=function(){return!0},b=c.util.indexOf,d=function(a,b){return function(c){return a(c[b])}},e=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){if(c.util.isArray(a)){if(f=e.length,f!==a.length)return!1;for(;f>g;){if(f--,-1===b(a,e[g])||-1===b(a,e[f]))return!1;g++}return!0}return b(e,a)>-1}return e===a}},f=function(a,b){var c=e(a,b);return function(a){return!c(a)}},g=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){for(f=e.length;f>g;){if(f--,b(a,e[g])>-1||b(a,e[f])>-1)return!0;g++}return!1}return b(a,e)>-1}},h=function(a,b){var c=g(a,b);return function(a){return!c(a)}},i=function(a){return a=new c.vector(a),function(b){var d=b.aabb();return c.aabb.contains(d,a)}},j=function(a){return a.next?function(b){for(var c=a;c;){if(!c(b))return!1;c=c.next}return!0}:a},k=function(a){return a.next?function(b){for(var c=a;c;){if(c(b))return!0;c=c.next}return!1}:a},l={$eq:e,$ne:f,$in:g,$nin:h,$at:i},m=function n(b,f){var g,h,i,m,o,p;if(f){if("$or"===f||"$and"===f){for(g=0,h=b.length;h>g;++g)p=n(b[g]),o=o?o.next=p:m=p;return"$or"===f?k(m):j(m)}if(g=l[f])return g(b);throw"Unknown query operation: "+f}for(g in b)i=b[g],p="$"===g[0]?n(i,g):c.util.isPlainObject(i)?d(n(i),g):e(i,g),o=o?o.next=p:m=p;return j(m||a)};c.query=m}(this),function(){var a={priority:0};c.behavior=d("behavior",{init:function(b){this.options=c.util.options(a),this.options(b)},applyTo:function(a){return this._targets=a===!0?null:c.util.uniq(a),this},getTargets:function(){return this._targets||(this._world?this._world._bodies:[])},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},connect:function(a){this.behave&&a.on("integrate:positions",this.behave,this,this.options.priority)},disconnect:function(a){this.behave&&a.off("integrate:positions",this.behave,this)},behave:null})}(),function(){{var a={hidden:!1,treatment:"dynamic",mass:1,restitution:1,cof:.8,view:null},b=1;2*Math.PI}c.body=d("body",{init:function(d){var e=this,f=c.vector;if(this.options=c.util.options(a,this),this.options.onChange(function(a){e.offset=new f(a.offset)}),this.options(d),this.state={pos:new f(this.x,this.y),vel:new f(this.vx,this.vy),acc:new f,angular:{pos:this.angle||0,vel:this.angularVelocity||0,acc:0},old:{pos:new f,vel:new f,acc:new f,angular:{pos:0,vel:0,acc:0}}},this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean=new f,this._sleepPosVariance=new f,this._sleepMeanK=0,delete this.x,delete this.y,delete this.vx,delete this.vy,delete this.angle,delete this.angularVelocity,0===this.mass)throw"Error: Bodies must have non-zero mass";this.uid=b++,this.geometry=c.geometry("point")},sleep:function(a){return a===!0?this.asleep=!0:a===!1?(this.asleep=!1,this._sleepMeanK=0,this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean.zero(),this._sleepPosVariance.zero(),this.sleepIdleTime=0):a&&!this.asleep&&this.sleepCheck(a),this.asleep},sleepCheck:function(a){var b=this._world&&this._world.options;if(!(this.sleepDisabled||b&&b.sleepDisabled)){{var d,e,f,g,h,i,j=c.scratchpad();j.vector(),j.vector()}if(a=a||0,g=this.geometry.aabb(),f=Math.max(g.hw,g.hh),this.asleep&&(e=this.state.vel.norm()+Math.abs(f*this.state.angular.vel),d=this.sleepSpeedLimit||b&&b.sleepSpeedLimit||0,e>=d))return this.sleep(!1),j.done();this._sleepMeanK++,h=this._sleepMeanK>1?1/(this._sleepMeanK-1):0,c.statistics.pushRunningVectorAvg(this.state.pos,this._sleepMeanK,this._sleepPosMean,this._sleepPosVariance),i=c.statistics.pushRunningAvg(Math.sin(this.state.angular.pos),this._sleepMeanK,this._sleepAngPosMean,this._sleepAngPosVariance),this._sleepAngPosMean=i[0],this._sleepAngPosVariance=i[1],e=this._sleepPosVariance.norm()+Math.abs(f*Math.asin(i[1])),e*=h,d=this.sleepVarianceLimit||b&&b.sleepVarianceLimit||0,d>=e?(d=this.sleepTimeLimit||b&&b.sleepTimeLimit||0,this.sleepIdleTime=(this.sleepIdleTime||0)+a,this.sleepIdleTime>d&&(this.asleep=!0)):this.sleep(!1),j.done()}},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},accelerate:function(a){return"dynamic"===this.treatment&&this.state.acc.vadd(a),this},applyForce:function(a,b){if("dynamic"!==this.treatment)return this;var d,e=c.scratchpad(),f=e.vector();return b&&this.moi&&(d=this.state,f.clone(b),this.state.angular.acc-=f.cross(a)/this.moi),this.accelerate(f.clone(a).mult(1/this.mass)),e.done(),this},getGlobalOffset:function(a){return a=a||new c.vector,a.clone(this.offset).rotate(this.state.angular.pos),a},aabb:function(){var a=this.state.angular.pos,b=c.scratchpad(),d=b.vector(),e=this.geometry.aabb(a);return this.getGlobalOffset(d),e.x+=this.state.pos._[0]+d._[0],e.y+=this.state.pos._[1]+d._[1],b.done(e)},toBodyCoords:function(a){return a.vsub(this.state.pos).rotate(-this.state.angular.pos)},toWorldCoords:function(a){return a.rotate(this.state.angular.pos).vadd(this.state.pos)},recalc:function(){return this}}),c.body.getCOM=function(a,b){var d,e,f,g=a&&a.length,h=0;if(b=b||new c.vector,!g)return b.zero();if(1===g)return b.clone(a[0].state.pos);for(b.zero(),f=0;g>f;f++)d=a[f],e=d.state.pos,b.add(e._[0]*d.mass,e._[1]*d.mass),h+=d.mass;return b.mult(1/h),b}}(),function(){c.geometry=d("geometry",{init:function(a){this.options=c.util.options(),this.options(a),this._aabb=new c.aabb},aabb:function(){return c.aabb.clone(this._aabb)},getFarthestHullPoint:function(a,b){return b=b||new c.vector,b.set(0,0)},getFarthestCorePoint:function(a,b){return b=b||new c.vector,b.set(0,0)}})}(),c.geometry.regularPolygonVertices=function(a,b){var c,d=[],e=2*Math.PI/a,f=0;for(c=0;a>c;c++)d.push({x:b*Math.cos(f),y:b*Math.sin(f)}),f+=e;return d},c.geometry.isPolygonConvex=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=b.vector(),g=!0,h=!1,i=a.length;if(!a||!i)return!1;if(3>i)return b.done(),g;d.clone(a[0]).vsub(f.clone(a[i-1]));for(var j=1;i>=j;++j){if(e.clone(a[j%i]).vsub(f.clone(a[(j-1)%i])),h===!1)h=d.cross(e);else if(h>0^d.cross(e)>0){g=!1;break}e.swap(d)}return b.done(),g},c.geometry.getPolygonMOI=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=0,h=0,i=a.length;if(2>i)return d.done(),0;if(2===i)return b=f.clone(a[1]).distSq(e.clone(a[0])),d.done(),b/12;e.clone(a[0]);for(var j=1;i>j;++j)f.clone(a[j]),b=Math.abs(f.cross(e)),g+=b*(f.normSq()+f.dot(e)+e.normSq()),h+=b,e.swap(f);return d.done(),g/(6*h)},c.geometry.isPointInPolygon=function(a,b){var d=c.scratchpad(),e=d.vector().clone(a),f=d.vector(),g=d.vector(),h=0,i=b.length;if(2>i)return h=e.equals(f.clone(b[0])),d.done(),h;if(2===i)return h=e.angle(f.clone(b[0])),h+=e.angle(f.clone(b[1])),d.done(),Math.abs(h)===Math.PI;f.clone(b[0]).vsub(e);for(var j=1;i>=j;++j)g.clone(b[j%i]).vsub(e),h+=g.angle(f),f.swap(g);return d.done(),Math.abs(h)>1e-6},c.geometry.getPolygonArea=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=0,g=a.length;if(3>g)return b.done(),0;d.clone(a[g-1]);for(var h=0;g>h;++h)e.clone(a[h]),f+=d.cross(e),d.swap(e);return b.done(),f/2},c.geometry.getPolygonCentroid=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=new c.vector,h=a.length;if(2>h)return d.done(),new c.vector(a[0]);if(2===h)return d.done(),new c.vector((a[1].x+a[0].x)/2,(a[1].y+a[0].y)/2);e.clone(a[h-1]);for(var i=0;h>i;++i)f.clone(a[i]),b=e.cross(f),e.vadd(f).mult(b),g.vadd(e),e.swap(f);return b=1/(6*c.geometry.getPolygonArea(a)),d.done(),g.mult(b)},c.geometry.nearestPointOnLine=function(a,b,d){var e,f,g=c.scratchpad(),h=g.vector().clone(a),i=g.vector().clone(b).vsub(h),j=g.vector().clone(d).vsub(h).vsub(i);return j.equals(c.vector.zero)?(g.done(),new c.vector(b)):(e=-j.dot(i)/j.normSq(),f=1-e,0>=f?(g.done(),new c.vector(d)):0>=e?(g.done(),new c.vector(b)):(h=new c.vector(d).mult(e).vadd(i.clone(b).mult(f)),g.done(),h))},function(){var a={drag:0};c.integrator=d("integrator",{init:function(b){this.options=c.util.options(a),this.options(b)},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},integrate:function(a,b){var c=this._world;return this.integrateVelocities(a,b),c&&c.emit("integrate:velocities",{bodies:a,dt:b}),this.integratePositions(a,b),c&&c.emit("integrate:positions",{bodies:a,dt:b}),this},connect:null,disconnect:null,integrateVelocities:function(){throw"The integrator.integrateVelocities() method must be overriden"},integratePositions:function(){throw"The integrator.integratePositions() method must be overriden"}})}(),function(){var e={meta:!1,metaRefresh:200,width:600,height:600,autoResize:!0};c.renderer=d("renderer",{init:function(d){var f=this,g="string"==typeof d.el?b.getElementById(d.el):d.el;this.options=c.util.options(e),this.options(d),this.el=g?g:b.body,this.container=g&&g.parentNode?g.parentNode:b.body,this.drawMeta=c.util.throttle(c.util.bind(this.drawMeta,this),this.options.metaRefresh),a.addEventListener("resize",c.util.throttle(function(){f.options.autoResize&&f.resize()}),100)},resize:function(a,b){void 0===a&&void 0===b&&(a=this.container.offsetWidth,b=this.container.offsetHeight),this.width=a||0,this.height=b||0},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},render:function(a,b){var c,d;this.beforeRender&&this.beforeRender(),this._world.emit("beforeRender",{renderer:this,bodies:a,meta:b}),this.options.meta&&this.drawMeta(b),this._interpolateTime=b.interpolateTime;for(var e=0,f=a.length;f>e;++e)c=a[e],d=c.view||(c.view=this.createView(c.geometry,c.styles)),c.hidden||this.drawBody(c,d);return this},createView:function(){throw"You must override the renderer.createView() method."},drawMeta:function(){throw"You must override the renderer.drawMeta() method."},drawBody:function(){throw"You must override the renderer.drawBody() method."}})}(),function(){var a=function e(a,b,c){for(var d,f,g=function(){return e(a,b,c)};d=a.shift();)if(f=d.apply(b,c),f&&f.then)return f.then(g)},b={timestep:6,maxIPF:4,webworker:!1,integrator:"verlet",sleepDisabled:!1,sleepSpeedLimit:.05,sleepVarianceLimit:.02,sleepTimeLimit:500},d=function f(a,b){return this instanceof f?void this.init(a,b):new f(a,b)};d.prototype=c.util.extend({},c.util.pubsub.prototype,{init:function(d,e){var f=this;(c.util.isFunction(d)||c.util.isArray(d))&&(e=d,d={}),this._meta={fps:0,ipf:0},this._bodies=[],this._behaviors=[],this._integrator=null,this._renderer=null,this._paused=!1,this._warp=1,this._time=0,this.options=c.util.options(b),this.options.onChange(function(a){f.timestep(a.timestep)}),this.options(d),this.add(c.integrator(this.options.integrator)),c.util.isFunction(e)?a([e],this,[this,c]):c.util.isArray(e)&&a(e,this,[this,c])},options:null,add:function(a){var b=0,d=a&&a.length||0,e=c.util.isArray(a)?a[0]:a;if(!e)return this;do switch(e.type){case"behavior":this.addBehavior(e);break;case"integrator":this.integrator(e);break;case"renderer":this.renderer(e);break;case"body":this.addBody(e);break;default:throw'Error: failed to add item of unknown type "'+e.type+'" to world'}while(++b-1},integrator:function(a){return void 0===a?this._integrator:this._integrator===a?this:(this._integrator&&(this._integrator.setWorld(null),this.emit("remove:integrator",{integrator:this._integrator})),a&&(this._integrator=a,this._integrator.setWorld(this),this.emit("add:integrator",{integrator:this._integrator})),this)},renderer:function(a){return void 0===a?this._renderer:this._renderer===a?this:(this._renderer&&(this._renderer.setWorld(null),this.emit("remove:renderer",{renderer:this._renderer})),a&&(this._renderer=a,this._renderer.setWorld(this),this.emit("add:renderer",{renderer:this._renderer})),this)},timestep:function(a){return a?(this._dt=+a.toPrecision(4),this._maxJump=a*this.options.maxIPF,this):this._dt},wakeUpAll:function(){var a=0,b=this._bodies.length;for(a=0;b>a;a++)this._bodies[a].sleep(!1)},addBehavior:function(a){return this.has(a)?this:(a.setWorld(this),this._behaviors.push(a),this.emit("add:behavior",{behavior:a}),this)},getBehaviors:function(){return[].concat(this._behaviors)},removeBehavior:function(a){var b=this._behaviors;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:behavior",{behavior:a});break}return this},addBody:function(a){return this.has(a)?this:(a.setWorld(this),this._bodies.push(a),this.emit("add:body",{body:a}),this)},getBodies:function(){return[].concat(this._bodies)},removeBody:function(a){var b=this._bodies;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:body",{body:a});break}return this},findOne:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.find(b._bodies,d)||!1},find:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.filter(b._bodies,d)},iterate:function(a){this._integrator.integrate(this._bodies,a)},step:function(a){var b,d,e,f=this._time,g=this._warp,h=1/g,i=this._dt,j=i*h,k=this._maxJump*h,l=this._meta;if(this._paused||void 0===this._animTime)return this._animTime=a||this._animTime||c.util.ticker.now(),this._paused||this.emit("step",l),this;if(a=a||this._animTime+j,b=a-this._animTime,b>k&&(this._animTime=a-k,b=k),d=b*g,e=f+d-i,this.emit("beforeStep"),e>=f)for(;e>=f;)f+=i,this._animTime+=j,this._time=f,this.iterate(i);return l.fps=1e3/(a-this._lastTime),l.ipf=(d/i).toFixed(2),l.interpolateTime=i+e-f,this._lastTime=a,this.emit("step",l),this},warp:function(a){return void 0===a?this._warp:(this._warp=a||1,this)},render:function(){if(!this._renderer)throw"No renderer added to world";return this._renderer.render(this._bodies,this._meta),this.emit("render",{bodies:this._bodies,meta:this._meta,renderer:this._renderer}),this},pause:function(){return this._paused=!0,this.emit("pause"),this},unpause:function(){return this._paused=!1,this.emit("unpause"),this},isPaused:function(){return!!this._paused},destroy:function(){var a=this;a.pause(),this.emit("destroy"),a.off(!0),a.remove(a.getBodies()),a.remove(a.getBehaviors()),a.integrator(null),a.renderer(null) +}}),c.world=d}(),c.integrator("verlet",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=b*b,e=1-this.options.drag,f=null,g=this.prevDt||b,h=.5*(d+b*g),i=0,j=a.length;j>i;++i)f=a[i],c=f.state,"static"===f.treatment||f.sleep(b)?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(c.vel.equals(c.old.vel)&&f.started()?c.vel.clone(c.pos).vsub(c.old.pos):(c.old.pos.clone(c.pos).vsub(c.vel),c.vel.mult(b)),e&&c.vel.mult(e),c.vel.vadd(c.acc.mult(h)),c.vel.mult(1/b),c.old.vel.clone(c.vel),c.acc.zero(),c.angular.vel===c.old.angular.vel&&f.started()?c.angular.vel=c.angular.pos-c.old.angular.pos:(c.old.angular.pos=c.angular.pos-c.angular.vel,c.angular.vel*=b),c.angular.vel+=c.angular.acc*h,c.angular.vel/=b,c.old.angular.vel=c.angular.vel,c.angular.acc=0,f.started(!0))},integratePositions:function(a,b){for(var c,d=null,e=this.prevDt||b,f=b/e,g=0,h=a.length;h>g;++g)d=a[g],c=d.state,"static"===d.treatment||d.sleep()||(c.vel.mult(b*f),c.old.pos.clone(c.pos),c.pos.vadd(c.vel),c.vel.mult(1/(b*f)),c.old.vel.clone(c.vel),c.angular.vel*=b*f,c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel,c.angular.vel/=b*f,c.old.angular.vel=c.angular.vel);this.prevDt=b}}}),c.geometry("point",function(){}),c.body("point",function(a){return{init:function(b){a.init.call(this,b),this.moi=0}}}),c.geometry("circle",function(a){var b={radius:1};return{init:function(d){a.init.call(this,d),this.options.defaults(b),this.options.onChange(function(a){this.radius=a.radius}),this.options(d),this._aabb=c.aabb(),this.radius=this.options.radius},aabb:function(){var a=this.radius;return this._aabb.hw!==a&&(this._aabb=c.aabb(-a,-a,a,a)),c.aabb.clone(this._aabb)},getFarthestHullPoint:function(a,b){return b=b||new c.vector,b.clone(a).normalize().mult(this.radius)},getFarthestCorePoint:function(a,b,d){return b=b||new c.vector,b.clone(a).normalize().mult(this.radius-d)}}}),c.geometry("compound",function(a){var b={};return{init:function(c){a.init.call(this,c),this.options.defaults(b),this.options(c),this.children=[]},addChild:function(a,b,d){return this._aabb=null,this.children.push({g:a,pos:new c.vector(b),angle:d}),this},clear:function(){return this._aabb=null,this.children=[],this},aabb:function(a){if(!a&&this._aabb)return c.aabb.clone(this._aabb);var b,d,e,f=c.scratchpad(),g=c.vector();a=a||0;for(var h=0,i=this.children.length;i>h;h++)d=this.children[h],b=d.g.aabb(a+d.angle),g.clone(d.pos),a&&g.rotate(a),b.x+=g._[0],b.y+=g._[1],e=e?c.aabb.union(e,b,!0):b;return a||(this._aabb=c.aabb.clone(e)),f.done(e)},getFarthestHullPoint:function(a,b){var d,e,f=this.children.length,g=c.scratchpad(),h=g.vector(),i=0,j=0;for(b=b||new c.vector,e=0;f>e;e++)d=this.children[e],d.g.getFarthestHullPoint(a.rotate(-d.angle),h),i=h.rotate(d.angle).vadd(d.pos).proj(a.rotate(d.angle)),i>j&&(j=i,b.swap(h));return g.done(b)},getFarthestCorePoint:function(a,b,d){var e,f,g=this.children.length,h=c.scratchpad(),i=h.vector(),j=0,k=0;for(b=b||new c.vector,f=0;g>f;f++)e=this.children[f],e.g.getFarthestCorePoint(a.rotate(-e.angle),i,d),j=i.rotate(e.angle).vadd(e.pos).proj(a.rotate(e.angle)),j>k&&(k=j,b.swap(i));return h.done(b)}}}),c.geometry("convex-polygon",function(a){var b="Error: The vertices specified do not match that of a _convex_ polygon.",d={};return{init:function(b){var c=this;a.init.call(this,b),this.options.defaults(d),this.options.onChange(function(a){c.setVertices(a.vertices||[])}),this.options(b),c.setVertices(this.options.vertices||[])},setVertices:function(a){var d=c.scratchpad(),e=d.transform(),f=this.vertices=[];if(!c.geometry.isPolygonConvex(a))throw b;e.setRotation(0),e.setTranslation(c.geometry.getPolygonCentroid(a).negate());for(var g=0,h=a.length;h>g;++g)f.push(new c.vector(a[g]).translate(e));return this._area=c.geometry.getPolygonArea(f),this._aabb=!1,d.done(this)},aabb:function(a){if(!a&&this._aabb)return c.aabb.clone(this._aabb);var b,d=c.scratchpad(),e=d.vector(),f=d.transform().setRotation(a||0),g=d.vector().set(1,0).rotateInv(f),h=d.vector().set(0,1).rotateInv(f),i=this.getFarthestHullPoint(g,e).proj(g),j=-this.getFarthestHullPoint(g.negate(),e).proj(g),k=this.getFarthestHullPoint(h,e).proj(h),l=-this.getFarthestHullPoint(h.negate(),e).proj(h);return b=c.aabb(j,l,i,k),a||(this._aabb=c.aabb.clone(b)),d.done(),b},getFarthestHullPoint:function(a,b,d){var e,f,g,h=this.vertices,i=h.length,j=2;if(b=b||new c.vector,2>i)return d&&(d.idx=0),b.clone(h[0]);if(f=h[0].dot(a),e=h[1].dot(a),2===i)return g=e>=f?1:0,d&&(d.idx=g),b.clone(h[g]);if(e>=f){for(;i>j&&e>=f;)f=e,e=h[j].dot(a),j++;return e>=f&&j++,g=j-2,d&&(d.idx=j-2),b.clone(h[g])}for(j=i;j>1&&f>=e;)j--,e=f,f=h[j].dot(a);return g=(j+1)%i,d&&(d.idx=g),b.clone(h[g])},getFarthestCorePoint:function(a,b,d){var e,f=c.scratchpad(),g=f.vector(),h=f.vector(),i=this.vertices,j=i.length,k=this._area>0,l={};return b=this.getFarthestHullPoint(a,b,l),g.clone(i[(l.idx+1)%j]).vsub(b).normalize().perp(k),h.clone(i[(l.idx-1+j)%j]).vsub(b).normalize().perp(!k),e=d/(1+g.dot(h)),b.vadd(g.vadd(h).mult(e)),f.done(),b}}}),c.geometry("rectangle",function(a){var b={};return{init:function(c){var d=this;a.init.call(this,c),this.options.defaults(b),this.options.onChange(function(){d.width=d.options.width||1,d.height=d.options.height||1}),this.options(c)},aabb:function(a){if(!a)return c.aabb(this.width,this.height);var b=c.scratchpad(),d=b.vector(),e=b.transform().setRotation(a||0),f=b.vector().set(1,0).rotateInv(e),g=b.vector().set(0,1).rotateInv(e),h=this.getFarthestHullPoint(f,d).proj(f),i=-this.getFarthestHullPoint(f.negate(),d).proj(f),j=this.getFarthestHullPoint(g,d).proj(g),k=-this.getFarthestHullPoint(g.negate(),d).proj(g);return b.done(),c.aabb(i,k,h,j)},getFarthestHullPoint:function(a,b){b=b||new c.vector;var d=a.x,e=a.y;return d=0===d?0:0>d?.5*-this.width:.5*this.width,e=0===e?0:0>e?.5*-this.height:.5*this.height,b.set(d,e)},getFarthestCorePoint:function(a,b,c){var d,e;return b=this.getFarthestHullPoint(a,b),d=b.x,e=b.y,b.x=0===d?0:0>d?d+c:d-c,b.y=0===e?0:0>e?e+c:e-c,b}}}),c.body("circle",function(a){var b={radius:1};return{init:function(d){a.init.call(this,d),d=c.util.extend({},b,d),this.geometry=c.geometry("circle",{radius:d.radius}),this.recalc()},recalc:function(){a.recalc.call(this),this.moi=this.mass*this.geometry.radius*this.geometry.radius/2}}}),c.body("compound",function(a){return{init:function(b){a.init.call(this,b),this.mass=0,this.moi=0,this.children=[],this.geometry=c.geometry("compound"),this.addChildren(b.children)},connect:function(){if(this.mass<=0)throw"Can not add empty compound body to world."},addChild:function(a){return this.addChildren([a]),this},addChildren:function(a){var b,d,e,f=this,g=c.scratchpad(),h=g.vector().zero(),i=a&&a.length,j=0;if(!i)return g.done(this);for(e=0;i>e;e++)b=a[e],b._world&&b._world.remove(b),this.children.push(b),this.geometry.addChild(b.geometry,new c.vector(b.offset).rotate(b.state.angular.pos).vadd(b.state.pos),b.state.angular.pos),d=b.state.pos,h.add(d._[0]*b.mass,d._[1]*b.mass),j+=b.mass;return this.mass+=j,h.mult(1/this.mass),this.offset.vsub(h),this._world&&this._world.one("render",function(){f.view=null}),this.recalc(),g.done(this)},clear:function(){return this._aabb=null,this.moi=0,this.mass=0,this.offset.zero(),this.children=[],this.geometry.clear(),this},refreshGeometry:function(){this.geometry.clear();for(var a,b=0,d=this.children.length;d>b;b++)a=this.children[b],this.geometry.addChild(a.geometry,new c.vector(a.state.pos).vadd(a.offset),a.state.angular.pos);return this},recalc:function(){a.recalc.call(this);for(var b,c=0,d=0,e=this.children.length;e>d;d++)b=this.children[d],b.recalc(),c+=b.moi+b.mass*b.state.pos.normSq();return this.moi=c,this}}}),c.body("convex-polygon",function(a){var b={};return{init:function(d){a.init.call(this,d),d=c.util.extend({},b,d),this.geometry=c.geometry("convex-polygon",{vertices:d.vertices}),this.recalc()},recalc:function(){a.recalc.call(this),this.moi=c.geometry.getPolygonMOI(this.geometry.vertices)}}}),c.body("rectangle",function(a){var b={};return{init:function(d){a.init.call(this,d),d=c.util.extend({},b,d),this.geometry=c.geometry("rectangle",{width:d.width,height:d.height}),this.recalc()},recalc:function(){var b=this.geometry.width,c=this.geometry.height;a.recalc.call(this),this.moi=(b*b+c*c)*this.mass/12}}}),c.behavior("attractor",function(a){var b={pos:null,strength:1,order:2,max:!1,min:!1};return{init:function(d){var e=this;this._pos=new c.vector,a.init.call(this),this.options.defaults(b),this.options.onChange(function(a){e._maxDist=a.max===!1?1/0:a.max,e._minDist=a.min?a.min:10,e.position(a.pos)}),this.options(d)},position:function(a){var b=this;return a?(this._pos.clone(a),b):this._pos.values()},behave:function(){for(var a,b,d,e=this.getTargets(),f=this.options.order,g=this.options.strength,h=this._minDist,i=this._maxDist,j=c.scratchpad(),k=j.vector(),l=0,m=e.length;m>l;l++)a=e[l],k.clone(this._pos),k.vsub(a.state.pos),b=k.norm(),b>h&&i>b&&(d=g/Math.pow(b,f),a.accelerate(k.normalize().mult(d)));j.done()}}}),c.behavior("body-collision-detection",function(a){var b=[],d=function(a,d){var e=c.util.pairHash(a.uid,d.uid),f=b[e];return f||(f=b[e]=function(b){var c=f.tA,e=f.tB,g=f.tmpv1,h=f.tmpv2;return f.useCore?(g=a.geometry.getFarthestCorePoint(b.rotateInv(c),g,f.marginA),h=d.geometry.getFarthestCorePoint(b.rotate(c).rotateInv(e).negate(),h,f.marginB)):(g=a.geometry.getFarthestHullPoint(b.rotateInv(c),g),h=d.geometry.getFarthestHullPoint(b.rotate(c).rotateInv(e).negate(),h)),g.vadd(a.offset).transform(c),h.vadd(d.offset).transform(e),b.negate().rotate(e),{a:g.values(),b:h.values(),pt:g.vsub(h).values()}},f.tA=new c.transform,f.tB=new c.transform,f.tmpv1=new c.vector,f.tmpv2=new c.vector),f.useCore=!1,f.margin=0,f.tA.setRotation(a.state.angular.pos).setTranslation(a.state.pos),f.tB.setRotation(d.state.angular.pos).setTranslation(d.state.pos),f.bodyA=a,f.bodyB=d,f},e=function(a,b){var e,f,g,h,i=c.scratchpad(),j=i.vector(),k=i.vector(),l=i.vector(),m=!1,n=a.aabb(),o=Math.min(n.hw,n.hh),p=b.aabb(),q=Math.min(p.hw,p.hh);if(g=d(a,b),j.clone(a.state.pos).vadd(a.getGlobalOffset(l)).vsub(b.state.pos).vsub(b.getGlobalOffset(l)),f=c.gjk(g,j,!0),f.overlap){for(m={bodyA:a,bodyB:b},h=.01*Math.min(o||1,q||1),g.useCore=!0,g.marginA=0,g.marginB=0;(f.overlap||0===f.distance)&&(g.marginA=e)return i.done(!1);m.overlap=e,m.norm=j.clone(f.closest.b).vsub(k.clone(f.closest.a)).normalize().values(),m.mtv=j.mult(e).values(),m.pos=j.clone(m.norm).mult(g.marginA).vadd(k.clone(f.closest.a)).vsub(a.state.pos).values()}return i.done(m)},f=function(a,b){var d,e=c.scratchpad(),f=e.vector(),g=e.vector(),h=!1;return f.clone(b.state.pos).vadd(b.getGlobalOffset(g)).vsub(a.state.pos).vsub(a.getGlobalOffset(g)),d=f.norm()-(a.geometry.radius+b.geometry.radius),f.equals(c.vector.zero)&&f.set(1,0),0>=d&&(h={bodyA:a,bodyB:b,norm:f.normalize().values(),mtv:f.mult(-d).values(),pos:f.mult(-a.geometry.radius/d).vadd(g).values(),overlap:-d}),e.done(h)},g=function i(a,b){if(!("static"!==a.treatment&&"kinematic"!==a.treatment||"static"!==b.treatment&&"kinematic"!==b.treatment))return!1;if("circle"===a.geometry.name&&"circle"===b.geometry.name)return f(a,b);if("compound"===a.geometry.name||"compound"===b.geometry.name){var d,g,h,j,k="compound"===a.geometry.name,l=k?a:b,m=k?b:a,n=[],o=c.scratchpad(),p=(o.vector(),o.vector()),q=m.aabb();for(h=0,j=l.children.length;j>h;h++){if(g=l.children[h],p.clone(g.state.pos),g.offset.vadd(p.vadd(l.offset).rotate(-g.state.angular.pos)),g.state.pos.clone(l.state.pos),g.state.angular.pos+=l.state.angular.pos,c.aabb.overlap(q,g.aabb()))if(d=i(m,g),d instanceof Array)for(var r,s=0,t=d.length;t>s;s++)r=d[s],r.bodyA===g?r.bodyA=l:r.bodyB=l,n.push(r);else d&&(d.bodyA===g?d.bodyA=l:d.bodyB=l,n.push(d));g.state.angular.pos-=l.state.angular.pos,g.offset.vsub(p),g.state.pos.clone(p.rotate(g.state.angular.pos).vsub(l.offset))}return o.done(n)}return e(a,b)},h={check:"collisions:candidates",channel:"collisions:detected"};return{init:function(b){a.init.call(this),this.options.defaults(h),this.options(b)},connect:function(a){this.options.check===!0?a.on("integrate:velocities",this.checkAll,this):a.on(this.options.check,this.check,this)},disconnect:function(a){this.options.check===!0?a.off("integrate:velocities",this.checkAll,this):a.off(this.options.check,this.check,this)},check:function(a){for(var b,d,e,f=a.candidates,h=this.getTargets(),i=[],j=this.prevContacts||{},k={},l=c.util.pairHash,m=0,n=f.length;n>m;++m)if(b=f[m],h===this._world._bodies||c.util.indexOf(h,b.bodyA)>-1&&c.util.indexOf(h,b.bodyB)>-1)if(d=g(b.bodyA,b.bodyB),d instanceof Array)for(var o,p=0,q=d.length;q>p;p++)o=d[p],o&&(e=l(b.bodyA.uid,b.bodyB.uid),k[e]=!0,o.collidedPreviously=j[e],i.push(o));else d&&(e=l(b.bodyA.uid,b.bodyB.uid),k[e]=!0,d.collidedPreviously=j[e],i.push(d));this.prevContacts=k,i.length&&this._world.emit(this.options.channel,{collisions:i})},checkAll:function(a){for(var b,d,e,f,h=this.getTargets(),i=(a.dt,[]),j=this.prevContacts||{},k={},l=c.util.pairHash,m=0,n=h.length;n>m;m++){b=h[m];for(var o=m+1;n>o;o++)if(d=h[o],e=g(b,d),e instanceof Array)for(var p,q=0,r=e.length;r>q;q++)p=e[q],p&&(f=l(b.uid,d.uid),k[f]=!0,p.collidedPreviously=j[f],i.push(p));else e&&(f=l(b.uid,d.uid),k[f]=!0,e.collidedPreviously=j[f],i.push(e))}this.prevContacts=k,i.length&&this._world.emit(this.options.channel,{collisions:i})}}}),c.behavior("body-impulse-response",function(a){function b(a){return a.uid}function d(a,b,c){var d,e;return e=b.norm(),d=e-a.proj(b),d=Math.max(0,Math.min(e,d)),0===e?c.zero():c.clone(b).mult(d/e),c}var e={check:"collisions:detected",mtvThreshold:1,bodyExtractDropoff:.5,forceWakeupAboveOverlapThreshold:!0};return{init:function(b){a.init.call(this),this.options.defaults(e),this.options(b),this._bodyList=[]},applyTo:!1,connect:function(a){a.on(this.options.check,this.respond,this)},disconnect:function(a){a.off(this.options.check,this.respond,this)},collideBodies:function(a,b,e,f,g,h){var i="static"===a.treatment||"kinematic"===a.treatment,j="static"===b.treatment||"kinematic"===b.treatment,k=c.scratchpad(),l=k.vector().clone(g);if(i&&j)return void k.done();var m,n,o,p,q=i?0:1/a.moi,r=j?0:1/b.moi,s=i?0:1/a.mass,t=j?0:1/b.mass,u=a.restitution*b.restitution,v=a.cof*b.cof,w=k.vector().clone(e),x=k.vector().clone(w).perp(),y=k.vector(),z=k.vector().clone(f),A=k.vector().clone(f).vadd(a.state.pos).vsub(b.state.pos),B=a.state.angular.vel,C=b.state.angular.vel,D=k.vector().clone(b.state.vel).vadd(y.clone(A).perp().mult(C)).vsub(a.state.vel).vsub(y.clone(z).perp().mult(B)),E=z.proj(w),F=z.proj(x),G=A.proj(w),H=A.proj(x),I=D.proj(w),J=D.proj(x);return h&&(i?(d(b._mtvTotal,l,y),b._mtvTotal.vadd(y)):j?(d(a._mtvTotal,l.negate(),y),a._mtvTotal.vadd(y),l.negate()):(p=.5,l.mult(p),d(b._mtvTotal,l,y),b._mtvTotal.vadd(y),l.clone(g).mult(p-1),d(a._mtvTotal,l,y),a._mtvTotal.vadd(y))),I>=0?void k.done():(q=1/0===q?0:q,r=1/0===r?0:r,m=-((1+u)*I)/(s+t+q*F*F+r*H*H),i?(b.state.vel.vadd(w.mult(m*t)),b.state.angular.vel-=m*r*H):j?(a.state.vel.vsub(w.mult(m*s)),a.state.angular.vel+=m*q*F):(b.state.vel.vadd(w.mult(m*t)),b.state.angular.vel-=m*r*H,a.state.vel.vsub(w.mult(s*b.mass)),a.state.angular.vel+=m*q*F),v&&J&&(o=Math.abs(J)/(s+t+q*E*E+r*G*G),n=0>J?-1:1,m=v*Math.abs(m),m=Math.min(m,o),m*=n,i?(b.state.vel.vsub(x.mult(m*t)),b.state.angular.vel-=m*r*G):j?(a.state.vel.vadd(x.mult(m*s)),a.state.angular.vel+=m*q*E):(b.state.vel.vsub(x.mult(m*t)),b.state.angular.vel-=m*r*G,a.state.vel.vadd(x.mult(s*b.mass)),a.state.angular.vel+=m*q*E)),a.sleep()&&a.sleepCheck(),b.sleep()&&b.sleepCheck(),void k.done())},_pushUniq:function(a){var d=c.util.sortedIndex(this._bodyList,a,b);this._bodyList[d]!==a&&this._bodyList.splice(d,0,a)},respond:function(a){var b,d,e,f,g=this,h=a.collisions;for(d=0,e=h.length;e>d;++d)b=h[d],this._pushUniq(b.bodyA),this._pushUniq(b.bodyB),b.bodyA._mtvTotal=b.bodyA._mtvTotal||new c.vector,b.bodyB._mtvTotal=b.bodyB._mtvTotal||new c.vector,b.bodyA._oldmtvTotal=b.bodyA._oldmtvTotal||new c.vector,b.bodyB._oldmtvTotal=b.bodyB._oldmtvTotal||new c.vector,g.collideBodies(b.bodyA,b.bodyB,b.norm,b.pos,b.mtv,b.collidedPreviously);for(d=0,e=this._bodyList.length;e>d;++d)f=this._bodyList.pop(),f._mtvTotal.normSq()b;++b)a[b].accelerate(this._acc)}}}),c.behavior("edge-collision-detection",function(a){var b=function(a,b,d){var e,f=a.aabb(),g=c.scratchpad(),h=a.getGlobalOffset(g.vector()),i=g.transform(),j=g.vector(),k=g.vector(),l=!1,m=[];return e=f.x+f.hw-b.max.x,e>=0&&(j.set(1,0).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:1,y:0},mtv:{x:e,y:0},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),e=f.y+f.hh-b.max.y,e>=0&&(j.set(0,1).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:0,y:1},mtv:{x:0,y:e},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),e=b.min.x-(f.x-f.hw),e>=0&&(j.set(-1,0).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:-1,y:0},mtv:{x:-e,y:0},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),e=b.min.y-(f.y-f.hh),e>=0&&(j.set(0,-1).rotateInv(i.setRotation(a.state.angular.pos)),l={bodyA:a,bodyB:d,overlap:e,norm:{x:0,y:-1},mtv:{x:0,y:-e},pos:a.geometry.getFarthestHullPoint(j,k).rotate(i).vadd(h).values()},m.push(l)),g.done(),m},d=function(a,c,d){return b(a,c,d)},e={aabb:null,restitution:.99,cof:1,channel:"collisions:detected"};return{init:function(b){a.init.call(this),this.options.defaults(e),this.options(b),this.setAABB(this.options.aabb),this.restitution=this.options.restitution,this.body=c.body("point",{treatment:"static",restitution:this.options.restitution,cof:this.options.cof})},setAABB:function(a){if(!a)throw"Error: aabb not set";return this._edges={min:{x:a.x-a.hw,y:a.y-a.hh},max:{x:a.x+a.hw,y:a.y+a.hh}},this},connect:function(a){a.on("integrate:positions",this.checkAll,this,2)},disconnect:function(a){a.off("integrate:positions",this.checkAll,this,2)},checkAll:function(a){for(var b,e,f,g=this.getTargets(),h=(a.dt,[]),i=this._edges,j=this.body,k=this.prevContacts||{},l={},m=c.util.pairHash,n=0,o=g.length;o>n;n++)if(b=g[n],"dynamic"===b.treatment&&(e=d(b,i,j))){f=m(b.uid,j.uid);for(var p=0,q=e.length;q>p;p++)l[f]=!0,e[p].collidedPreviously=k[f];h.push.apply(h,e)}this.prevContacts=l,h.length&&this._world.emit(this.options.channel,{collisions:h})}}}),c.behavior("interactive",function(d){if(!b)return{};var e={el:null,moveThrottle:10,minVel:{x:-5,y:-5},maxVel:{x:5,y:5}},f=function(a){var b=0,c=0;if(a.offsetParent)do b+=a.offsetLeft,c+=a.offsetTop;while(a=a.offsetParent);return{left:b,top:c}};return{init:function(a){var g=this;if(d.init.call(this),this.options.defaults(e),this.options(a),this.bodyData={},this.bodyDataByUID={},this.el="string"==typeof this.options.el?b.getElementById(this.options.el):this.options.el,!this.el)throw"No DOM element specified";g.grab=function(a){var b,d,e,h,i,j,k,l;if(g._world)for(a.changedTouches||(a.changedTouches=[a]),i=f(a.target),k=0,l=a.changedTouches.length;l>k;k++)h=a.changedTouches[k],e=h.identifier||h.pointerId||"mouse",b={idx:e,x:h.pageX-i.left,y:h.pageY-i.top},d=g._world.findOne({$at:new c.vector(b),$in:g.getTargets()}),d?(d.state.vel.zero(),d.state.angular.vel=0,d.isGrabbed=!0,j=g.bodyData[e]||{},j.body=d,d.sleep(!1),j.time=c.util.ticker.now(),j.treatment=g.bodyDataByUID[d.uid]?g.bodyDataByUID[d.uid].treatment:d.treatment,d.treatment="kinematic",j.pos=j.pos||new c.vector,j.pos.clone(b),j.offset=j.offset||new c.vector,j.offset.clone(b).vsub(d.state.pos),j.oldPos=j.oldPos||new c.vector,j.oldPos.clone(b),b.body=d,g.bodyData[e]=j,g.bodyDataByUID[d.uid]=j,g._world.emit("interact:grab",b)):g._world.emit("interact:poke",b)},g.move=c.util.throttle(function(a){var b,d,e,h,i,j,k,l;if(g._world)for(a.changedTouches||(a.changedTouches=[a]),i=f(g.el),k=0,l=a.changedTouches.length;l>k;k++)h=a.changedTouches[k],e=h.identifier||h.pointerId||"mouse",b={idx:e,x:h.pageX-i.left,y:h.pageY-i.top},j=g.bodyData[e],j&&(d=j.body,d.sleep(!1),j.time=c.util.ticker.now(),j.oldPos.clone(j.pos),j.pos.clone(b),b.body=d),g._world.emit("interact:move",b)},g.options.moveThrottle),g.release=function(a){var b,d,e,h,i,j,k,l,m;if(g._world)for(a.changedTouches||(a.changedTouches=[a]),l=0,m=a.changedTouches.length;m>l;l++)i=f(g.el),h=a.changedTouches[l],e=h.identifier||h.pointerId||"mouse",b={idx:e,x:h.pageX-i.left,y:h.pageY-i.top},j=g.bodyData[e],j&&(d=j.body,d.sleep(!1),j.pos.clone(b),k=Math.max(c.util.ticker.now()-j.time,g.options.moveThrottle),d.treatment=j.treatment,d.state.vel.clone(j.pos).vsub(j.oldPos).mult(1/k),d.state.vel.clamp(g.options.minVel,g.options.maxVel),d.isGrabbed=!1,b.body=d,delete d.isGrabbed),g._world.emit("interact:release",b),delete g.bodyData[e]}},connect:function(b){b.on("integrate:positions",this.behave,this),a.PointerEvent?(this.el.addEventListener("pointerdown",this.grab),a.addEventListener("pointermove",this.move),a.addEventListener("pointerup",this.release)):(this.el.addEventListener("mousedown",this.grab),this.el.addEventListener("touchstart",this.grab),a.addEventListener("mousemove",this.move),a.addEventListener("touchmove",this.move),a.addEventListener("mouseup",this.release),a.addEventListener("touchend",this.release))},disconnect:function(b){b.off("integrate:positions",this.behave,this),a.PointerEvent?(this.el.removeEventListener("pointerdown",this.grab),a.removeEventListener("pointermove",this.move),a.removeEventListener("pointerup",this.release)):(this.el.removeEventListener("mousedown",this.grab),this.el.removeEventListener("touchstart",this.grab),a.removeEventListener("mousemove",this.move),a.removeEventListener("touchmove",this.move),a.removeEventListener("mouseup",this.release),a.removeEventListener("touchend",this.release))},behave:function(a){var b,c,d,e=this,f=Math.max(a.dt,e.options.moveThrottle);for(var g in e.bodyData)d=e.bodyData[g],c=d.body,b=c.state,b.vel.clone(d.pos).vsub(d.offset).vsub(b.pos).mult(1/f)}}}),c.behavior("newtonian",function(a){var b={strength:1,max:!1,min:!1};return{init:function(c){var d=this;a.init.call(this),this.options.defaults(b),this.options.onChange(function(a){d._maxDistSq=a.max===!1?1/0:a.max*a.max,d._minDistSq=a.min?a.min*a.min:100*a.strength}),this.options(c)},calcPotential:function(a,b,d){var e,f,g,h=this.options.strength,i=this._minDistSq,j=this._maxDistSq;return g=d||new c.vector,g.clone(b).vsub(a),e=g.normSq(),e>i&&j>e?(f=h/e,g.normalize().mult(f)):g.zero()},behave:function(){var a,b,d,e,f,g,h,i,j,k,l,m,n=this.getTargets(),o=c.scratchpad(),p=o.vector(),q=o.vector(),r=o.vector();for(h=0,k=n.length;k>h;h++)for(a=n[h],g=h+1;k>g;g++){if(b=n[g],"compound"===a.name?d=a:"compound"===b.name&&(d=b,b=a),d)if("compound"===b.name)for(i=0,l=d.children.length;l>i;i++)for(e=d.children[i],d.toWorldCoords(q.clone(e.state.pos).vadd(d.offset)),j=0,m=b.children.length;m>j;j++)f=b.children[j],b.toWorldCoords(r.clone(f.state.pos).vadd(b.offset)),this.calcPotential(q,r,p),d.accelerate(p.mult(f.mass)),b.accelerate(p.mult(e.mass/f.mass).negate());else for(i=0,l=d.children.length;l>i;i++)e=d.children[i],d.toWorldCoords(q.clone(e.state.pos).vadd(d.offset)),this.calcPotential(q,b.state.pos,p),d.accelerate(p.mult(b.mass)),b.accelerate(p.mult(e.mass/b.mass).negate());else this.calcPotential(a.state.pos,b.state.pos,p),a.accelerate(p.mult(b.mass)),b.accelerate(p.mult(a.mass/b.mass).negate());d=null}o.done()}}}),c.behavior("sweep-prune",function(a){var b=1,d=function(){return b++},e={x:0,y:1},f=2,g=c.util.pairHash;return{init:function(b){a.init.call(this),this.options.defaults({channel:"collisions:candidates"}),this.options(b),this.encounters=[],this.candidates=[],this.clear()},clear:function(){this.tracked=[],this.pairs=[],this.intervalLists=[];for(var a=0;f>a;++a)this.intervalLists[a]=[]},connect:function(a){a.on("add:body",this.trackBody,this),a.on("remove:body",this.untrackBody,this),a.on("integrate:positions",this.sweep,this,1);for(var b=a.getBodies(),c=0,d=b.length;d>c;++c)this.trackBody({body:b[c]})},disconnect:function(a){a.off("add:body",this.trackBody,this),a.off("remove:body",this.untrackBody,this),a.off("integrate:positions",this.sweep,this,1),this.clear()},broadPhase:function(){return this.updateIntervals(),this.sortIntervalLists(),this._world&&this._world.emit("sweep-prune:intervals",this.intervalLists),this.checkOverlaps()},sortIntervalLists:function(){for(var a,b,c,d,e,g,h,i,j,k=0;f>k;++k)for(a=this.intervalLists[k],c=0,b=a.length,j=k;++c0&&(i>g||i===g&&h.type&&!e.type);)a[d]=h,d--,h=a[d-1],i=h&&h.val.get(j);a[d]=e}},getPair:function(a,b,c){var d=g(a.id,b.id);if(d===!1)return null;var e=this.pairs[d];if(!e){if(!c)return null;e=this.pairs[d]={bodyA:a.body,bodyB:b.body,flag:1}}return c&&(e.flag=1),e},checkOverlaps:function(){var a,b,d,g,h,i,j,k,l,m=1<q;++q)for(a=0===q,h=this.intervalLists[q],j=0,i=h.length;i>j;j++)if(g=h[j],b=g.tracker,g.type)for(k=o,k=o-1;k>=0;k--)d=n[k],d===b?(o-1>k?n[k]=n.pop():n.pop(),o--):(l=this.getPair(b,d,a),l&&l.flag=0;)a=d[e],b=a.interval,c=a.body.aabb(),b.min.val.clone(c).sub(c.hw,c.hh),b.max.val.clone(c).add(c.hw,c.hh)},trackBody:function(a){var b=a.body,e={id:d(),body:b},g={min:{type:!1,val:new c.vector,tracker:e},max:{type:!0,val:new c.vector,tracker:e}};e.interval=g,this.tracked.push(e);for(var h=0;f>h;++h)this.intervalLists[h].push(g.min,g.max)},untrackBody:function(a){for(var b,c,d,e,g=a.body,h=this.tracked,i=0,j=h.length;j>i;++i)if(d=h[i],d.body===g){h.splice(i,1);for(var k=0;f>k;++k){e=0,b=this.intervalLists[k];for(var l=0,m=b.length;m>l;++l)if(c=b[l],c===d.interval.min||c===d.interval.max){if(b.splice(l,1),l--,j--,e>0)break;e++}}break}},sweep:function(){var a,b=this;a=b.broadPhase(),a.length&&this._world.emit(this.options.channel,{candidates:a})}}}),c.behavior("verlet-constraints",function(a){var b=2*Math.PI,d={iterations:2};return{init:function(b){a.init.call(this),this.options.defaults(d),this.options(b),this._distanceConstraints=[],this._angleConstraints=[]},connect:function(a){var b=a.integrator();if(b&&b.name.indexOf("verlet")<0)throw'The rigid constraint manager needs a world with a "verlet" compatible integrator.';a.on("integrate:positions",this.resolve,this)},disconnect:function(a){a.off("integrate:positions",this.resolve,this)},drop:function(){return this._distanceConstraints=[],this._angleConstraints=[],this},distanceConstraint:function(a,b,d,e){var f;return a&&b?(f={id:c.util.uniqueId("dis-constraint"),type:"dis",bodyA:a,bodyB:b,stiffness:d||.5,targetLength:e||b.state.pos.dist(a.state.pos)},f.targetLengthSq=f.targetLength*f.targetLength,this._distanceConstraints.push(f),f):!1},angleConstraint:function(a,b,d,e,f){var g;return a&&b?(g={id:c.util.uniqueId("ang-constraint"),type:"ang",bodyA:a,bodyB:b,bodyC:d,stiffness:e||.5,targetAngle:f||b.state.pos.angle2(a.state.pos,d.state.pos)},this._angleConstraints.push(g),g):!1},remove:function(a){var b,d,e,f,g;if(e=c.util.isObject(a),d=e?a.type:a.substr(0,3),b="ang"===d?this._angleConstraints:this._distanceConstraints,e){for(f=0,g=b.length;g>f;++f)if(b[f]===a)return b.splice(f,1),this}else for(f=0,g=b.length;g>f;++f)if(b[f].id===a)return b.splice(f,1),this;return this},resolveAngleConstraints:function(a){for(var d,e,f,g,h=this._angleConstraints,i=c.scratchpad(),j=i.transform(),k=0,l=h.length;l>k;++k)d=h[k],e=d.bodyB.state.pos.angle2(d.bodyA.state.pos,d.bodyC.state.pos),f=e-d.targetAngle,f&&(f<=-Math.PI?f+=b:f>=Math.PI&&(f-=b),j.setTranslation(d.bodyB.state.pos),f*=-a*d.stiffness,"dynamic"===d.bodyA.treatment&&"dynamic"===d.bodyB.treatment&&"dynamic"===d.bodyC.treatment&&(g=1/(d.bodyA.mass+d.bodyB.mass+d.bodyC.mass)),"dynamic"===d.bodyA.treatment&&(e="dynamic"===d.bodyB.treatment&&"dynamic"===d.bodyC.treatment?f*(d.bodyB.mass+d.bodyC.mass)*g:"dynamic"!==d.bodyB.treatment?f*d.bodyC.mass/(d.bodyC.mass+d.bodyA.mass):f*d.bodyB.mass/(d.bodyB.mass+d.bodyA.mass),j.setRotation(e),d.bodyA.state.pos.translateInv(j),d.bodyA.state.pos.rotate(j),d.bodyA.state.pos.translate(j)),"dynamic"===d.bodyC.treatment&&(e="dynamic"===d.bodyA.treatment&&"dynamic"===d.bodyB.treatment?-f*(d.bodyB.mass+d.bodyA.mass)*g:"dynamic"!==d.bodyB.treatment?-f*d.bodyA.mass/(d.bodyC.mass+d.bodyA.mass):-f*d.bodyB.mass/(d.bodyB.mass+d.bodyC.mass),j.setRotation(e),d.bodyC.state.pos.translateInv(j),d.bodyC.state.pos.rotate(j),d.bodyC.state.pos.translate(j)),"dynamic"===d.bodyB.treatment&&(e="dynamic"===d.bodyA.treatment&&"dynamic"===d.bodyC.treatment?f*(d.bodyA.mass+d.bodyC.mass)*g:"dynamic"!==d.bodyA.treatment?f*d.bodyC.mass/(d.bodyC.mass+d.bodyB.mass):f*d.bodyA.mass/(d.bodyA.mass+d.bodyC.mass),j.setRotation(e).setTranslation(d.bodyA.state.pos),d.bodyB.state.pos.translateInv(j),d.bodyB.state.pos.rotate(j),d.bodyB.state.pos.translate(j),j.setTranslation(d.bodyC.state.pos),d.bodyB.state.pos.translateInv(j),d.bodyB.state.pos.rotateInv(j),d.bodyB.state.pos.translate(j)),d.bodyA.sleepCheck(),d.bodyB.sleepCheck(),d.bodyC.sleepCheck());i.done()},resolveDistanceConstraints:function(a){for(var b,d,e,f,g=this._distanceConstraints,h=c.scratchpad(),i=h.vector(),j=0,k=g.length;k>j;++j)b=g[j],i.clone(b.bodyB.state.pos).vsub(b.bodyA.state.pos),d=i.normSq()||1e-4*Math.random(),e=a*b.stiffness*(d-b.targetLengthSq)/d,i.mult(e),f="dynamic"!==b.bodyA.treatment||"dynamic"!==b.bodyB.treatment?1:b.bodyB.mass/(b.bodyA.mass+b.bodyB.mass),"dynamic"===b.bodyA.treatment&&("dynamic"===b.bodyB.treatment&&i.mult(f),b.bodyA.state.pos.vadd(i),"dynamic"===b.bodyB.treatment&&i.mult(1/f)),"dynamic"===b.bodyB.treatment&&("dynamic"===b.bodyA.treatment&&i.mult(1-f),b.bodyB.state.pos.vsub(i)),b.bodyA.sleepCheck(),b.bodyB.sleepCheck();h.done()},shuffleConstraints:function(){this._distanceConstraints=c.util.shuffle(this._distanceConstraints),this._angleConstraints=c.util.shuffle(this._angleConstraints)},resolve:function(){for(var a=this.options.iterations,b=1/a,c=0;a>c;c++)this.resolveDistanceConstraints(b),this.resolveAngleConstraints(b)},getConstraints:function(){return{distanceConstraints:[].concat(this._distanceConstraints),angleConstraints:[].concat(this._angleConstraints)}}}}),c.integrator("improved-euler",function(a){return{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=1-this.options.drag,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"===e.treatment||e.sleep(b)?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(c.old.vel.clone(c.vel),c.old.acc.clone(c.acc),c.vel.vadd(c.acc.mult(b)),d&&c.vel.mult(d),c.acc.zero(),c.old.angular.vel=c.angular.vel,c.angular.vel+=c.angular.acc*b,c.angular.acc=0)},integratePositions:function(a,b){for(var d,e=.5*b*b,f=null,g=c.scratchpad(),h=g.vector(),i=0,j=a.length;j>i;++i)f=a[i],d=f.state,"static"===f.treatment||f.sleep()||(d.old.pos.clone(d.pos),h.clone(d.old.vel),d.pos.vadd(h.mult(b)).vadd(d.old.acc.mult(e)),d.old.acc.zero(),d.old.angular.pos=d.angular.pos,d.angular.pos+=d.old.angular.vel*b+d.old.angular.acc*e,d.old.angular.acc=0); +g.done()}}}),c.integrator("velocity-verlet-alt",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=1-this.options.drag,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"!==e.treatment?(e.started()||(c.old.acc.clone(c.acc),c.old.acc.mult(b),c.old.vel.clone(c.vel).vsub(c.old.acc),c.old.acc.mult(1/b)),d&&c.vel.mult(d),c.vel.vadd(c.old.acc.vadd(c.acc).mult(.5*b)),e.started()||(c.old.angular.acc=c.angular.acc,c.old.angular.vel=c.angular.vel-c.old.angular.acc*b),c.angular.vel+=.5*(c.angular.acc+c.old.angular.acc)*b,c.angular.acc=0,e.started(!0)):(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0)},integratePositions:function(a,b){for(var c,d=b*b,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"!==e.treatment&&(c.old.pos.clone(c.pos),c.old.vel.mult(b),c.old.acc.mult(.5*d),c.pos.vadd(c.old.vel).vadd(c.old.acc),c.old.vel.clone(c.vel),c.old.acc.clone(c.acc),c.acc.zero(),c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel*b+.5*c.old.angular.acc*d,c.old.angular.vel=c.angular.vel,c.old.angular.acc=c.angular.acc,c.angular.acc=0)}}}),c.integrator("velocity-verlet",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrate:function(a,b){var c=this._world;return this.integratePositions(a,b),c&&c.emit("integrate:positions",{bodies:a,dt:b}),this.integrateVelocities(a,b),c&&c.emit("integrate:velocities",{bodies:a,dt:b}),this},integrateVelocities:function(a,b){for(var c,d=1-this.options.drag,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"===e.treatment||e.sleep()?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(d&&c.vel.mult(d),c.old.vel.clone(c.vel),c.vel.vadd(c.old.acc.vadd(c.acc).mult(.5*b)),c.old.acc.clone(c.acc),c.acc.zero(),c.old.angular.vel=c.angular.vel,c.old.angular.acc=c.angular.acc,c.angular.vel+=.5*(c.angular.acc+c.old.angular.acc)*b,c.angular.acc=0,e.started(!0))},integratePositions:function(a,b){for(var c,d=b*b,e=null,f=0,g=a.length;g>f;++f)e=a[f],c=e.state,"static"===e.treatment||e.sleep(b)||(e.started()||(c.old.acc.clone(c.acc),c.old.acc.mult(b),c.old.vel.clone(c.vel).vsub(c.old.acc),c.old.acc.mult(1/b)),c.old.pos.clone(c.pos),c.old.vel.mult(b),c.old.acc.mult(.5*d),c.pos.vadd(c.old.vel).vadd(c.old.acc),c.old.vel.mult(1/b),c.old.acc.mult(2/d),e.started()||(c.old.angular.acc=c.angular.acc,c.old.angular.vel=c.angular.vel-c.old.angular.acc*b),c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel*b+.5*c.old.angular.acc*d)}}}),c.renderer("canvas",function(a){if(!b)return{};var d=2*Math.PI,e=function(a,c){var d=b.createElement(a||"div");return c&&(d.innerHTML=c),d},f={white:"#fff",violet:"#542437",blue:"#53777A"},g={metaEl:null,styles:{point:f.blue,circle:{strokeStyle:f.blue,lineWidth:1,fillStyle:f.blue,angleIndicator:f.white},rectangle:{strokeStyle:f.violet,lineWidth:1,fillStyle:f.violet,angleIndicator:f.white},"convex-polygon":{strokeStyle:f.violet,lineWidth:1,fillStyle:f.violet,angleIndicator:f.white}},offset:{x:0,y:0}};return{init:function(d){var f=this;if(a.init.call(this,d),this.options.defaults(g,!0),this.options.onChange(function(){f.options.offset=new c.vector(f.options.offset)}),this.options(d,!0),this.hiddenCanvas=b.createElement("canvas"),this.hiddenCanvas.width=this.hiddenCanvas.height=100,!this.hiddenCanvas.getContext)throw"Canvas not supported";this.hiddenCtx=this.hiddenCanvas.getContext("2d");var h=this.el;if("CANVAS"!==h.nodeName.toUpperCase()&&(h=b.createElement("canvas"),this.el.appendChild(h),"string"==typeof this.options.el&&this.el===b.body&&(h.id=this.options.el),this.el=h),this.container=this.el.parentNode,this.ctx=h.getContext("2d"),this.els={},this.options.meta){var i=this.options.metaEl||e();i.className="pjs-meta",this.els.fps=e("span"),this.els.ipf=e("span"),i.appendChild(e("span","fps: ")),i.appendChild(this.els.fps),i.appendChild(e("br")),i.appendChild(e("span","ipf: ")),i.appendChild(this.els.ipf),h.parentNode.insertBefore(i,h)}this._layers={},this.addLayer("main",this.el),this.options.autoResize?this.resize():this.resize(this.options.width,this.options.height)},layer:function(a){return a in this._layers?this._layers[a]:null},addLayer:function(a,d,e){var f=this,g=[],h=c.util.extend({},this.options.styles),i={id:a,el:d||b.createElement("canvas"),options:c.util.options({width:this.el.width,height:this.el.height,manual:!1,autoResize:!0,follow:null,offset:null,scale:1,zIndex:1})(e)};if(a in this._layers)throw'Layer "'+a+'" already added.';return this.el.parentNode.insertBefore(i.el,this.el),i.el.style.position="absolute",i.el.style.zIndex=i.options.zIndex,i.el.className+=" pjs-layer-"+i.id,i.ctx=i.el.getContext("2d"),i.ctx.scale(1,1),i.el.width=i.options.width,i.el.height=i.options.height,i.bodies=g,i.reset=function(a){return g=a||[],i},i.addToStack=function(a){return c.util.isArray(a)?g.push.apply(g,a):g.push(a),i},i.removeFromStack=function(a){var b,d;if(c.util.isArray(a))for(b=0,d=a.length;d>b;++b)i.removeFromStack(a[b]);else b=c.util.indexOf(g,a),b>-1&&g.splice(b,1);return i},i.render=function(a){var b,d,e,j=c.scratchpad(),k=j.vector().set(0,0),l=i.options.scale,m=g.length,n=f._interpolateTime,o=m||"main"!==i.id?g:f._world._bodies;if(i.options.manual)return j.done(),i;for(i.options.offset&&("center"===i.options.offset?k.add(.5*i.el.width,.5*i.el.height).mult(1/l):k.vadd(i.options.offset).mult(1/l)),i.options.follow&&(k.vsub(i.options.follow.state.pos),k.sub(i.options.follow.state.vel.get(0)*n,i.options.follow.state.vel.get(1)*n)),a!==!1&&i.ctx.clearRect(0,0,i.el.width,i.el.height),1!==l&&(i.ctx.save(),i.ctx.scale(l,l)),e=0,m=o.length;m>e;++e)b=o[e],b.hidden||(d=b.view||(b.view=f.createView(b.geometry,b.styles||h[b.geometry.name])),f.drawBody(b,b.view,i.ctx,k));return 1!==l&&i.ctx.restore(),j.done(),i},this._layers[a]=i,i},removeLayer:function(a){var b=a.id?a.id:a,c=this._layers[b].el;return c!==this.el&&c.parentNode.removeChild(c),delete this._layers[b],this},resize:function(b,c){var d;a.resize.call(this,b,c);for(var e in this._layers)d=this._layers[e],d.options.autoResize&&(d.el.width=this.width,d.el.height=this.height);return this},setStyle:function(a,b){b=b||this.ctx,c.util.isObject(a)?(a.strokeStyle=a.lineWidth?a.strokeStyle:"rgba(0,0,0,0)",c.util.extend(b,a)):(b.fillStyle=b.strokeStyle=a,b.lineWidth=1)},drawCircle:function(a,b,c,e,f){f=f||this.ctx,f.beginPath(),this.setStyle(e,f),f.arc(a,b,c,0,d,!1),f.closePath(),f.stroke(),f.fill()},drawPolygon:function(a,b,c){var d=a[0],e=d.x,f=d.y,g=a.length;c=c||this.ctx,c.beginPath(),this.setStyle(b,c),c.moveTo(e,f);for(var h=1;g>h;++h)d=a[h],e=d.x,f=d.y,c.lineTo(e,f);g>2&&c.closePath(),c.stroke(),c.fill()},drawRect:function(a,b,c,d,e,f){var g=.5*c,h=.5*d;f=f||this.ctx,this.setStyle(e,f),f.beginPath(),f.rect(a-g,b-h,c,d),f.closePath(),f.stroke(),f.fill()},drawLine:function(a,b,c,d){var e=a.x,f=a.y;d=d||this.ctx,d.beginPath(),this.setStyle(c,d),d.moveTo(e,f),e=b.x,f=b.y,d.lineTo(e,f),d.stroke(),d.fill()},draw:function(a,b,c,d){var e=a.name,f=+(d&&d.x),g=+(d&&d.y),h=a.aabb().hw;if(c=c||this.ctx,b=b||this.options.styles[e]||this.options.styles.circle||{},c.save(),c.translate(f,g),"circle"===e)this.drawCircle(0,0,a.radius,b,c);else if("convex-polygon"===e)this.drawPolygon(a.vertices,b,c);else if("rectangle"===e)this.drawRect(0,0,a.width,a.height,b,c);else if("compound"===e)for(var i,j=0,k=a.children.length;k>j;j++)i=a.children[j],c.translate(i.pos.x,i.pos.y),c.rotate(i.angle),this.draw(i.g,b,c),c.rotate(-i.angle),c.translate(-i.pos.x,-i.pos.y);else this.drawCircle(0,0,1,b,c);return"compound"!==e&&b.angleIndicator&&(c.beginPath(),this.setStyle(b.angleIndicator,c),c.moveTo(0,0),c.lineTo(h,0),c.closePath(),c.stroke()),c.restore(),this},createView:function(a,b){var c,d=a.aabb(),e=d.hw+Math.abs(d.x),f=d.hh+Math.abs(d.y),g={x:e+1,y:f+1},h=this.hiddenCtx,i=this.hiddenCanvas;return b=b||this.options.styles[name]||this.options.styles.circle||{},b.src?(c=new Image,c.src=b.src,b.width&&(c.width=b.width),b.height&&(c.height=b.height),c):(g.x+=0|b.lineWidth,g.y+=0|b.lineWidth,i.width=2*e+2+(2*b.lineWidth|0),i.height=2*f+2+(2*b.lineWidth|0),this.draw(a,b,h,g),c=new Image(i.width,i.height),c.src=i.toDataURL("image/png"),c)},drawMeta:function(a){this.els.fps.innerHTML=a.fps.toFixed(2),this.els.ipf.innerHTML=a.ipf},drawBody:function(a,b,c,d){var e,f,g,h=a.state.pos,i=a.offset,j=a.state.vel,k=this._interpolateTime||0;d=d||this.options.offset,c=c||this.ctx,e=h._[0]+d.x+j._[0]*k,f=h._[1]+d.y+j._[1]*k,g=a.state.angular.pos+a.state.angular.vel*k,c.save(),c.translate(e,f),c.rotate(g),c.translate(i._[0],i._[1]),c.drawImage(b,-b.width/2,-b.height/2,b.width,b.height),c.restore()},render:function(a,b){this._world.emit("beforeRender",{renderer:this,meta:b}),this.options.meta&&this.drawMeta(b),this._interpolateTime=b.interpolateTime;for(var c in this._layers)this._layers[c].render();return this}}}),c.renderer("dom",function(a){if(!b)return{};var c={},d=b.createElement("div"),e=function(a){return a.replace(/(?:^|\s)\w/g,function(a){return a.toUpperCase()})},f=function(a){if(c[a])return c[a];for(var b,f=["Webkit","Moz","Ms","O"],g=0,h=f.length;h>g;++g)if(b=f[g]+e(a),b in d.style)return c[a]=b;return b in d.style?c[a]=a:!1},g="pjs-",h="px",i=f("transform"),j=f("borderRadius"),k=function(a,c){var d=b.createElement(a||"div");return c&&(d.innerHTML=c),d};return{init:function(b){a.init.call(this,b);var c=this.el;if(c.style.position="relative",c.style.overflow="hidden",c.style[i]="translateZ(0)",c.style.width=this.options.width+h,c.style.height=this.options.height+h,this.els={},b.meta){var d=k();d.className="pjs-meta",this.els.fps=k("span"),this.els.ipf=k("span"),d.appendChild(k("span","fps: ")),d.appendChild(this.els.fps),d.appendChild(k("br")),d.appendChild(k("span","ipf: ")),d.appendChild(this.els.ipf),c.appendChild(d)}this.options.autoResize?this.resize():this.resize(this.options.width,this.options.height)},resize:function(b,c){a.resize.call(this,b,c),this.el.style.width=this.width+h,this.el.style.height=this.height+h},pointProperties:function(a){a.style.width="2px",a.style.height="2px",a.style.marginLeft="-1px",a.style.marginTop="-1px",a.style[j]="50%"},circleProperties:function(a,b){var c=b.aabb();a.style.width=2*c.hw+h,a.style.height=2*c.hh+h,a.style.marginLeft=-c.hw+h,a.style.marginTop=-c.hh+h,a.style[j]="50%"},rectangleProperties:function(a,b){var c=b.aabb();a.style.width=2*c.hw+h,a.style.height=2*c.hh+h,a.style.marginLeft=-c.hw+h,a.style.marginTop=-c.hh+h},createView:function(a){var b,c=k(),d=a.name+"Properties";if(c.className=g+a.name,c.style.position="absolute",c.style.top="0px",c.style.left="0px","compound"===a.name)for(var e,f=0,h=a.children.length;h>f;f++)e=a.children[f],b=k(),b.className=g+a.name+" "+g+"child",b.style.position="absolute",b.style.top="0px",b.style.left="0px",this[e.g.name+"Properties"]&&this[e.g.name+"Properties"](b,e.g),b.style[i]="translate("+e.pos._[0]+"px,"+e.pos._[1]+"px) rotate("+e.angle+"rad)",c.appendChild(b);else this[d]&&this[d](c,a);return this.el.appendChild(c),c},connect:function(a){a.on("add:body",this.attach,this),a.on("remove:body",this.detach,this)},disconnect:function(a){a.off("add:body",this.attach,this),a.off("remove:body",this.detach,this)},detach:function(a){var b=a.nodeType&&a||a.body&&a.body.view,c=b&&b.parentNode;return b&&c&&c.removeChild(b),this},attach:function(a){var b=a.nodeType&&a||a.body&&a.body.view;return b&&this.el.appendChild(b),this},drawMeta:function(a){this.els.fps.innerHTML=a.fps.toFixed(2),this.els.ipf.innerHTML=a.ipf},drawBody:function(a,b){var c,d,e,f=a.state.pos,g=a.state.vel,h=a.offset,j=this._interpolateTime;c=f._[0]+g._[0]*j,d=f._[1]+g._[1]*j,e=a.state.angular.pos+a.state.angular.vel*j,b.style[i]="translate("+c+"px,"+d+"px) rotate("+e+"rad) translate("+h._[0]+"px,"+h._[1]+"px)"}}}),c.renderer("pixi",function(d){if(!b)return{};var e=(2*Math.PI,{white:"0xFFFFFF",violet:"0x542437",blue:"0x53777A"}),f={font:"18px monospace",fill:"black",align:"left"},g={metaEl:null,offset:{x:0,y:0},styles:{color:!1,point:e.blue,circle:{strokeStyle:e.blue,lineWidth:1,fillStyle:e.blue,angleIndicator:e.white,fillAlpha:1,strokeAlpha:1,alpha:1},rectangle:{strokeStyle:e.violet,lineWidth:1,fillStyle:e.violet,angleIndicator:e.white,fillAlpha:1,strokeAlpha:1,alpha:1},"convex-polygon":{strokeStyle:e.violet,lineWidth:1,fillStyle:e.violet,angleIndicator:e.white,fillAlpha:1,strokeAlpha:1,alpha:1}}};return{init:function(e){var f,h,i=this;if("undefined"==typeof PIXI)throw"PIXI not present - cannot continue";d.init.call(this,e),this.options.defaults(g,!0),this.options.onChange(function(){i.options.offset=new c.vector(i.options.offset)}),this.options(e,!0),h=!this.options.styles.color||"transparent"===this.options.styles.color,this.stage=new PIXI.Stage(this.options.styles.color),this.meta={},f=this.el&&"CANVAS"===this.el.nodeName?f:null,this.renderer=new PIXI.autoDetectRenderer(this.options.width,this.options.height,{view:f,transparent:h,resolution:a.devicePixelRatio||1}),f||(this.el=this.el||b.body,this.el.appendChild(this.renderer.view)),this.options.autoResize?this.resize():this.resize(this.options.width,this.options.height)},resize:function(a,b){d.resize.call(this,a,b),this.renderer.resize(this.width,this.height)},connect:function(a){a.on("add:body",this.attach,this),a.on("remove:body",this.detach,this)},disconnect:function(a){a.off("add:body",this.attach,this),a.off("remove:body",this.detach,this)},detach:function(a){var b=a instanceof PIXI.Graphics&&a||a.body&&a.body.view;return b&&this.stage.removeChild(b),this},attach:function(a){var b=a instanceof PIXI.Graphics&&a||a.body&&a.body.view;return b&&this.stage.addChild(b),this},loadSpriteSheets:function(a,b){if(!c.util.isArray(a))throw"Spritesheets must be defined in arrays";var d=this,e=new PIXI.AssetLoader(a);return e.load(),e.on("onComplete",function(){d.assetsLoaded=!0,b()}),d},drawBody:function(a,b){var c,d,e,f=a.state.pos,g=a.state.vel,h=a.offset,i=this._interpolateTime||0;c=f._[0]+g._[0]*i,d=f._[1]+g._[1]*i,e=a.state.angular.pos+a.state.angular.vel*i,b.position.set(c,d),b.pivot.set(-h._[0],-h._[1]),b.rotation=e},render:function(a,b){d.render.call(this,a,b),this.renderer.render(this.stage)},setStyles:function(a,b){return c.util.isObject(b)?(b.fillStyle&&"transparent"!==b.fillStyle?(a.beginFill(b.fillStyle),a.fillAlpha=void 0!==b.fillAlpha?b.fillAlpha:1):(a.beginFill(),a.fillAlpha=0),a.lineStyle(b.lineWidth||0,b.strokeStyle,void 0!==b.strokeAlpha?b.strokeAlpha:1),a.alpha=void 0!==b.alpha?b.alpha:1):(b&&"transparent"!==b?a.beginFill(b):(a.beginFill(),a.fillAlpha=0),a.lineStyle(0)),a},createCircle:function(a,b,c,d){var e=new PIXI.Graphics;return this.setStyles(e,d),e.drawCircle(a,b,c),e.endFill(),e},createRect:function(a,b,c,d,e){var f=new PIXI.Graphics;return this.setStyles(f,e),f.drawRect(a,b,c,d),f.endFill(),f},createPolygon:function(a,b){var c=a[0],d=c.x,e=c.y,f=a.length,g={x:d,y:e},h=new PIXI.Graphics;this.setStyles(h,b),h.moveTo(d,e);for(var i=1;f>i;++i)c=a[i],d=c.x,e=c.y,h.lineTo(d,e);return f>2&&h.lineTo(g.x,g.y),h.endFill(),h},createLine:function(a,b,c){var d=a.x,e=a.y,f=new PIXI.Graphics;return this.setStyles(f,c),f.moveTo(d,e),d=b.x,e=b.y,f.lineTo(d,e),f.endFill(),f},createView:function(a,b,c){var d=null,e=a.aabb(),f=e.hw+Math.abs(e.x),g=(e.hh+Math.abs(e.y),a.name);if(c=c||this.stage,b=b||this.options.styles[g]||this.options.styles.circle||{},b.src)return d=PIXI.Sprite.fromImage(b.src),d.anchor.set(.5,.5),b.anchor&&(d.anchor.x=b.anchor.x,d.anchor.y=b.anchor.y),b.width&&(d.width=b.width),b.height&&(d.height=b.height),c.addChild(d),d;if("circle"===g)d=this.createCircle(0,0,a.radius,b);else if("convex-polygon"===g)d=this.createPolygon(a.vertices,b);else if("rectangle"===g)d=this.createRect(-a.width/2,-a.height/2,a.width,a.height,b);else if("compound"===g){d=new PIXI.Graphics;for(var h,i,j=0,k=a.children.length;k>j;j++)h=a.children[j],i=this.createView(h.g,b,d),i.position.set(h.pos.x,h.pos.y),i.rotation=h.angle}else d=this.createCircle(0,0,1,b);return"compound"!==g&&b.angleIndicator&&"transparent"!==b.angleIndicator&&(d.lineStyle(b.lineWidth,b.angleIndicator),d.moveTo(0,0),d.lineTo(f,0)),"compound"!==g&&(d.cacheAsBitmap=!0),c.addChild(d),d},drawMeta:function(a){this.meta.loaded?(this.meta.fps.setText("FPS: "+a.fps.toFixed(2)),this.meta.ipf.setText("IPF: "+a.ipf)):(this.meta.fps=new PIXI.Text("FPS: "+a.fps.toFixed(2),f),this.meta.fps.position.x=15,this.meta.fps.position.y=5,this.meta.ipf=new PIXI.Text("IPF: "+a.ipf,f),this.meta.ipf.position.x=15,this.meta.ipf.position.y=30,this.stage.addChild(this.meta.fps),this.stage.addChild(this.meta.ipf),this.meta.loaded=!0)},createDisplay:function(a,b){var c=null,d=null;switch(a){case"sprite":return d=PIXI.Texture.fromImage(b.texture),c=new PIXI.Sprite(d),b.anchor&&(c.anchor.x=b.anchor.x,c.anchor.y=b.anchor.y),b.container?b.container.addChild(c):this.stage.addChild(c),c;case"movieclip":if(!this.assetsLoaded)throw"No assets have been loaded. Use loadSpritesheet() first";var e=[],f=0;for(f;f Array + * - v (Number): is value to push + * - k (Number): is num elements + * - m (Number): is current mean + * - s (Number): is current s value + * + (Array): Returns a 2 element array containing the next mean, and s value + * + * Push a value to a running average calculation. + * see [http://www.johndcook.com/blog/standard_deviation] + * + * Note: variance can be calculated from the "s" value by multiplying it by `1/(k-1)` + **/ + pushRunningAvg: function( v, k, m, s ){ + + var x = v - m; + + // Mk = Mk-1+ (xk – Mk-1)/k + // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). + m += x / k; + s += x * (v - m); + return [m, s]; + }, + + /** + * Physics.statistics.pushRunningVectorAvg( v, k, m[, s] ) + * - v (Physics.vector): is vector to push + * - k (Number): is num elements + * - m (Physics.vector): is current mean + * - s (Physics.vector): is current s value + * + * Push a vector to a running vector average calculation. + * see [http://www.johndcook.com/blog/standard_deviation] + * + * Calculations are done in place. The `m` and `s` parameters are altered. + * + * Note: variance can be calculated from the "s" vector by multiplying it by `1/(k-1)` + * + * If s value is ommitted it won't be used. + **/ + pushRunningVectorAvg: function( v, k, m, s ){ + var invK = 1/k + ,x = v.get(0) - m.get(0) + ,y = v.get(1) - m.get(1) + ; + + // Mk = Mk-1+ (xk – Mk-1)/k + // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). + m.add( x * invK, y * invK ); + + if ( s ){ + x *= v.get(0) - m.get(0); + y *= v.get(1) - m.get(1); + + s.add( x, y ); + } + } + }; +})(); + + // --- // inside: src/math/transform.js @@ -3524,46 +3591,13 @@ Physics.scratchpad = (function(){ view: null }; - // Running average - // http://www.johndcook.com/blog/standard_deviation - // k is num elements - // m is current mean - // s is current std deviation - // v is value to push - function pushRunningAvg( k, m, s, v ){ - - var x = v - m; - - // Mk = Mk-1+ (xk – Mk-1)/k - // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). - m += x / k; - s += x * (v - m); - } - - // Running vector average - // http://www.johndcook.com/blog/standard_deviation - // k is num elements - // m is current mean (vector) - // s is current std deviation (vector) - // v is vector to push - function pushRunningVectorAvg( k, m, s, v ){ - var invK = 1/k - ,x = v.get(0) - m.get(0) - ,y = v.get(1) - m.get(1) - ; - - // Mk = Mk-1+ (xk – Mk-1)/k - // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). - m.add( x * invK, y * invK ); - - x *= v.get(0) - m.get(0); - y *= v.get(1) - m.get(1); + var uidGen = 1; - s.add( x, y ); + var Pi2 = Math.PI * 2; + function cycleAngle( ang ){ + return ((ang % Pi2) + Pi2) % Pi2; } - var uidGen = 1; - /** related to: Physics.util.decorator * Physics.body( name[, options] ) -> Body * - name (String): The name of the body to create @@ -3857,6 +3891,8 @@ Physics.scratchpad = (function(){ ,scratch = Physics.scratchpad() ,diff = scratch.vector() ,diff2 = scratch.vector() + ,kfac + ,stats ; dt = dt || 0; @@ -3875,11 +3911,17 @@ Physics.scratchpad = (function(){ } this._sleepMeanK++; - pushRunningVectorAvg( this._sleepMeanK, this._sleepPosMean, this._sleepPosVariance, this.state.pos ); - pushRunningAvg( this._sleepMeanK, this._sleepAngPosMean, this._sleepAngPosVariance, this.state.angular.pos ); - v = this._sleepPosVariance.norm() + Math.abs(r * this._sleepAngPosVariance); + kfac = this._sleepMeanK > 1 ? 1/(this._sleepMeanK - 1) : 0; + Physics.statistics.pushRunningVectorAvg( this.state.pos, this._sleepMeanK, this._sleepPosMean, this._sleepPosVariance ); + // we take the sin because that maps the discontinuous angle to a continuous value + // then the statistics calculations work better + stats = Physics.statistics.pushRunningAvg( Math.sin(this.state.angular.pos), this._sleepMeanK, this._sleepAngPosMean, this._sleepAngPosVariance ); + this._sleepAngPosMean = stats[0]; + this._sleepAngPosVariance = stats[1]; + v = this._sleepPosVariance.norm() + Math.abs(r * Math.asin(stats[1])); + v *= kfac; limit = this.sleepVarianceLimit || (opts && opts.sleepVarianceLimit) || 0; - + // console.log(v, limit, kfac, this._sleepPosVariance.norm(), stats[1]) if ( v <= limit ){ // check idle time limit = this.sleepTimeLimit || (opts && opts.sleepTimeLimit) || 0; @@ -5000,9 +5042,9 @@ Physics.geometry.nearestPointOnLine = function nearestPointOnLine( pt, linePt1, // is sleeping disabled? sleepDisabled: false, // speed at which bodies wake up - sleepSpeedLimit: 0.1, + sleepSpeedLimit: 0.05, // variance in position below which bodies fall asleep - sleepVarianceLimit: 2, + sleepVarianceLimit: 0.02, // time (ms) before sleepy bodies fall asleep sleepTimeLimit: 500 }; diff --git a/dist/physicsjs.min.js b/dist/physicsjs.min.js index 29adfea5..08d5e52a 100644 --- a/dist/physicsjs.min.js +++ b/dist/physicsjs.min.js @@ -1,10 +1,10 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * * Copyright (c) 2014 Jasper Palfree * Licensed MIT */ -!function(a,b){"object"==typeof exports?module.exports=b.call(a):"function"==typeof define&&define.amd?define(function(){return b.call(a)}):a.Physics=b.call(a)}("undefined"!=typeof window?window:this,function(){"use strict";var a=this,b=a.document,c=function f(){return f.world.apply(f,arguments)};c.util={},function(){c.aabb=function(a,b,c,d){var e={x:0,y:0,hw:0,hh:0};return void 0===a?e:(a&&void 0!==a.x&&(c=b.x,d=b.y,b=a.y,a=a.x),void 0===d&&void 0!==a&&void 0!==b?(e.hw=.5*a,e.hh=.5*b,c&&void 0!==c.x&&(e.x=c.x,e.y=c.y),e):(e.hw=.5*Math.abs(c-a),e.hh=.5*Math.abs(d-b),e.x=.5*(c+a),e.y=.5*(d+b),e))},c.aabb.contains=function(a,b){return b.x>a.x-a.hw&&b.xa.y-a.hh&&b.y=d&&f>=e||f>=c&&e>=f?(c=a.y-a.hh,d=b.y-b.hh,e=a.y+a.hh,f=b.y+b.hh,e>=d&&f>=e||f>=c&&e>=f):!1}}(),function(){var a=1e-4,b=100,d=function(a,b,c){var d=b.normSq()-b.dot(a),e=b.dot(a)-a.normSq();return 0>d?c.clone(b).negate():e>0?c.clone(a).negate():(c.clone(b).vsub(a),c.perp(a.cross(c)>0))},e=function(a){var b,d,e=a.length,f=a[e-2],g=a[e-3],h=c.scratchpad(),i=h.vector().clone(f.pt),j=h.vector().clone(g.pt).vsub(i);return j.equals(c.vector.zero)?h.done({a:f.a,b:f.b}):(b=-j.dot(i)/j.normSq(),d=1-b,h.done(0>=d?{a:g.a,b:g.b}:0>=b?{a:f.a,b:f.b}:{a:i.clone(f.a).mult(d).vadd(j.clone(g.a).mult(b)).values(),b:i.clone(f.b).mult(d).vadd(j.clone(g.b).mult(b)).values()}))},f=function(f,g,h,i){var j,k,l,m,n=!1,o=!1,p=!1,q=[],r=1,s=c.scratchpad(),t=s.vector().clone(g||c.vector.axis[0]),u=s.vector(),v=s.vector(),w=s.vector(),x=s.vector(),y=0;for(m=f(t),r=q.push(m),u.clone(m.pt),t.negate();++y;){if(u.swap(v),m=f(t),r=q.push(m),u.clone(m.pt),i&&i(q),u.equals(c.vector.zero)){n=!0;break}if(!o&&u.dot(t)<=0){if(h)break;o=!0}if(2===r)t=d(u,v,t);else if(o){if(t.normalize(),m=v.dot(t),Math.abs(m-u.dot(t))0,l^u.cross(j)>0)q.shift(),j.perp(!l),t.swap(j);else{if(!(l^k.cross(u)>0)){n=!0;break}q.splice(1,1),k.perp(l),t.swap(j)}if(y>b)return s.done(),{simplex:q,iterations:y,distance:0,maxIterationsReached:!0}}return s.done(),m={overlap:n,simplex:q,iterations:y},p!==!1&&(m.distance=p,m.closest=e(q)),m};c.gjk=f}(),function(){var a=function b(a,d,e){return this instanceof b?(this.v=new c.vector,this.o=new c.vector,a instanceof b?void this.clone(a):(a&&this.setTranslation(a),void this.setRotation(d||0,e))):new b(a,d)};a.prototype.setTranslation=function(a){return this.v.clone(a),this},a.prototype.setRotation=function(a,b){return this.cosA=Math.cos(a),this.sinA=Math.sin(a),b?this.o.clone(b):this.o.zero(),this},a.prototype.clone=function(b){return b?(this.setTranslation(b.v),this.cosA=b.cosA,this.sinA=b.sinA,this.o.clone(b.o),this):new a(this)},c.transform=a}(),function(a){var b=Math.sqrt,d=Math.min,e=Math.max,f=(Math.acos,Math.atan2),g=2*Math.PI,h=!!a.Float64Array,i=function j(a,b){return this instanceof j?(this._=h?new Float64Array(5):[],void(a&&(void 0!==a.x||a._&&a._.length)?this.clone(a):(this.recalc=!0,this.set(a,b)))):new j(a,b)};Object.defineProperties(i.prototype,{x:{get:function(){return+this._[0]},set:function(a){a=+a||0,this.recalc=a===this._[0],this._[0]=a}},y:{get:function(){return+this._[1]},set:function(a){a=+a||0,this.recalc=a===this._[1],this._[1]=a}}}),i.prototype.set=function(a,b){return this.recalc=!0,this._[0]=+a||0,this._[1]=+b||0,this},i.prototype.get=function(a){return this._[a]},i.prototype.vadd=function(a){return this.recalc=!0,this._[0]+=a._[0],this._[1]+=a._[1],this},i.prototype.vsub=function(a){return this.recalc=!0,this._[0]-=a._[0],this._[1]-=a._[1],this},i.prototype.add=function(a,b){return this.recalc=!0,this._[0]+=+a||0,this._[1]+=+b||0,this},i.prototype.sub=function(a,b){return this.recalc=!0,this._[0]-=a,this._[1]-=void 0===b?0:b,this},i.prototype.mult=function(a){return this.recalc||(this._[4]*=a*a,this._[3]*=a),this._[0]*=a,this._[1]*=a,this},i.prototype.dot=function(a){return this._[0]*a._[0]+this._[1]*a._[1]},i.prototype.cross=function(a){return-this._[0]*a._[1]+this._[1]*a._[0]},i.prototype.proj=function(a){return this.dot(a)/a.norm()},i.prototype.vproj=function(a){var b=this.dot(a)/a.normSq();return this.clone(a).mult(b)},i.prototype.angle=function(a){var b;if(this.equals(i.zero))return a?a.angle():0/0;for(b=a&&!a.equals(i.zero)?f(this._[1]*a._[0]-this._[0]*a._[1],this._[0]*a._[0]+this._[1]*a._[1]):f(this._[1],this._[0]);b>Math.PI;)b-=g;for(;b<-Math.PI;)b+=g;return b},i.prototype.angle2=function(a,b){for(var c=a._[0]-this._[0],d=a._[1]-this._[1],e=b._[0]-this._[0],h=b._[1]-this._[1],i=f(d*e-c*h,c*e+d*h);i>Math.PI;)i-=g;for(;i<-Math.PI;)i+=g;return i},i.prototype.norm=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[3]},i.prototype.normSq=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[4]},i.prototype.dist=function(a){var c,d;return b((c=a._[0]-this._[0])*c+(d=a._[1]-this._[1])*d)},i.prototype.distSq=function(a){var b,c;return(b=a._[0]-this._[0])*b+(c=a._[1]-this._[1])*c},i.prototype.perp=function(a){var b=this._[0];return a?(this._[0]=this._[1],this._[1]=-b):(this._[0]=-this._[1],this._[1]=b),this},i.prototype.normalize=function(){var a=this.norm();return 0===a?this:(a=1/a,this._[0]*=a,this._[1]*=a,this._[3]=1,this._[4]=1,this)},i.prototype.transform=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d,this._[1]-=e,this.set(this._[0]*c-this._[1]*b+d+a.v._[0],this._[0]*b+this._[1]*c+e+a.v._[1])},i.prototype.transformInv=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d+a.v._[0],this._[1]-=e+a.v._[1],this.set(this._[0]*c+this._[1]*b+d,-this._[0]*b+this._[1]*c+e)},i.prototype.rotate=function(a,b){var c,d,e=0,f=0;return"number"==typeof a?(c=Math.sin(a),d=Math.cos(a),b&&(e=b.x,f=b.y)):(c=a.sinA,d=a.cosA,e=a.o._[0],f=a.o._[1]),this._[0]-=e,this._[1]-=f,this.set(this._[0]*d-this._[1]*c+e,this._[0]*c+this._[1]*d+f)},i.prototype.rotateInv=function(a){return this.set((this._[0]-a.o._[0])*a.cosA+(this._[1]-a.o._[1])*a.sinA+a.o._[0],-(this._[0]-a.o._[0])*a.sinA+(this._[1]-a.o._[1])*a.cosA+a.o._[1])},i.prototype.translate=function(a){return this.vadd(a.v)},i.prototype.translateInv=function(a){return this.vsub(a.v)},i.prototype.clone=function(a){return a?a._?(this.recalc=a.recalc,a.recalc||(this._[3]=a._[3],this._[4]=a._[4]),this._[0]=a._[0],this._[1]=a._[1],this):this.set(a.x,a.y):new i(this)},i.prototype.swap=function(a){var b=this._;return this._=a._,a._=b,b=this.recalc,this.recalc=a.recalc,a.recalc=b,this},i.prototype.values=function(){return{x:this._[0],y:this._[1]}},i.prototype.zero=function(){return this._[3]=0,this._[4]=0,this._[0]=0,this._[1]=0,this},i.prototype.negate=function(a){return void 0!==a?(this._[a]=-this._[a],this):(this._[0]=-this._[0],this._[1]=-this._[1],this)},i.prototype.clamp=function(a,b){return this._[0]=d(e(this._[0],a.x),b.x),this._[1]=d(e(this._[1],a.y),b.y),this.recalc=!0,this},i.prototype.toString=function(){return"("+this._[0]+", "+this._[1]+")"},i.prototype.equals=function(a){return this._[0]===a._[0]&&this._[1]===a._[1]&&this._[2]===a._[2]},i.axis=[new i(1,0),new i(0,1)],i.zero=new i(0,0),c.vector=i}(this),function(a){var b=a.Physics;c.noConflict=function(){return a.Physics===c&&(a.Physics=b),c}}(this);var d=c.util.decorator=function(a,b){var d={},e={},f=function(a,b){var d,e;for(e in b)d=Object.getOwnPropertyDescriptor(b,e),d.get||d.set?Object.defineProperty(a,e,d):c.util.isFunction(d.value)&&(a[e]=d.value);return a},g=Object.getPrototypeOf;"function"!=typeof g&&(g="object"==typeof"test".__proto__?function(a){return a.__proto__}:function(a){return a.constructor.prototype});var h=Object.create;"function"!=typeof h&&(h=function(a){function b(){}return b.prototype=a,new b});var i=function(b,d){return"object"==typeof b?(e=f(e,b),void(e.type=a)):void("type"!==b&&c.util.isFunction(d)&&(e[b]=d))};i(b);var j=function(b,c,i,j){var k,l=e;if("string"!=typeof c)j=i,i=c;else{if(l=d[c],!l)throw'Error: "'+c+'" '+a+" not defined";l=l.prototype}if("function"==typeof i)k=d[b],k?k.prototype=f(k.prototype,i(g(k.prototype))):(k=d[b]=function(a){this.init&&this.init(a)},k.prototype=h(l),k.prototype=f(k.prototype,i(l,k.prototype))),k.prototype.type=a,k.prototype.name=b;else if(j=i||{},k=d[b],!k)throw'Error: "'+b+'" '+a+" not defined";return j?new k(j):void 0};return j.mixin=i,j};c.util.indexOf=function(a,b){for(var c=0,d=a.length;d>c;){if(d--,a[c]===b)return c;if(a[d]===b)return d;c++}return-1},c.util.clearArray=function(a){for(var b=a.length;b--;)a.pop();return a},c.util.throttle=function(a,b,c){var d,e,f=!1,g=function(){clearTimeout(d),f?(f=!1,d=setTimeout(g,b),a.apply(c,e)):d=!1};return c=c||null,function(){f=!0,e=arguments,d||g()}};var e=function(a,b){return c.util.isPlainObject(b)?c.util.extend({},a,b,e):void 0!==b?b:a};return c.util.options=function(a,b){var d,f={},g=[];return d=function(a,d){c.util.extend(b,a,d?e:null);for(var f=0,h=g.length;h>f;++f)g[f](b);return b},d.defaults=function(a,d){return c.util.extend(f,a,d?e:null),c.util.defaults(b,f,d?e:null),f},d.onChange=function(a){g.push(a)},b=b||d,d.defaults(a),d},c.util.pairHash=function(a,b){return a=0|a,b=0|b,(0|a)===(0|b)?-1:0|((0|a)>(0|b)?a<<16|65535&b:b<<16|65535&a)},c.util.bind=Function.prototype.bind?function(a,b,c){return c=Array.prototype.slice.call(arguments,1),Function.prototype.bind.apply(a,c)}:function(a,b,c){return c=Array.prototype.slice.call(arguments,2),function(){return a.apply(b,c.concat(Array.prototype.slice.call(arguments)))}},c.util.find=function(a,b){var c,d,e=a.length;for(c=0;e>c;c++)if(d=a[c],b(d,c,a))return d},c.util.filter=function(a,b){var c,d,e=a.length,f=[];for(c=0;e>c;c++)d=a[c],b(d,c,a)&&f.push(d);return f},function(){function a(a){c.util.clearArray(a),v.length-1?0:-1:a?0:-1}function g(a){var b=this.cache,c=typeof a;if("boolean"===c||null==a)b[a]=!0;else{"number"!==c&&"string"!==c&&(c="object");var d="number"===c?a:y+a,e=b[c]||(b[c]={});"object"===c?(e[d]||(e[d]=[])).push(a):e[d]=!0}}function h(a){var b=-1,c=a.length,e=a[0],f=a[c/2|0],h=a[c-1];if(e&&"object"==typeof e&&f&&"object"==typeof f&&h&&"object"==typeof h)return!1;var i=d();i["false"]=i["null"]=i["true"]=i.undefined=!1;var j=d();for(j.array=a,j.cache=i,j.push=g;++b=u&&k===c.util.indexOf,o=i||n?e():m;if(n){var p=h(o);k=f,o=p}for(;++jb;b++)d=a[b],e=i(0,++f),h[f]=h[e],h[e]=d;return h},c.util.isObject=function(a){return!(!a||!n[typeof a])},c.util.isFunction=j,c.util.isArray=Array.isArray||function(a){return a&&"object"==typeof a&&"number"==typeof a.length&&s.call(a)===p||!1};var C=RegExp("^"+String(s).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$");c.util.isPlainObject=Object.getPrototypeOf?function(a){if(!a||s.call(a)!==q)return!1;var b=a.valueOf,c=k(b)&&(c=Object.getPrototypeOf(b))&&Object.getPrototypeOf(c);return c?a===c||Object.getPrototypeOf(a)===c:l(a)}:l,c.util.uniq=function(a,b,c){return"boolean"!=typeof b&&null!=b&&(c=b,b=!1),m(a,b,c)};var D=function(a,b,c){var d,e=a,f=e;if(!e)return f;var g,h=arguments,i=0,j="number"==typeof c?2:h.length;for(j>2&&"function"==typeof h[j-1]&&(g=h[--j]);++id;){var f=d+e>>>1;c(a[f])=b.maxScratches)throw f},a.prototype={done:function(a){this._active=!1;for(var b=0;j>b;++b)this[b]=0;return h.push(this),a}},b=function k(b){if(b)return k.fn(b);var c=h.pop()||new a;return c._active=!0,c},b.maxScratches=100,b.maxIndex=20,b.fn=function(b){for(var c=[],d=0,e=b.length;e>d;d++)c.push(d);c="a"+c.join(",a");var f=new Function("fn, scratches, Scratch","return function("+c+"){ var scratch = scratches.pop() || new Scratch( scratches );scratch._active = true;return scratch.done( fn(scratch, "+c+") );};");return f(b,h,a)},b.register=function(c,f,h){var i=a.prototype,k=j++,l="_"+c+"Stack",m=h&&h.useFactory;if(c in i)throw g;a.prototype[c]=function(){var a=this[l]||(this[l]=[]),c=0|this[k];if(this[k]=c+1,!this._active)throw d;if(c>=b.maxIndex)throw e;return a[c]||(a[c]=m?f():new f)}},b.register("vector",c.vector),b.register("transform",c.transform),b}(),function(){function a(a){return a._priority_}var b=1;c.scratchpad.register("event",function(){return{}},{useFactory:!0});var d=function e(){return this instanceof e?void 0:new e};d.prototype={on:function(d,e,f,g){var h,i,j;if(this._topics=this._topics||(this._topics={}),c.util.isObject(d)){for(var k in d)this.on(k,d[k],e,f);return this}return h=this._topics[d]||(this._topics[d]=[]),i=e,c.util.isObject(f)?(e=c.util.bind(e,f),e._bindfn_=i,e._one_=i._one_,e._scope_=f):void 0===g&&(g=f),e._priority_=void 0===g?b:g,j=c.util.sortedIndex(h,e,a),h.splice(j,0,e),this},off:function(a,b,d){var e,f;if(!this._topics)return this;if(a===!0)return this._topics={},this;if(c.util.isObject(a)){for(var g in a)this.off(g,a[g]);return this}if(e=this._topics[a],!e)return this;if(b===!0)return this._topics[a]=[],this;for(var h=0,i=e.length;i>h;h++)if(f=e[h],!(f._bindfn_!==b&&f!==b||d&&f._scope_!==d)){e.splice(h,1);break}return this},emit:function(a,b){if(!this._topics)return this;var d,e,f=this._topics[a],g=f&&f.length,h=c.scratchpad();if(!g)return h.done(this);for(e=h.event(),e.topic=a,e.handler=d;g--;)d=f[g],d(b,e),d._one_&&f.splice(g,1);return h.done(this)},one:function(a,b,d){if(c.util.isObject(a)){for(var e in a)this.one(e,a[e],b,d);return this}return b._one_=!0,this.on(a,b,d),this}},c.util.pubsub=d}(),function(a){function b(){return l&&l.now?l.now()+l.timing.navigationStart:Date.now()}function d(){var c;a.requestAnimationFrame(d),j&&(c=b(),c&&k.emit("tick",c))}function e(){return j=!0,this}function f(){return j=!1,this}function g(a){return k.on("tick",a),this}function h(a){return k.off("tick",a),this}function i(){return!!j}var j=!0,k=c.util.pubsub(),l=a.performance;a.requestAnimationFrame?d():j=!1,c.util.ticker={now:b,start:e,stop:f,on:g,off:h,isActive:i}}(this),function(){var a=function(){return!0},b=c.util.indexOf,d=function(a,b){return function(c){return a(c[b])}},e=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){if(c.util.isArray(a)){if(f=e.length,f!==a.length)return!1;for(;f>g;){if(f--,-1===b(a,e[g])||-1===b(a,e[f]))return!1;g++}return!0}return b(e,a)>-1}return e===a}},f=function(a,b){var c=e(a,b);return function(a){return!c(a)}},g=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){for(f=e.length;f>g;){if(f--,b(a,e[g])>-1||b(a,e[f])>-1)return!0;g++}return!1}return b(a,e)>-1}},h=function(a,b){var c=g(a,b);return function(a){return!c(a)}},i=function(a){return a=new c.vector(a),function(b){var d=b.aabb();return c.aabb.contains(d,a)}},j=function(a){return a.next?function(b){for(var c=a;c;){if(!c(b))return!1;c=c.next}return!0}:a},k=function(a){return a.next?function(b){for(var c=a;c;){if(c(b))return!0;c=c.next}return!1}:a},l={$eq:e,$ne:f,$in:g,$nin:h,$at:i},m=function n(b,f){var g,h,i,m,o,p;if(f){if("$or"===f||"$and"===f){for(g=0,h=b.length;h>g;++g)p=n(b[g]),o=o?o.next=p:m=p;return"$or"===f?k(m):j(m)}if(g=l[f])return g(b);throw"Unknown query operation: "+f}for(g in b)i=b[g],p="$"===g[0]?n(i,g):c.util.isPlainObject(i)?d(n(i),g):e(i,g),o=o?o.next=p:m=p;return j(m||a)};c.query=m}(this),function(){var a={priority:0};c.behavior=d("behavior",{init:function(b){this.options=c.util.options(a),this.options(b)},applyTo:function(a){return this._targets=a===!0?null:c.util.uniq(a),this},getTargets:function(){return this._targets||(this._world?this._world._bodies:[])},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},connect:function(a){this.behave&&a.on("integrate:positions",this.behave,this,this.options.priority)},disconnect:function(a){this.behave&&a.off("integrate:positions",this.behave,this)},behave:null})}(),function(){function a(a,b,c,d){var e=d-b;b+=e/a,c+=e*(d-b)}function b(a,b,c,d){var e=1/a,f=d.get(0)-b.get(0),g=d.get(1)-b.get(1);b.add(f*e,g*e),f*=d.get(0)-b.get(0),g*=d.get(1)-b.get(1),c.add(f,g)}var e={hidden:!1,treatment:"dynamic",mass:1,restitution:1,cof:.8,view:null},f=1;c.body=d("body",{init:function(a){var b=this,d=c.vector;if(this.options=c.util.options(e,this),this.options.onChange(function(a){b.offset=new d(a.offset)}),this.options(a),this.state={pos:new d(this.x,this.y),vel:new d(this.vx,this.vy),acc:new d,angular:{pos:this.angle||0,vel:this.angularVelocity||0,acc:0},old:{pos:new d,vel:new d,acc:new d,angular:{pos:0,vel:0,acc:0}}},this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean=new d,this._sleepPosVariance=new d,this._sleepMeanK=0,delete this.x,delete this.y,delete this.vx,delete this.vy,delete this.angle,delete this.angularVelocity,0===this.mass)throw"Error: Bodies must have non-zero mass";this.uid=f++,this.geometry=c.geometry("point")},sleep:function(a){return a===!0?this.asleep=!0:a===!1?(this.asleep=!1,this._sleepMeanK=0,this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean.zero(),this._sleepPosVariance.zero(),this.sleepIdleTime=0):a&&!this.asleep&&this.sleepCheck(a),this.asleep},sleepCheck:function(d){var e=this._world&&this._world.options;if(!(this.sleepDisabled||e&&e.sleepDisabled)){{var f,g,h,i,j=c.scratchpad();j.vector(),j.vector()}if(d=d||0,i=this.geometry.aabb(),h=Math.max(i.hw,i.hh),this.asleep&&(g=this.state.vel.norm()+Math.abs(h*this.state.angular.vel),f=this.sleepSpeedLimit||e&&e.sleepSpeedLimit||0,g>=f))return this.sleep(!1),j.done();this._sleepMeanK++,b(this._sleepMeanK,this._sleepPosMean,this._sleepPosVariance,this.state.pos),a(this._sleepMeanK,this._sleepAngPosMean,this._sleepAngPosVariance,this.state.angular.pos),g=this._sleepPosVariance.norm()+Math.abs(h*this._sleepAngPosVariance),f=this.sleepVarianceLimit||e&&e.sleepVarianceLimit||0,f>=g?(f=this.sleepTimeLimit||e&&e.sleepTimeLimit||0,this.sleepIdleTime=(this.sleepIdleTime||0)+d,this.sleepIdleTime>f&&(this.asleep=!0)):this.sleep(!1),j.done()}},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},accelerate:function(a){return"dynamic"===this.treatment&&this.state.acc.vadd(a),this},applyForce:function(a,b){if("dynamic"!==this.treatment)return this;var d,e=c.scratchpad(),f=e.vector();return b&&this.moi&&(d=this.state,f.clone(b),this.state.angular.acc-=f.cross(a)/this.moi),this.accelerate(f.clone(a).mult(1/this.mass)),e.done(),this},getGlobalOffset:function(a){return a=a||new c.vector,a.clone(this.offset).rotate(this.state.angular.pos),a},aabb:function(){var a=this.state.angular.pos,b=c.scratchpad(),d=b.vector(),e=this.geometry.aabb(a);return this.getGlobalOffset(d),e.x+=this.state.pos._[0]+d._[0],e.y+=this.state.pos._[1]+d._[1],b.done(e)},toBodyCoords:function(a){return a.vsub(this.state.pos).rotate(-this.state.angular.pos)},toWorldCoords:function(a){return a.rotate(this.state.angular.pos).vadd(this.state.pos)},recalc:function(){return this}}),c.body.getCOM=function(a,b){var d,e,f,g=a&&a.length,h=0;if(b=b||new c.vector,!g)return b.zero();if(1===g)return b.clone(a[0].state.pos);for(b.zero(),f=0;g>f;f++)d=a[f],e=d.state.pos,b.add(e._[0]*d.mass,e._[1]*d.mass),h+=d.mass;return b.mult(1/h),b}}(),function(){c.geometry=d("geometry",{init:function(a){this.options=c.util.options(),this.options(a),this._aabb=new c.aabb},aabb:function(){return c.aabb.clone(this._aabb)},getFarthestHullPoint:function(a,b){return b=b||new c.vector,b.set(0,0)},getFarthestCorePoint:function(a,b){return b=b||new c.vector,b.set(0,0)}})}(),c.geometry.regularPolygonVertices=function(a,b){var c,d=[],e=2*Math.PI/a,f=0;for(c=0;a>c;c++)d.push({x:b*Math.cos(f),y:b*Math.sin(f)}),f+=e;return d},c.geometry.isPolygonConvex=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=b.vector(),g=!0,h=!1,i=a.length;if(!a||!i)return!1;if(3>i)return b.done(),g;d.clone(a[0]).vsub(f.clone(a[i-1]));for(var j=1;i>=j;++j){if(e.clone(a[j%i]).vsub(f.clone(a[(j-1)%i])),h===!1)h=d.cross(e);else if(h>0^d.cross(e)>0){g=!1;break}e.swap(d)}return b.done(),g},c.geometry.getPolygonMOI=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=0,h=0,i=a.length;if(2>i)return d.done(),0;if(2===i)return b=f.clone(a[1]).distSq(e.clone(a[0])),d.done(),b/12;e.clone(a[0]);for(var j=1;i>j;++j)f.clone(a[j]),b=Math.abs(f.cross(e)),g+=b*(f.normSq()+f.dot(e)+e.normSq()),h+=b,e.swap(f);return d.done(),g/(6*h)},c.geometry.isPointInPolygon=function(a,b){var d=c.scratchpad(),e=d.vector().clone(a),f=d.vector(),g=d.vector(),h=0,i=b.length;if(2>i)return h=e.equals(f.clone(b[0])),d.done(),h;if(2===i)return h=e.angle(f.clone(b[0])),h+=e.angle(f.clone(b[1])),d.done(),Math.abs(h)===Math.PI;f.clone(b[0]).vsub(e);for(var j=1;i>=j;++j)g.clone(b[j%i]).vsub(e),h+=g.angle(f),f.swap(g);return d.done(),Math.abs(h)>1e-6},c.geometry.getPolygonArea=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=0,g=a.length;if(3>g)return b.done(),0;d.clone(a[g-1]);for(var h=0;g>h;++h)e.clone(a[h]),f+=d.cross(e),d.swap(e);return b.done(),f/2},c.geometry.getPolygonCentroid=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=new c.vector,h=a.length;if(2>h)return d.done(),new c.vector(a[0]);if(2===h)return d.done(),new c.vector((a[1].x+a[0].x)/2,(a[1].y+a[0].y)/2);e.clone(a[h-1]);for(var i=0;h>i;++i)f.clone(a[i]),b=e.cross(f),e.vadd(f).mult(b),g.vadd(e),e.swap(f);return b=1/(6*c.geometry.getPolygonArea(a)),d.done(),g.mult(b)},c.geometry.nearestPointOnLine=function(a,b,d){var e,f,g=c.scratchpad(),h=g.vector().clone(a),i=g.vector().clone(b).vsub(h),j=g.vector().clone(d).vsub(h).vsub(i);return j.equals(c.vector.zero)?(g.done(),new c.vector(b)):(e=-j.dot(i)/j.normSq(),f=1-e,0>=f?(g.done(),new c.vector(d)):0>=e?(g.done(),new c.vector(b)):(h=new c.vector(d).mult(e).vadd(i.clone(b).mult(f)),g.done(),h))},function(){var a={drag:0};c.integrator=d("integrator",{init:function(b){this.options=c.util.options(a),this.options(b)},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},integrate:function(a,b){var c=this._world;return this.integrateVelocities(a,b),c&&c.emit("integrate:velocities",{bodies:a,dt:b}),this.integratePositions(a,b),c&&c.emit("integrate:positions",{bodies:a,dt:b}),this},connect:null,disconnect:null,integrateVelocities:function(){throw"The integrator.integrateVelocities() method must be overriden"},integratePositions:function(){throw"The integrator.integratePositions() method must be overriden"}})}(),function(){var e={meta:!1,metaRefresh:200,width:600,height:600,autoResize:!0};c.renderer=d("renderer",{init:function(d){var f=this,g="string"==typeof d.el?b.getElementById(d.el):d.el;this.options=c.util.options(e),this.options(d),this.el=g?g:b.body,this.container=g&&g.parentNode?g.parentNode:b.body,this.drawMeta=c.util.throttle(c.util.bind(this.drawMeta,this),this.options.metaRefresh),a.addEventListener("resize",c.util.throttle(function(){f.options.autoResize&&f.resize()}),100)},resize:function(a,b){void 0===a&&void 0===b&&(a=this.container.offsetWidth,b=this.container.offsetHeight),this.width=a||0,this.height=b||0},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},render:function(a,b){var c,d;this.beforeRender&&this.beforeRender(),this._world.emit("beforeRender",{renderer:this,bodies:a,meta:b}),this.options.meta&&this.drawMeta(b),this._interpolateTime=b.interpolateTime;for(var e=0,f=a.length;f>e;++e)c=a[e],d=c.view||(c.view=this.createView(c.geometry,c.styles)),c.hidden||this.drawBody(c,d);return this},createView:function(){throw"You must override the renderer.createView() method."},drawMeta:function(){throw"You must override the renderer.drawMeta() method."},drawBody:function(){throw"You must override the renderer.drawBody() method."}})}(),function(){var a=function e(a,b,c){for(var d,f,g=function(){return e(a,b,c)};d=a.shift();)if(f=d.apply(b,c),f&&f.then)return f.then(g)},b={timestep:6,maxIPF:4,webworker:!1,integrator:"verlet",sleepDisabled:!1,sleepSpeedLimit:.1,sleepVarianceLimit:2,sleepTimeLimit:500},d=function f(a,b){return this instanceof f?void this.init(a,b):new f(a,b)};d.prototype=c.util.extend({},c.util.pubsub.prototype,{init:function(d,e){var f=this;(c.util.isFunction(d)||c.util.isArray(d))&&(e=d,d={}),this._meta={fps:0,ipf:0},this._bodies=[],this._behaviors=[],this._integrator=null,this._renderer=null,this._paused=!1,this._warp=1,this._time=0,this.options=c.util.options(b),this.options.onChange(function(a){f.timestep(a.timestep)}),this.options(d),this.add(c.integrator(this.options.integrator)),c.util.isFunction(e)?a([e],this,[this,c]):c.util.isArray(e)&&a(e,this,[this,c])},options:null,add:function(a){var b=0,d=a&&a.length||0,e=c.util.isArray(a)?a[0]:a;if(!e)return this;do switch(e.type){case"behavior":this.addBehavior(e);break;case"integrator":this.integrator(e);break;case"renderer":this.renderer(e);break;case"body":this.addBody(e);break;default:throw'Error: failed to add item of unknown type "'+e.type+'" to world'}while(++b-1},integrator:function(a){return void 0===a?this._integrator:this._integrator===a?this:(this._integrator&&(this._integrator.setWorld(null),this.emit("remove:integrator",{integrator:this._integrator})),a&&(this._integrator=a,this._integrator.setWorld(this),this.emit("add:integrator",{integrator:this._integrator})),this)},renderer:function(a){return void 0===a?this._renderer:this._renderer===a?this:(this._renderer&&(this._renderer.setWorld(null),this.emit("remove:renderer",{renderer:this._renderer})),a&&(this._renderer=a,this._renderer.setWorld(this),this.emit("add:renderer",{renderer:this._renderer})),this)},timestep:function(a){return a?(this._dt=+a.toPrecision(4),this._maxJump=a*this.options.maxIPF,this):this._dt},wakeUpAll:function(){var a=0,b=this._bodies.length;for(a=0;b>a;a++)this._bodies[a].sleep(!1)},addBehavior:function(a){return this.has(a)?this:(a.setWorld(this),this._behaviors.push(a),this.emit("add:behavior",{behavior:a}),this)},getBehaviors:function(){return[].concat(this._behaviors)},removeBehavior:function(a){var b=this._behaviors;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:behavior",{behavior:a});break}return this},addBody:function(a){return this.has(a)?this:(a.setWorld(this),this._bodies.push(a),this.emit("add:body",{body:a}),this)},getBodies:function(){return[].concat(this._bodies)},removeBody:function(a){var b=this._bodies;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:body",{body:a});break}return this},findOne:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.find(b._bodies,d)||!1},find:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.filter(b._bodies,d)},iterate:function(a){this._integrator.integrate(this._bodies,a)},step:function(a){var b,d,e,f=this._time,g=this._warp,h=1/g,i=this._dt,j=i*h,k=this._maxJump*h,l=this._meta;if(this._paused||void 0===this._animTime)return this._animTime=a||this._animTime||c.util.ticker.now(),this._paused||this.emit("step",l),this;if(a=a||this._animTime+j,b=a-this._animTime,b>k&&(this._animTime=a-k,b=k),d=b*g,e=f+d-i,this.emit("beforeStep"),e>=f)for(;e>=f;)f+=i,this._animTime+=j,this._time=f,this.iterate(i);return l.fps=1e3/(a-this._lastTime),l.ipf=(d/i).toFixed(2),l.interpolateTime=i+e-f,this._lastTime=a,this.emit("step",l),this},warp:function(a){return void 0===a?this._warp:(this._warp=a||1,this)},render:function(){if(!this._renderer)throw"No renderer added to world";return this._renderer.render(this._bodies,this._meta),this.emit("render",{bodies:this._bodies,meta:this._meta,renderer:this._renderer}),this},pause:function(){return this._paused=!0,this.emit("pause"),this},unpause:function(){return this._paused=!1,this.emit("unpause"),this},isPaused:function(){return!!this._paused},destroy:function(){var a=this;a.pause(),this.emit("destroy"),a.off(!0),a.remove(a.getBodies()),a.remove(a.getBehaviors()),a.integrator(null),a.renderer(null)}}),c.world=d}(),c.integrator("verlet",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=b*b,e=1-this.options.drag,f=null,g=this.prevDt||b,h=.5*(d+b*g),i=0,j=a.length;j>i;++i)f=a[i],c=f.state,"static"===f.treatment||f.sleep(b)?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(c.vel.equals(c.old.vel)&&f.started()?c.vel.clone(c.pos).vsub(c.old.pos):(c.old.pos.clone(c.pos).vsub(c.vel),c.vel.mult(b)),e&&c.vel.mult(e),c.vel.vadd(c.acc.mult(h)),c.vel.mult(1/b),c.old.vel.clone(c.vel),c.acc.zero(),c.angular.vel===c.old.angular.vel&&f.started()?c.angular.vel=c.angular.pos-c.old.angular.pos:(c.old.angular.pos=c.angular.pos-c.angular.vel,c.angular.vel*=b),c.angular.vel+=c.angular.acc*h,c.angular.vel/=b,c.old.angular.vel=c.angular.vel,c.angular.acc=0,f.started(!0)) -},integratePositions:function(a,b){for(var c,d=null,e=this.prevDt||b,f=b/e,g=0,h=a.length;h>g;++g)d=a[g],c=d.state,"static"===d.treatment||d.sleep()||(c.vel.mult(b*f),c.old.pos.clone(c.pos),c.pos.vadd(c.vel),c.vel.mult(1/(b*f)),c.old.vel.clone(c.vel),c.angular.vel*=b*f,c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel,c.angular.vel/=b*f,c.old.angular.vel=c.angular.vel);this.prevDt=b}}}),c.geometry("point",function(){}),c.body("point",function(a){return{init:function(b){a.init.call(this,b),this.moi=0}}}),c}); \ No newline at end of file +!function(a,b){"object"==typeof exports?module.exports=b.call(a):"function"==typeof define&&define.amd?define(function(){return b.call(a)}):a.Physics=b.call(a)}("undefined"!=typeof window?window:this,function(){"use strict";var a=this,b=a.document,c=function f(){return f.world.apply(f,arguments)};c.util={},function(){c.aabb=function(a,b,c,d){var e={x:0,y:0,hw:0,hh:0};return void 0===a?e:(a&&void 0!==a.x&&(c=b.x,d=b.y,b=a.y,a=a.x),void 0===d&&void 0!==a&&void 0!==b?(e.hw=.5*a,e.hh=.5*b,c&&void 0!==c.x&&(e.x=c.x,e.y=c.y),e):(e.hw=.5*Math.abs(c-a),e.hh=.5*Math.abs(d-b),e.x=.5*(c+a),e.y=.5*(d+b),e))},c.aabb.contains=function(a,b){return b.x>a.x-a.hw&&b.xa.y-a.hh&&b.y=d&&f>=e||f>=c&&e>=f?(c=a.y-a.hh,d=b.y-b.hh,e=a.y+a.hh,f=b.y+b.hh,e>=d&&f>=e||f>=c&&e>=f):!1}}(),function(){var a=1e-4,b=100,d=function(a,b,c){var d=b.normSq()-b.dot(a),e=b.dot(a)-a.normSq();return 0>d?c.clone(b).negate():e>0?c.clone(a).negate():(c.clone(b).vsub(a),c.perp(a.cross(c)>0))},e=function(a){var b,d,e=a.length,f=a[e-2],g=a[e-3],h=c.scratchpad(),i=h.vector().clone(f.pt),j=h.vector().clone(g.pt).vsub(i);return j.equals(c.vector.zero)?h.done({a:f.a,b:f.b}):(b=-j.dot(i)/j.normSq(),d=1-b,h.done(0>=d?{a:g.a,b:g.b}:0>=b?{a:f.a,b:f.b}:{a:i.clone(f.a).mult(d).vadd(j.clone(g.a).mult(b)).values(),b:i.clone(f.b).mult(d).vadd(j.clone(g.b).mult(b)).values()}))},f=function(f,g,h,i){var j,k,l,m,n=!1,o=!1,p=!1,q=[],r=1,s=c.scratchpad(),t=s.vector().clone(g||c.vector.axis[0]),u=s.vector(),v=s.vector(),w=s.vector(),x=s.vector(),y=0;for(m=f(t),r=q.push(m),u.clone(m.pt),t.negate();++y;){if(u.swap(v),m=f(t),r=q.push(m),u.clone(m.pt),i&&i(q),u.equals(c.vector.zero)){n=!0;break}if(!o&&u.dot(t)<=0){if(h)break;o=!0}if(2===r)t=d(u,v,t);else if(o){if(t.normalize(),m=v.dot(t),Math.abs(m-u.dot(t))0,l^u.cross(j)>0)q.shift(),j.perp(!l),t.swap(j);else{if(!(l^k.cross(u)>0)){n=!0;break}q.splice(1,1),k.perp(l),t.swap(j)}if(y>b)return s.done(),{simplex:q,iterations:y,distance:0,maxIterationsReached:!0}}return s.done(),m={overlap:n,simplex:q,iterations:y},p!==!1&&(m.distance=p,m.closest=e(q)),m};c.gjk=f}(),function(){c.statistics={pushRunningAvg:function(a,b,c,d){var e=a-c;return c+=e/b,d+=e*(a-c),[c,d]},pushRunningVectorAvg:function(a,b,c,d){var e=1/b,f=a.get(0)-c.get(0),g=a.get(1)-c.get(1);c.add(f*e,g*e),d&&(f*=a.get(0)-c.get(0),g*=a.get(1)-c.get(1),d.add(f,g))}}}(),function(){var a=function b(a,d,e){return this instanceof b?(this.v=new c.vector,this.o=new c.vector,a instanceof b?void this.clone(a):(a&&this.setTranslation(a),void this.setRotation(d||0,e))):new b(a,d)};a.prototype.setTranslation=function(a){return this.v.clone(a),this},a.prototype.setRotation=function(a,b){return this.cosA=Math.cos(a),this.sinA=Math.sin(a),b?this.o.clone(b):this.o.zero(),this},a.prototype.clone=function(b){return b?(this.setTranslation(b.v),this.cosA=b.cosA,this.sinA=b.sinA,this.o.clone(b.o),this):new a(this)},c.transform=a}(),function(a){var b=Math.sqrt,d=Math.min,e=Math.max,f=(Math.acos,Math.atan2),g=2*Math.PI,h=!!a.Float64Array,i=function j(a,b){return this instanceof j?(this._=h?new Float64Array(5):[],void(a&&(void 0!==a.x||a._&&a._.length)?this.clone(a):(this.recalc=!0,this.set(a,b)))):new j(a,b)};Object.defineProperties(i.prototype,{x:{get:function(){return+this._[0]},set:function(a){a=+a||0,this.recalc=a===this._[0],this._[0]=a}},y:{get:function(){return+this._[1]},set:function(a){a=+a||0,this.recalc=a===this._[1],this._[1]=a}}}),i.prototype.set=function(a,b){return this.recalc=!0,this._[0]=+a||0,this._[1]=+b||0,this},i.prototype.get=function(a){return this._[a]},i.prototype.vadd=function(a){return this.recalc=!0,this._[0]+=a._[0],this._[1]+=a._[1],this},i.prototype.vsub=function(a){return this.recalc=!0,this._[0]-=a._[0],this._[1]-=a._[1],this},i.prototype.add=function(a,b){return this.recalc=!0,this._[0]+=+a||0,this._[1]+=+b||0,this},i.prototype.sub=function(a,b){return this.recalc=!0,this._[0]-=a,this._[1]-=void 0===b?0:b,this},i.prototype.mult=function(a){return this.recalc||(this._[4]*=a*a,this._[3]*=a),this._[0]*=a,this._[1]*=a,this},i.prototype.dot=function(a){return this._[0]*a._[0]+this._[1]*a._[1]},i.prototype.cross=function(a){return-this._[0]*a._[1]+this._[1]*a._[0]},i.prototype.proj=function(a){return this.dot(a)/a.norm()},i.prototype.vproj=function(a){var b=this.dot(a)/a.normSq();return this.clone(a).mult(b)},i.prototype.angle=function(a){var b;if(this.equals(i.zero))return a?a.angle():0/0;for(b=a&&!a.equals(i.zero)?f(this._[1]*a._[0]-this._[0]*a._[1],this._[0]*a._[0]+this._[1]*a._[1]):f(this._[1],this._[0]);b>Math.PI;)b-=g;for(;b<-Math.PI;)b+=g;return b},i.prototype.angle2=function(a,b){for(var c=a._[0]-this._[0],d=a._[1]-this._[1],e=b._[0]-this._[0],h=b._[1]-this._[1],i=f(d*e-c*h,c*e+d*h);i>Math.PI;)i-=g;for(;i<-Math.PI;)i+=g;return i},i.prototype.norm=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[3]},i.prototype.normSq=function(){return this.recalc&&(this.recalc=!1,this._[4]=this._[0]*this._[0]+this._[1]*this._[1],this._[3]=b(this._[4])),this._[4]},i.prototype.dist=function(a){var c,d;return b((c=a._[0]-this._[0])*c+(d=a._[1]-this._[1])*d)},i.prototype.distSq=function(a){var b,c;return(b=a._[0]-this._[0])*b+(c=a._[1]-this._[1])*c},i.prototype.perp=function(a){var b=this._[0];return a?(this._[0]=this._[1],this._[1]=-b):(this._[0]=-this._[1],this._[1]=b),this},i.prototype.normalize=function(){var a=this.norm();return 0===a?this:(a=1/a,this._[0]*=a,this._[1]*=a,this._[3]=1,this._[4]=1,this)},i.prototype.transform=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d,this._[1]-=e,this.set(this._[0]*c-this._[1]*b+d+a.v._[0],this._[0]*b+this._[1]*c+e+a.v._[1])},i.prototype.transformInv=function(a){var b=a.sinA,c=a.cosA,d=a.o._[0],e=a.o._[1];return this._[0]-=d+a.v._[0],this._[1]-=e+a.v._[1],this.set(this._[0]*c+this._[1]*b+d,-this._[0]*b+this._[1]*c+e)},i.prototype.rotate=function(a,b){var c,d,e=0,f=0;return"number"==typeof a?(c=Math.sin(a),d=Math.cos(a),b&&(e=b.x,f=b.y)):(c=a.sinA,d=a.cosA,e=a.o._[0],f=a.o._[1]),this._[0]-=e,this._[1]-=f,this.set(this._[0]*d-this._[1]*c+e,this._[0]*c+this._[1]*d+f)},i.prototype.rotateInv=function(a){return this.set((this._[0]-a.o._[0])*a.cosA+(this._[1]-a.o._[1])*a.sinA+a.o._[0],-(this._[0]-a.o._[0])*a.sinA+(this._[1]-a.o._[1])*a.cosA+a.o._[1])},i.prototype.translate=function(a){return this.vadd(a.v)},i.prototype.translateInv=function(a){return this.vsub(a.v)},i.prototype.clone=function(a){return a?a._?(this.recalc=a.recalc,a.recalc||(this._[3]=a._[3],this._[4]=a._[4]),this._[0]=a._[0],this._[1]=a._[1],this):this.set(a.x,a.y):new i(this)},i.prototype.swap=function(a){var b=this._;return this._=a._,a._=b,b=this.recalc,this.recalc=a.recalc,a.recalc=b,this},i.prototype.values=function(){return{x:this._[0],y:this._[1]}},i.prototype.zero=function(){return this._[3]=0,this._[4]=0,this._[0]=0,this._[1]=0,this},i.prototype.negate=function(a){return void 0!==a?(this._[a]=-this._[a],this):(this._[0]=-this._[0],this._[1]=-this._[1],this)},i.prototype.clamp=function(a,b){return this._[0]=d(e(this._[0],a.x),b.x),this._[1]=d(e(this._[1],a.y),b.y),this.recalc=!0,this},i.prototype.toString=function(){return"("+this._[0]+", "+this._[1]+")"},i.prototype.equals=function(a){return this._[0]===a._[0]&&this._[1]===a._[1]&&this._[2]===a._[2]},i.axis=[new i(1,0),new i(0,1)],i.zero=new i(0,0),c.vector=i}(this),function(a){var b=a.Physics;c.noConflict=function(){return a.Physics===c&&(a.Physics=b),c}}(this);var d=c.util.decorator=function(a,b){var d={},e={},f=function(a,b){var d,e;for(e in b)d=Object.getOwnPropertyDescriptor(b,e),d.get||d.set?Object.defineProperty(a,e,d):c.util.isFunction(d.value)&&(a[e]=d.value);return a},g=Object.getPrototypeOf;"function"!=typeof g&&(g="object"==typeof"test".__proto__?function(a){return a.__proto__}:function(a){return a.constructor.prototype});var h=Object.create;"function"!=typeof h&&(h=function(a){function b(){}return b.prototype=a,new b});var i=function(b,d){return"object"==typeof b?(e=f(e,b),void(e.type=a)):void("type"!==b&&c.util.isFunction(d)&&(e[b]=d))};i(b);var j=function(b,c,i,j){var k,l=e;if("string"!=typeof c)j=i,i=c;else{if(l=d[c],!l)throw'Error: "'+c+'" '+a+" not defined";l=l.prototype}if("function"==typeof i)k=d[b],k?k.prototype=f(k.prototype,i(g(k.prototype))):(k=d[b]=function(a){this.init&&this.init(a)},k.prototype=h(l),k.prototype=f(k.prototype,i(l,k.prototype))),k.prototype.type=a,k.prototype.name=b;else if(j=i||{},k=d[b],!k)throw'Error: "'+b+'" '+a+" not defined";return j?new k(j):void 0};return j.mixin=i,j};c.util.indexOf=function(a,b){for(var c=0,d=a.length;d>c;){if(d--,a[c]===b)return c;if(a[d]===b)return d;c++}return-1},c.util.clearArray=function(a){for(var b=a.length;b--;)a.pop();return a},c.util.throttle=function(a,b,c){var d,e,f=!1,g=function(){clearTimeout(d),f?(f=!1,d=setTimeout(g,b),a.apply(c,e)):d=!1};return c=c||null,function(){f=!0,e=arguments,d||g()}};var e=function(a,b){return c.util.isPlainObject(b)?c.util.extend({},a,b,e):void 0!==b?b:a};return c.util.options=function(a,b){var d,f={},g=[];return d=function(a,d){c.util.extend(b,a,d?e:null);for(var f=0,h=g.length;h>f;++f)g[f](b);return b},d.defaults=function(a,d){return c.util.extend(f,a,d?e:null),c.util.defaults(b,f,d?e:null),f},d.onChange=function(a){g.push(a)},b=b||d,d.defaults(a),d},c.util.pairHash=function(a,b){return a=0|a,b=0|b,(0|a)===(0|b)?-1:0|((0|a)>(0|b)?a<<16|65535&b:b<<16|65535&a)},c.util.bind=Function.prototype.bind?function(a,b,c){return c=Array.prototype.slice.call(arguments,1),Function.prototype.bind.apply(a,c)}:function(a,b,c){return c=Array.prototype.slice.call(arguments,2),function(){return a.apply(b,c.concat(Array.prototype.slice.call(arguments)))}},c.util.find=function(a,b){var c,d,e=a.length;for(c=0;e>c;c++)if(d=a[c],b(d,c,a))return d},c.util.filter=function(a,b){var c,d,e=a.length,f=[];for(c=0;e>c;c++)d=a[c],b(d,c,a)&&f.push(d);return f},function(){function a(a){c.util.clearArray(a),v.length-1?0:-1:a?0:-1}function g(a){var b=this.cache,c=typeof a;if("boolean"===c||null==a)b[a]=!0;else{"number"!==c&&"string"!==c&&(c="object");var d="number"===c?a:y+a,e=b[c]||(b[c]={});"object"===c?(e[d]||(e[d]=[])).push(a):e[d]=!0}}function h(a){var b=-1,c=a.length,e=a[0],f=a[c/2|0],h=a[c-1];if(e&&"object"==typeof e&&f&&"object"==typeof f&&h&&"object"==typeof h)return!1;var i=d();i["false"]=i["null"]=i["true"]=i.undefined=!1;var j=d();for(j.array=a,j.cache=i,j.push=g;++b=u&&k===c.util.indexOf,o=i||n?e():m;if(n){var p=h(o);k=f,o=p}for(;++jb;b++)d=a[b],e=i(0,++f),h[f]=h[e],h[e]=d;return h},c.util.isObject=function(a){return!(!a||!n[typeof a])},c.util.isFunction=j,c.util.isArray=Array.isArray||function(a){return a&&"object"==typeof a&&"number"==typeof a.length&&s.call(a)===p||!1};var C=RegExp("^"+String(s).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$");c.util.isPlainObject=Object.getPrototypeOf?function(a){if(!a||s.call(a)!==q)return!1;var b=a.valueOf,c=k(b)&&(c=Object.getPrototypeOf(b))&&Object.getPrototypeOf(c);return c?a===c||Object.getPrototypeOf(a)===c:l(a)}:l,c.util.uniq=function(a,b,c){return"boolean"!=typeof b&&null!=b&&(c=b,b=!1),m(a,b,c)};var D=function(a,b,c){var d,e=a,f=e;if(!e)return f;var g,h=arguments,i=0,j="number"==typeof c?2:h.length;for(j>2&&"function"==typeof h[j-1]&&(g=h[--j]);++id;){var f=d+e>>>1;c(a[f])=b.maxScratches)throw f},a.prototype={done:function(a){this._active=!1;for(var b=0;j>b;++b)this[b]=0;return h.push(this),a}},b=function k(b){if(b)return k.fn(b);var c=h.pop()||new a;return c._active=!0,c},b.maxScratches=100,b.maxIndex=20,b.fn=function(b){for(var c=[],d=0,e=b.length;e>d;d++)c.push(d);c="a"+c.join(",a");var f=new Function("fn, scratches, Scratch","return function("+c+"){ var scratch = scratches.pop() || new Scratch( scratches );scratch._active = true;return scratch.done( fn(scratch, "+c+") );};");return f(b,h,a)},b.register=function(c,f,h){var i=a.prototype,k=j++,l="_"+c+"Stack",m=h&&h.useFactory;if(c in i)throw g;a.prototype[c]=function(){var a=this[l]||(this[l]=[]),c=0|this[k];if(this[k]=c+1,!this._active)throw d;if(c>=b.maxIndex)throw e;return a[c]||(a[c]=m?f():new f)}},b.register("vector",c.vector),b.register("transform",c.transform),b}(),function(){function a(a){return a._priority_}var b=1;c.scratchpad.register("event",function(){return{}},{useFactory:!0});var d=function e(){return this instanceof e?void 0:new e};d.prototype={on:function(d,e,f,g){var h,i,j;if(this._topics=this._topics||(this._topics={}),c.util.isObject(d)){for(var k in d)this.on(k,d[k],e,f);return this}return h=this._topics[d]||(this._topics[d]=[]),i=e,c.util.isObject(f)?(e=c.util.bind(e,f),e._bindfn_=i,e._one_=i._one_,e._scope_=f):void 0===g&&(g=f),e._priority_=void 0===g?b:g,j=c.util.sortedIndex(h,e,a),h.splice(j,0,e),this},off:function(a,b,d){var e,f;if(!this._topics)return this;if(a===!0)return this._topics={},this;if(c.util.isObject(a)){for(var g in a)this.off(g,a[g]);return this}if(e=this._topics[a],!e)return this;if(b===!0)return this._topics[a]=[],this;for(var h=0,i=e.length;i>h;h++)if(f=e[h],!(f._bindfn_!==b&&f!==b||d&&f._scope_!==d)){e.splice(h,1);break}return this},emit:function(a,b){if(!this._topics)return this;var d,e,f=this._topics[a],g=f&&f.length,h=c.scratchpad();if(!g)return h.done(this);for(e=h.event(),e.topic=a,e.handler=d;g--;)d=f[g],d(b,e),d._one_&&f.splice(g,1);return h.done(this)},one:function(a,b,d){if(c.util.isObject(a)){for(var e in a)this.one(e,a[e],b,d);return this}return b._one_=!0,this.on(a,b,d),this}},c.util.pubsub=d}(),function(a){function b(){return l&&l.now?l.now()+l.timing.navigationStart:Date.now()}function d(){var c;a.requestAnimationFrame(d),j&&(c=b(),c&&k.emit("tick",c))}function e(){return j=!0,this}function f(){return j=!1,this}function g(a){return k.on("tick",a),this}function h(a){return k.off("tick",a),this}function i(){return!!j}var j=!0,k=c.util.pubsub(),l=a.performance;a.requestAnimationFrame?d():j=!1,c.util.ticker={now:b,start:e,stop:f,on:g,off:h,isActive:i}}(this),function(){var a=function(){return!0},b=c.util.indexOf,d=function(a,b){return function(c){return a(c[b])}},e=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){if(c.util.isArray(a)){if(f=e.length,f!==a.length)return!1;for(;f>g;){if(f--,-1===b(a,e[g])||-1===b(a,e[f]))return!1;g++}return!0}return b(e,a)>-1}return e===a}},f=function(a,b){var c=e(a,b);return function(a){return!c(a)}},g=function(a,d){return function(e){e=d?e[d]:e;var f,g=0;if(c.util.isArray(e)){for(f=e.length;f>g;){if(f--,b(a,e[g])>-1||b(a,e[f])>-1)return!0;g++}return!1}return b(a,e)>-1}},h=function(a,b){var c=g(a,b);return function(a){return!c(a)}},i=function(a){return a=new c.vector(a),function(b){var d=b.aabb();return c.aabb.contains(d,a)}},j=function(a){return a.next?function(b){for(var c=a;c;){if(!c(b))return!1;c=c.next}return!0}:a},k=function(a){return a.next?function(b){for(var c=a;c;){if(c(b))return!0;c=c.next}return!1}:a},l={$eq:e,$ne:f,$in:g,$nin:h,$at:i},m=function n(b,f){var g,h,i,m,o,p;if(f){if("$or"===f||"$and"===f){for(g=0,h=b.length;h>g;++g)p=n(b[g]),o=o?o.next=p:m=p;return"$or"===f?k(m):j(m)}if(g=l[f])return g(b);throw"Unknown query operation: "+f}for(g in b)i=b[g],p="$"===g[0]?n(i,g):c.util.isPlainObject(i)?d(n(i),g):e(i,g),o=o?o.next=p:m=p;return j(m||a)};c.query=m}(this),function(){var a={priority:0};c.behavior=d("behavior",{init:function(b){this.options=c.util.options(a),this.options(b)},applyTo:function(a){return this._targets=a===!0?null:c.util.uniq(a),this},getTargets:function(){return this._targets||(this._world?this._world._bodies:[])},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},connect:function(a){this.behave&&a.on("integrate:positions",this.behave,this,this.options.priority)},disconnect:function(a){this.behave&&a.off("integrate:positions",this.behave,this)},behave:null})}(),function(){{var a={hidden:!1,treatment:"dynamic",mass:1,restitution:1,cof:.8,view:null},b=1;2*Math.PI}c.body=d("body",{init:function(d){var e=this,f=c.vector;if(this.options=c.util.options(a,this),this.options.onChange(function(a){e.offset=new f(a.offset)}),this.options(d),this.state={pos:new f(this.x,this.y),vel:new f(this.vx,this.vy),acc:new f,angular:{pos:this.angle||0,vel:this.angularVelocity||0,acc:0},old:{pos:new f,vel:new f,acc:new f,angular:{pos:0,vel:0,acc:0}}},this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean=new f,this._sleepPosVariance=new f,this._sleepMeanK=0,delete this.x,delete this.y,delete this.vx,delete this.vy,delete this.angle,delete this.angularVelocity,0===this.mass)throw"Error: Bodies must have non-zero mass";this.uid=b++,this.geometry=c.geometry("point")},sleep:function(a){return a===!0?this.asleep=!0:a===!1?(this.asleep=!1,this._sleepMeanK=0,this._sleepAngPosMean=0,this._sleepAngPosVariance=0,this._sleepPosMean.zero(),this._sleepPosVariance.zero(),this.sleepIdleTime=0):a&&!this.asleep&&this.sleepCheck(a),this.asleep},sleepCheck:function(a){var b=this._world&&this._world.options;if(!(this.sleepDisabled||b&&b.sleepDisabled)){{var d,e,f,g,h,i,j=c.scratchpad();j.vector(),j.vector()}if(a=a||0,g=this.geometry.aabb(),f=Math.max(g.hw,g.hh),this.asleep&&(e=this.state.vel.norm()+Math.abs(f*this.state.angular.vel),d=this.sleepSpeedLimit||b&&b.sleepSpeedLimit||0,e>=d))return this.sleep(!1),j.done();this._sleepMeanK++,h=this._sleepMeanK>1?1/(this._sleepMeanK-1):0,c.statistics.pushRunningVectorAvg(this.state.pos,this._sleepMeanK,this._sleepPosMean,this._sleepPosVariance),i=c.statistics.pushRunningAvg(Math.sin(this.state.angular.pos),this._sleepMeanK,this._sleepAngPosMean,this._sleepAngPosVariance),this._sleepAngPosMean=i[0],this._sleepAngPosVariance=i[1],e=this._sleepPosVariance.norm()+Math.abs(f*Math.asin(i[1])),e*=h,d=this.sleepVarianceLimit||b&&b.sleepVarianceLimit||0,d>=e?(d=this.sleepTimeLimit||b&&b.sleepTimeLimit||0,this.sleepIdleTime=(this.sleepIdleTime||0)+a,this.sleepIdleTime>d&&(this.asleep=!0)):this.sleep(!1),j.done()}},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},accelerate:function(a){return"dynamic"===this.treatment&&this.state.acc.vadd(a),this},applyForce:function(a,b){if("dynamic"!==this.treatment)return this;var d,e=c.scratchpad(),f=e.vector();return b&&this.moi&&(d=this.state,f.clone(b),this.state.angular.acc-=f.cross(a)/this.moi),this.accelerate(f.clone(a).mult(1/this.mass)),e.done(),this},getGlobalOffset:function(a){return a=a||new c.vector,a.clone(this.offset).rotate(this.state.angular.pos),a},aabb:function(){var a=this.state.angular.pos,b=c.scratchpad(),d=b.vector(),e=this.geometry.aabb(a);return this.getGlobalOffset(d),e.x+=this.state.pos._[0]+d._[0],e.y+=this.state.pos._[1]+d._[1],b.done(e)},toBodyCoords:function(a){return a.vsub(this.state.pos).rotate(-this.state.angular.pos)},toWorldCoords:function(a){return a.rotate(this.state.angular.pos).vadd(this.state.pos)},recalc:function(){return this}}),c.body.getCOM=function(a,b){var d,e,f,g=a&&a.length,h=0;if(b=b||new c.vector,!g)return b.zero();if(1===g)return b.clone(a[0].state.pos);for(b.zero(),f=0;g>f;f++)d=a[f],e=d.state.pos,b.add(e._[0]*d.mass,e._[1]*d.mass),h+=d.mass;return b.mult(1/h),b}}(),function(){c.geometry=d("geometry",{init:function(a){this.options=c.util.options(),this.options(a),this._aabb=new c.aabb},aabb:function(){return c.aabb.clone(this._aabb)},getFarthestHullPoint:function(a,b){return b=b||new c.vector,b.set(0,0)},getFarthestCorePoint:function(a,b){return b=b||new c.vector,b.set(0,0)}})}(),c.geometry.regularPolygonVertices=function(a,b){var c,d=[],e=2*Math.PI/a,f=0;for(c=0;a>c;c++)d.push({x:b*Math.cos(f),y:b*Math.sin(f)}),f+=e;return d},c.geometry.isPolygonConvex=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=b.vector(),g=!0,h=!1,i=a.length;if(!a||!i)return!1;if(3>i)return b.done(),g;d.clone(a[0]).vsub(f.clone(a[i-1]));for(var j=1;i>=j;++j){if(e.clone(a[j%i]).vsub(f.clone(a[(j-1)%i])),h===!1)h=d.cross(e);else if(h>0^d.cross(e)>0){g=!1;break}e.swap(d)}return b.done(),g},c.geometry.getPolygonMOI=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=0,h=0,i=a.length;if(2>i)return d.done(),0;if(2===i)return b=f.clone(a[1]).distSq(e.clone(a[0])),d.done(),b/12;e.clone(a[0]);for(var j=1;i>j;++j)f.clone(a[j]),b=Math.abs(f.cross(e)),g+=b*(f.normSq()+f.dot(e)+e.normSq()),h+=b,e.swap(f);return d.done(),g/(6*h)},c.geometry.isPointInPolygon=function(a,b){var d=c.scratchpad(),e=d.vector().clone(a),f=d.vector(),g=d.vector(),h=0,i=b.length;if(2>i)return h=e.equals(f.clone(b[0])),d.done(),h;if(2===i)return h=e.angle(f.clone(b[0])),h+=e.angle(f.clone(b[1])),d.done(),Math.abs(h)===Math.PI;f.clone(b[0]).vsub(e);for(var j=1;i>=j;++j)g.clone(b[j%i]).vsub(e),h+=g.angle(f),f.swap(g);return d.done(),Math.abs(h)>1e-6},c.geometry.getPolygonArea=function(a){var b=c.scratchpad(),d=b.vector(),e=b.vector(),f=0,g=a.length;if(3>g)return b.done(),0;d.clone(a[g-1]);for(var h=0;g>h;++h)e.clone(a[h]),f+=d.cross(e),d.swap(e);return b.done(),f/2},c.geometry.getPolygonCentroid=function(a){var b,d=c.scratchpad(),e=d.vector(),f=d.vector(),g=new c.vector,h=a.length;if(2>h)return d.done(),new c.vector(a[0]);if(2===h)return d.done(),new c.vector((a[1].x+a[0].x)/2,(a[1].y+a[0].y)/2);e.clone(a[h-1]);for(var i=0;h>i;++i)f.clone(a[i]),b=e.cross(f),e.vadd(f).mult(b),g.vadd(e),e.swap(f);return b=1/(6*c.geometry.getPolygonArea(a)),d.done(),g.mult(b)},c.geometry.nearestPointOnLine=function(a,b,d){var e,f,g=c.scratchpad(),h=g.vector().clone(a),i=g.vector().clone(b).vsub(h),j=g.vector().clone(d).vsub(h).vsub(i);return j.equals(c.vector.zero)?(g.done(),new c.vector(b)):(e=-j.dot(i)/j.normSq(),f=1-e,0>=f?(g.done(),new c.vector(d)):0>=e?(g.done(),new c.vector(b)):(h=new c.vector(d).mult(e).vadd(i.clone(b).mult(f)),g.done(),h))},function(){var a={drag:0};c.integrator=d("integrator",{init:function(b){this.options=c.util.options(a),this.options(b)},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},integrate:function(a,b){var c=this._world;return this.integrateVelocities(a,b),c&&c.emit("integrate:velocities",{bodies:a,dt:b}),this.integratePositions(a,b),c&&c.emit("integrate:positions",{bodies:a,dt:b}),this},connect:null,disconnect:null,integrateVelocities:function(){throw"The integrator.integrateVelocities() method must be overriden"},integratePositions:function(){throw"The integrator.integratePositions() method must be overriden"}})}(),function(){var e={meta:!1,metaRefresh:200,width:600,height:600,autoResize:!0};c.renderer=d("renderer",{init:function(d){var f=this,g="string"==typeof d.el?b.getElementById(d.el):d.el;this.options=c.util.options(e),this.options(d),this.el=g?g:b.body,this.container=g&&g.parentNode?g.parentNode:b.body,this.drawMeta=c.util.throttle(c.util.bind(this.drawMeta,this),this.options.metaRefresh),a.addEventListener("resize",c.util.throttle(function(){f.options.autoResize&&f.resize()}),100)},resize:function(a,b){void 0===a&&void 0===b&&(a=this.container.offsetWidth,b=this.container.offsetHeight),this.width=a||0,this.height=b||0},setWorld:function(a){return this.disconnect&&this._world&&this.disconnect(this._world),this._world=a,this.connect&&a&&this.connect(a),this},render:function(a,b){var c,d;this.beforeRender&&this.beforeRender(),this._world.emit("beforeRender",{renderer:this,bodies:a,meta:b}),this.options.meta&&this.drawMeta(b),this._interpolateTime=b.interpolateTime;for(var e=0,f=a.length;f>e;++e)c=a[e],d=c.view||(c.view=this.createView(c.geometry,c.styles)),c.hidden||this.drawBody(c,d);return this},createView:function(){throw"You must override the renderer.createView() method."},drawMeta:function(){throw"You must override the renderer.drawMeta() method."},drawBody:function(){throw"You must override the renderer.drawBody() method."}})}(),function(){var a=function e(a,b,c){for(var d,f,g=function(){return e(a,b,c)};d=a.shift();)if(f=d.apply(b,c),f&&f.then)return f.then(g)},b={timestep:6,maxIPF:4,webworker:!1,integrator:"verlet",sleepDisabled:!1,sleepSpeedLimit:.05,sleepVarianceLimit:.02,sleepTimeLimit:500},d=function f(a,b){return this instanceof f?void this.init(a,b):new f(a,b)};d.prototype=c.util.extend({},c.util.pubsub.prototype,{init:function(d,e){var f=this;(c.util.isFunction(d)||c.util.isArray(d))&&(e=d,d={}),this._meta={fps:0,ipf:0},this._bodies=[],this._behaviors=[],this._integrator=null,this._renderer=null,this._paused=!1,this._warp=1,this._time=0,this.options=c.util.options(b),this.options.onChange(function(a){f.timestep(a.timestep)}),this.options(d),this.add(c.integrator(this.options.integrator)),c.util.isFunction(e)?a([e],this,[this,c]):c.util.isArray(e)&&a(e,this,[this,c])},options:null,add:function(a){var b=0,d=a&&a.length||0,e=c.util.isArray(a)?a[0]:a;if(!e)return this;do switch(e.type){case"behavior":this.addBehavior(e);break;case"integrator":this.integrator(e);break;case"renderer":this.renderer(e);break;case"body":this.addBody(e);break;default:throw'Error: failed to add item of unknown type "'+e.type+'" to world'}while(++b-1},integrator:function(a){return void 0===a?this._integrator:this._integrator===a?this:(this._integrator&&(this._integrator.setWorld(null),this.emit("remove:integrator",{integrator:this._integrator})),a&&(this._integrator=a,this._integrator.setWorld(this),this.emit("add:integrator",{integrator:this._integrator})),this)},renderer:function(a){return void 0===a?this._renderer:this._renderer===a?this:(this._renderer&&(this._renderer.setWorld(null),this.emit("remove:renderer",{renderer:this._renderer})),a&&(this._renderer=a,this._renderer.setWorld(this),this.emit("add:renderer",{renderer:this._renderer})),this)},timestep:function(a){return a?(this._dt=+a.toPrecision(4),this._maxJump=a*this.options.maxIPF,this):this._dt},wakeUpAll:function(){var a=0,b=this._bodies.length;for(a=0;b>a;a++)this._bodies[a].sleep(!1)},addBehavior:function(a){return this.has(a)?this:(a.setWorld(this),this._behaviors.push(a),this.emit("add:behavior",{behavior:a}),this)},getBehaviors:function(){return[].concat(this._behaviors)},removeBehavior:function(a){var b=this._behaviors;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:behavior",{behavior:a});break}return this},addBody:function(a){return this.has(a)?this:(a.setWorld(this),this._bodies.push(a),this.emit("add:body",{body:a}),this)},getBodies:function(){return[].concat(this._bodies)},removeBody:function(a){var b=this._bodies;if(a)for(var c=0,d=b.length;d>c;++c)if(a===b[c]){b.splice(c,1),a.setWorld(null),this.emit("remove:body",{body:a});break}return this},findOne:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.find(b._bodies,d)||!1},find:function(a){var b=this,d="function"==typeof a?a:c.query(a);return c.util.filter(b._bodies,d)},iterate:function(a){this._integrator.integrate(this._bodies,a)},step:function(a){var b,d,e,f=this._time,g=this._warp,h=1/g,i=this._dt,j=i*h,k=this._maxJump*h,l=this._meta;if(this._paused||void 0===this._animTime)return this._animTime=a||this._animTime||c.util.ticker.now(),this._paused||this.emit("step",l),this;if(a=a||this._animTime+j,b=a-this._animTime,b>k&&(this._animTime=a-k,b=k),d=b*g,e=f+d-i,this.emit("beforeStep"),e>=f)for(;e>=f;)f+=i,this._animTime+=j,this._time=f,this.iterate(i);return l.fps=1e3/(a-this._lastTime),l.ipf=(d/i).toFixed(2),l.interpolateTime=i+e-f,this._lastTime=a,this.emit("step",l),this},warp:function(a){return void 0===a?this._warp:(this._warp=a||1,this)},render:function(){if(!this._renderer)throw"No renderer added to world";return this._renderer.render(this._bodies,this._meta),this.emit("render",{bodies:this._bodies,meta:this._meta,renderer:this._renderer}),this},pause:function(){return this._paused=!0,this.emit("pause"),this},unpause:function(){return this._paused=!1,this.emit("unpause"),this},isPaused:function(){return!!this._paused},destroy:function(){var a=this;a.pause(),this.emit("destroy"),a.off(!0),a.remove(a.getBodies()),a.remove(a.getBehaviors()),a.integrator(null),a.renderer(null) +}}),c.world=d}(),c.integrator("verlet",function(a){return c.body.mixin({started:function(a){return void 0!==a&&(this._started=!0),!!this._started}}),{init:function(b){a.init.call(this,b)},integrateVelocities:function(a,b){for(var c,d=b*b,e=1-this.options.drag,f=null,g=this.prevDt||b,h=.5*(d+b*g),i=0,j=a.length;j>i;++i)f=a[i],c=f.state,"static"===f.treatment||f.sleep(b)?(c.vel.zero(),c.acc.zero(),c.angular.vel=0,c.angular.acc=0):(c.vel.equals(c.old.vel)&&f.started()?c.vel.clone(c.pos).vsub(c.old.pos):(c.old.pos.clone(c.pos).vsub(c.vel),c.vel.mult(b)),e&&c.vel.mult(e),c.vel.vadd(c.acc.mult(h)),c.vel.mult(1/b),c.old.vel.clone(c.vel),c.acc.zero(),c.angular.vel===c.old.angular.vel&&f.started()?c.angular.vel=c.angular.pos-c.old.angular.pos:(c.old.angular.pos=c.angular.pos-c.angular.vel,c.angular.vel*=b),c.angular.vel+=c.angular.acc*h,c.angular.vel/=b,c.old.angular.vel=c.angular.vel,c.angular.acc=0,f.started(!0))},integratePositions:function(a,b){for(var c,d=null,e=this.prevDt||b,f=b/e,g=0,h=a.length;h>g;++g)d=a[g],c=d.state,"static"===d.treatment||d.sleep()||(c.vel.mult(b*f),c.old.pos.clone(c.pos),c.pos.vadd(c.vel),c.vel.mult(1/(b*f)),c.old.vel.clone(c.vel),c.angular.vel*=b*f,c.old.angular.pos=c.angular.pos,c.angular.pos+=c.angular.vel,c.angular.vel/=b*f,c.old.angular.vel=c.angular.vel);this.prevDt=b}}}),c.geometry("point",function(){}),c.body("point",function(a){return{init:function(b){a.init.call(this,b),this.moi=0}}}),c}); \ No newline at end of file diff --git a/dist/renderers/canvas.js b/dist/renderers/canvas.js index 86e8c829..d2143702 100644 --- a/dist/renderers/canvas.js +++ b/dist/renderers/canvas.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/renderers/debug.js b/dist/renderers/debug.js index e469381d..e0b49de6 100644 --- a/dist/renderers/debug.js +++ b/dist/renderers/debug.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * @@ -157,7 +157,6 @@ world.on('sweep-prune:intervals', this.storeIntervals, this ); world.on('collisions:detected', this.storeCollisions, this ); - world.on('render', this.reset, this); this.updateGui(); }, @@ -167,7 +166,7 @@ world.off('sweep-prune:intervals', this.storeIntervals, this ); world.off('collisions:detected', this.storeCollisions, this ); - world.off('render', this.reset, this); + }, storeIntervals: function( intervals ){ @@ -277,7 +276,7 @@ } } ,get sleepSpeedLimit(){ - return self._world ? self._world.options.sleepSpeedLimit : 0.01; + return self._world ? self._world.options.sleepSpeedLimit : 0.005; } ,set sleepSpeedLimit( t ){ if ( self._world ){ @@ -285,7 +284,7 @@ } } ,get sleepVarianceLimit(){ - return self._world ? self._world.options.sleepVarianceLimit : 2; + return self._world ? self._world.options.sleepVarianceLimit : 0.2; } ,set sleepVarianceLimit( t ){ if ( self._world ){ @@ -322,7 +321,7 @@ f.add( getset, 'sleepDisabled'); f.add( getset, 'sleepTimeLimit', 1, 10000).step( 10 ); f.add( getset, 'sleepSpeedLimit', 0.001, 1); - f.add( getset, 'sleepVarianceLimit', 0.01, 100); + f.add( getset, 'sleepVarianceLimit', 0.01, 1); f.add( { pause: pauseWorld }, 'pause'); f.open(); diff --git a/dist/renderers/dom.js b/dist/renderers/dom.js index 13863a2c..12d36033 100644 --- a/dist/renderers/dom.js +++ b/dist/renderers/dom.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * diff --git a/dist/renderers/pixi-renderer.js b/dist/renderers/pixi-renderer.js index 1c2d7167..f795a44a 100644 --- a/dist/renderers/pixi-renderer.js +++ b/dist/renderers/pixi-renderer.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * @@ -45,7 +45,9 @@ * strokeStyle: '0xE8900C', * lineWidth: 3, * fillStyle: '0xD5DE4C', - * angleIndicator: '0xE8900C' + * angleIndicator: '0xE8900C', + * strokeAlpha: 1, + * fillAlpha: 1 * }, * * 'convex-polygon' : { @@ -127,6 +129,7 @@ fillStyle: colors.blue, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 }, @@ -136,6 +139,7 @@ fillStyle: colors.violet, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 }, @@ -145,6 +149,7 @@ fillStyle: colors.violet, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 } } @@ -338,14 +343,14 @@ if ( styles.fillStyle && styles.fillStyle !== 'transparent' ){ graphics.beginFill( styles.fillStyle ); - graphics.fillAlpha = styles.fillAlpha || 1; + graphics.fillAlpha = styles.fillAlpha !== undefined ? styles.fillAlpha : 1; } else { graphics.beginFill(); graphics.fillAlpha = 0; } - graphics.lineStyle( styles.lineWidth || 0, styles.strokeStyle ); - graphics.alpha = styles.alpha || 1; + graphics.lineStyle( styles.lineWidth || 0, styles.strokeStyle, styles.strokeAlpha !== undefined ? styles.strokeAlpha : 1 ); + graphics.alpha = styles.alpha !== undefined ? styles.alpha : 1; } else { @@ -534,6 +539,9 @@ view.lineStyle( styles.lineWidth, styles.angleIndicator ); view.moveTo( 0, 0 ); view.lineTo( hw, 0 ); + } + + if ( name !== 'compound' ){ view.cacheAsBitmap = true; } diff --git a/docs/debug.json b/docs/debug.json index c7d8821c..26d1132a 100644 --- a/docs/debug.json +++ b/docs/debug.json @@ -34,6 +34,7 @@ "src/intro.js", "src/math/aabb.js", "src/math/gjk.js", + "src/math/statistics.js", "src/math/transform.js", "src/math/vector.js", "src/outro.js", @@ -216,7 +217,7 @@ "internal": true, "description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", "short_description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", - "line": 369, + "line": 366, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -253,7 +254,7 @@ "internal": true, "description": "Event callback to check all pairs of objects in the list for collisions", "short_description": "Event callback to check all pairs of objects in the list for collisions", - "line": 431, + "line": 428, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -297,7 +298,7 @@ "internal": true, "description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", "short_description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", - "line": 369, + "line": 366, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -334,7 +335,7 @@ "internal": true, "description": "Event callback to check all pairs of objects in the list for collisions", "short_description": "Event callback to check all pairs of objects in the list for collisions", - "line": 431, + "line": 428, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -450,7 +451,7 @@ "internal": true, "description": "Collide two bodies by modifying their positions and velocities to conserve momentum", "short_description": "Collide two bodies by modifying their positions and velocities to conserve momentum", - "line": 66, + "line": 88, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -487,7 +488,7 @@ "internal": true, "description": "Event callback to respond to collision data.", "short_description": "Event callback to respond to collision data.", - "line": 255, + "line": 281, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -601,7 +602,7 @@ "internal": true, "description": "Collide two bodies by modifying their positions and velocities to conserve momentum", "short_description": "Collide two bodies by modifying their positions and velocities to conserve momentum", - "line": 66, + "line": 88, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -638,7 +639,7 @@ "internal": true, "description": "Event callback to respond to collision data.", "short_description": "Event callback to respond to collision data.", - "line": 255, + "line": 281, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -3270,7 +3271,7 @@ "internal": true, "description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", "short_description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", - "line": 369, + "line": 366, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -3307,7 +3308,7 @@ "internal": true, "description": "Event callback to check all pairs of objects in the list for collisions", "short_description": "Event callback to check all pairs of objects in the list for collisions", - "line": 431, + "line": 428, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -3430,7 +3431,7 @@ "internal": true, "description": "Collide two bodies by modifying their positions and velocities to conserve momentum", "short_description": "Collide two bodies by modifying their positions and velocities to conserve momentum", - "line": 66, + "line": 88, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -3467,7 +3468,7 @@ "internal": true, "description": "Event callback to respond to collision data.", "short_description": "Event callback to respond to collision data.", - "line": 255, + "line": 281, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -4884,7 +4885,7 @@ "internal": true, "description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", "short_description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", - "line": 369, + "line": 366, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -4921,7 +4922,7 @@ "internal": true, "description": "Event callback to check all pairs of objects in the list for collisions", "short_description": "Event callback to check all pairs of objects in the list for collisions", - "line": 431, + "line": 428, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -5044,7 +5045,7 @@ "internal": true, "description": "Collide two bodies by modifying their positions and velocities to conserve momentum", "short_description": "Collide two bodies by modifying their positions and velocities to conserve momentum", - "line": 66, + "line": 88, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -5081,7 +5082,7 @@ "internal": true, "description": "Event callback to respond to collision data.", "short_description": "Event callback to respond to collision data.", - "line": 255, + "line": 281, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -6420,7 +6421,7 @@ "related_to": "Physics.util.decorator", "description": "Factory function for creating Bodies.\n\nVisit [the PhysicsJS wiki on Bodies](https://github.com/wellcaffeinated/PhysicsJS/wiki/Bodies)\nfor usage documentation.", "short_description": "Factory function for creating Bodies.\n", - "line": 91, + "line": 58, "aliases": [], "children": [ { @@ -6429,7 +6430,7 @@ "belongs_to": "Physics.body", "description": "The base class for bodies created by [[Physics.body]] factory function.", "short_description": "The base class for bodies created by [[Physics.body]] factory function.", - "line": 98, + "line": 65, "aliases": [ "PointBody" ], @@ -6456,7 +6457,7 @@ "related_to": "Physics.aabb", "description": "Get the Axis aligned bounding box for the body in its current position and rotation", "short_description": "Get the Axis aligned bounding box for the body in its current position and rotation", - "line": 483, + "line": 458, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6497,7 +6498,7 @@ ], "description": "Accelerate the body by adding supplied vector to its current acceleration", "short_description": "Accelerate the body by adding supplied vector to its current acceleration", - "line": 420, + "line": 395, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6553,7 +6554,7 @@ ], "description": "Apply a force at center of mass, or at point `p` relative to the center of mass", "short_description": "Apply a force at center of mass, or at point `p` relative to the center of mass", - "line": 436, + "line": 411, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6576,7 +6577,7 @@ ], "description": "The coefficient of friction of the body.\n\nIt's how much \"slide\" it has during collisions.\n\nA `cof` of `0` will really slidy.\n\nA `cof` of `1` has no slide.\n\nThis is a very simplistic implementation at the moment.\nWhat would be better is to have both static and kinetic\nfriction. But that's not done yet.", "short_description": "The coefficient of friction of the body.\n", - "line": 251, + "line": 218, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6591,7 +6592,7 @@ "related_to": "Physics.geometry", "description": "The geometry for this body.\n\nBy default it is a `point` geometry which gets overridden.", "short_description": "The geometry for this body.\n", - "line": 204, + "line": 171, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6641,7 +6642,7 @@ "related_to": "Body#offset", "description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", "short_description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", - "line": 470, + "line": 445, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6664,7 +6665,7 @@ ], "description": "Determines whether the body should be hidden by the renderer.", "short_description": "Determines whether the body should be hidden by the renderer.", - "line": 270, + "line": 237, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6701,7 +6702,7 @@ "internal": true, "description": "Initialization. Internal use.", "short_description": "Initialization. Internal use.", - "line": 105, + "line": 72, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6724,7 +6725,7 @@ ], "description": "The mass.", "short_description": "The mass.", - "line": 211, + "line": 178, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6738,7 +6739,7 @@ "type": "namespace", "description": "The vector offsetting the body's shape from its center of mass.", "short_description": "The vector offsetting the body's shape from its center of mass.", - "line": 217, + "line": 184, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6787,7 +6788,7 @@ "related_to": "Physics.util.options", "description": "Set options on this instance.\n\nAccess options directly from the options object.\n\nExample:\n\n```javascript\nthis.options.someOption;\n```", "short_description": "Set options on this instance.\n", - "line": 126, + "line": 93, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6811,7 +6812,7 @@ ], "description": "Recalculate properties.\n\nIntended to be overridden by subclasses. Call when body physical properties are changed.", "short_description": "Recalculate properties.\n", - "line": 528, + "line": 503, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6834,7 +6835,7 @@ ], "description": "The restitution.\n\nThis is the \"bounciness\" of the body.\nIt's a number between `0` and `1`.\n\nA restitution of 1 is the bounciest.\n\nA restitution of 0 is not bouncy.\n\nWhen colliding the restitutions of bodies are\nmultiplied together to get the restitution between two\nbodies.", "short_description": "The restitution.\n", - "line": 235, + "line": 202, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6875,7 +6876,7 @@ ], "description": "Set which world to apply to.\n\nUsually this is called internally. Shouldn't be a need to call this yourself usually.", "short_description": "Set which world to apply to.\n", - "line": 399, + "line": 374, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6924,7 +6925,7 @@ ], "description": "Get and/or set whether the body is asleep.\n\nIf called with a time (in ms), the time will be added to the idle time and sleep conditions will be checked.", "short_description": "Get and/or set whether the body is asleep.\n", - "line": 304, + "line": 271, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6961,7 +6962,7 @@ ], "description": "Check if the body should be sleeping.\n\nCall with no arguments if some event could possibly wake up the body. This will force the body to recheck.", "short_description": "Check if the body should be sleeping.\n", - "line": 336, + "line": 303, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6975,7 +6976,7 @@ "type": "namespace", "description": "The physical state container.\n\n- ``this.state.pos`` ([[Physics.vector]]) The position vector.\n- ``this.state.vel`` ([[Physics.vector]]) The velocity vector.\n- ``this.state.acc`` ([[Physics.vector]]) The acceleration vector.\n- ``this.state.angular.pos`` ([[Number]]) The angular position (in radians, positive is clockwise starting along the x axis)\n- ``this.state.angular.vel`` ([[Number]]) The angular velocity\n- ``this.state.angular.acc`` ([[Number]]) The angular acceleration\n\nProperties from the previous timestep are stored in:\n```javascript\nthis.state.old; // .pos, .vel, ...\n```", "short_description": "The physical state container.\n", - "line": 150, + "line": 117, "aliases": [], "children": [], "file": "src/core/body.js", @@ -6990,7 +6991,7 @@ "related_to": "Physics.renderer", "description": "The styles the renderer should use for creating the view.\n\nThe styles depend on the renderer. See [[Renderer#createView]] for style options.", "short_description": "The styles the renderer should use for creating the view.\n", - "line": 293, + "line": 260, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7038,7 +7039,7 @@ ], "description": "Transform a vector into coordinates relative to this body.", "short_description": "Transform a vector into coordinates relative to this body.", - "line": 506, + "line": 481, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7086,7 +7087,7 @@ ], "description": "Transform a vector from body coordinates into world coordinates.", "short_description": "Transform a vector from body coordinates into world coordinates.", - "line": 517, + "line": 492, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7109,7 +7110,7 @@ ], "description": "How the body is treated by the simulation.\n\nThe body can be `dynamic`, `kinematic` or `static` as\ndescribed by the [analogous box2d docs](http://www.box2d.org/manual.html#_Toc258082973).\n\n* _dynamic_ bodies are treated \"normally\". They are integrated, and collide, and all that.\n* _kinematic_ bodies are bodies that move at a specified velocity. Other bodies collide with them, but they don't bounce off of other bodies.\n* _static_ bodies just stand still. They are like obstacles.", "short_description": "How the body is treated by the simulation.\n", - "line": 264, + "line": 231, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7132,7 +7133,7 @@ ], "description": "The unique id for the body", "short_description": "The unique id for the body", - "line": 195, + "line": 162, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7156,7 +7157,7 @@ "related_to": "Physics.renderer", "description": "Storage for use by the renderer.\n\nThe type of renderer will put different things in the view property.\nBasically, this is how the body \"looks\". It could be a HTMLElement, or\nan Image, etc...\n\nIf your body changes appearance (shape), you should modify this somehow\notherwise the renderer will keep using this same view. If you're letting\nthe renderer create the view for you, just set this to `undefined` if the\nbody gets modified in shape during the simulation.", "short_description": "Storage for use by the renderer.\n", - "line": 285, + "line": 252, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7219,7 +7220,7 @@ ], "description": "Get center of mass position from list of bodies.", "short_description": "Get center of mass position from list of bodies.", - "line": 542, + "line": 517, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7461,7 +7462,7 @@ "belongs_to": "Physics.body", "description": "The base class for bodies created by [[Physics.body]] factory function.", "short_description": "The base class for bodies created by [[Physics.body]] factory function.", - "line": 98, + "line": 65, "aliases": [ "PointBody" ], @@ -7488,7 +7489,7 @@ "related_to": "Physics.aabb", "description": "Get the Axis aligned bounding box for the body in its current position and rotation", "short_description": "Get the Axis aligned bounding box for the body in its current position and rotation", - "line": 483, + "line": 458, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7529,7 +7530,7 @@ ], "description": "Accelerate the body by adding supplied vector to its current acceleration", "short_description": "Accelerate the body by adding supplied vector to its current acceleration", - "line": 420, + "line": 395, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7585,7 +7586,7 @@ ], "description": "Apply a force at center of mass, or at point `p` relative to the center of mass", "short_description": "Apply a force at center of mass, or at point `p` relative to the center of mass", - "line": 436, + "line": 411, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7608,7 +7609,7 @@ ], "description": "The coefficient of friction of the body.\n\nIt's how much \"slide\" it has during collisions.\n\nA `cof` of `0` will really slidy.\n\nA `cof` of `1` has no slide.\n\nThis is a very simplistic implementation at the moment.\nWhat would be better is to have both static and kinetic\nfriction. But that's not done yet.", "short_description": "The coefficient of friction of the body.\n", - "line": 251, + "line": 218, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7623,7 +7624,7 @@ "related_to": "Physics.geometry", "description": "The geometry for this body.\n\nBy default it is a `point` geometry which gets overridden.", "short_description": "The geometry for this body.\n", - "line": 204, + "line": 171, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7673,7 +7674,7 @@ "related_to": "Body#offset", "description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", "short_description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", - "line": 470, + "line": 445, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7696,7 +7697,7 @@ ], "description": "Determines whether the body should be hidden by the renderer.", "short_description": "Determines whether the body should be hidden by the renderer.", - "line": 270, + "line": 237, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7733,7 +7734,7 @@ "internal": true, "description": "Initialization. Internal use.", "short_description": "Initialization. Internal use.", - "line": 105, + "line": 72, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7756,7 +7757,7 @@ ], "description": "The mass.", "short_description": "The mass.", - "line": 211, + "line": 178, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7770,7 +7771,7 @@ "type": "namespace", "description": "The vector offsetting the body's shape from its center of mass.", "short_description": "The vector offsetting the body's shape from its center of mass.", - "line": 217, + "line": 184, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7819,7 +7820,7 @@ "related_to": "Physics.util.options", "description": "Set options on this instance.\n\nAccess options directly from the options object.\n\nExample:\n\n```javascript\nthis.options.someOption;\n```", "short_description": "Set options on this instance.\n", - "line": 126, + "line": 93, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7843,7 +7844,7 @@ ], "description": "Recalculate properties.\n\nIntended to be overridden by subclasses. Call when body physical properties are changed.", "short_description": "Recalculate properties.\n", - "line": 528, + "line": 503, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7866,7 +7867,7 @@ ], "description": "The restitution.\n\nThis is the \"bounciness\" of the body.\nIt's a number between `0` and `1`.\n\nA restitution of 1 is the bounciest.\n\nA restitution of 0 is not bouncy.\n\nWhen colliding the restitutions of bodies are\nmultiplied together to get the restitution between two\nbodies.", "short_description": "The restitution.\n", - "line": 235, + "line": 202, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7907,7 +7908,7 @@ ], "description": "Set which world to apply to.\n\nUsually this is called internally. Shouldn't be a need to call this yourself usually.", "short_description": "Set which world to apply to.\n", - "line": 399, + "line": 374, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7956,7 +7957,7 @@ ], "description": "Get and/or set whether the body is asleep.\n\nIf called with a time (in ms), the time will be added to the idle time and sleep conditions will be checked.", "short_description": "Get and/or set whether the body is asleep.\n", - "line": 304, + "line": 271, "aliases": [], "children": [], "file": "src/core/body.js", @@ -7993,7 +7994,7 @@ ], "description": "Check if the body should be sleeping.\n\nCall with no arguments if some event could possibly wake up the body. This will force the body to recheck.", "short_description": "Check if the body should be sleeping.\n", - "line": 336, + "line": 303, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8007,7 +8008,7 @@ "type": "namespace", "description": "The physical state container.\n\n- ``this.state.pos`` ([[Physics.vector]]) The position vector.\n- ``this.state.vel`` ([[Physics.vector]]) The velocity vector.\n- ``this.state.acc`` ([[Physics.vector]]) The acceleration vector.\n- ``this.state.angular.pos`` ([[Number]]) The angular position (in radians, positive is clockwise starting along the x axis)\n- ``this.state.angular.vel`` ([[Number]]) The angular velocity\n- ``this.state.angular.acc`` ([[Number]]) The angular acceleration\n\nProperties from the previous timestep are stored in:\n```javascript\nthis.state.old; // .pos, .vel, ...\n```", "short_description": "The physical state container.\n", - "line": 150, + "line": 117, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8022,7 +8023,7 @@ "related_to": "Physics.renderer", "description": "The styles the renderer should use for creating the view.\n\nThe styles depend on the renderer. See [[Renderer#createView]] for style options.", "short_description": "The styles the renderer should use for creating the view.\n", - "line": 293, + "line": 260, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8070,7 +8071,7 @@ ], "description": "Transform a vector into coordinates relative to this body.", "short_description": "Transform a vector into coordinates relative to this body.", - "line": 506, + "line": 481, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8118,7 +8119,7 @@ ], "description": "Transform a vector from body coordinates into world coordinates.", "short_description": "Transform a vector from body coordinates into world coordinates.", - "line": 517, + "line": 492, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8141,7 +8142,7 @@ ], "description": "How the body is treated by the simulation.\n\nThe body can be `dynamic`, `kinematic` or `static` as\ndescribed by the [analogous box2d docs](http://www.box2d.org/manual.html#_Toc258082973).\n\n* _dynamic_ bodies are treated \"normally\". They are integrated, and collide, and all that.\n* _kinematic_ bodies are bodies that move at a specified velocity. Other bodies collide with them, but they don't bounce off of other bodies.\n* _static_ bodies just stand still. They are like obstacles.", "short_description": "How the body is treated by the simulation.\n", - "line": 264, + "line": 231, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8164,7 +8165,7 @@ ], "description": "The unique id for the body", "short_description": "The unique id for the body", - "line": 195, + "line": 162, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8188,7 +8189,7 @@ "related_to": "Physics.renderer", "description": "Storage for use by the renderer.\n\nThe type of renderer will put different things in the view property.\nBasically, this is how the body \"looks\". It could be a HTMLElement, or\nan Image, etc...\n\nIf your body changes appearance (shape), you should modify this somehow\notherwise the renderer will keep using this same view. If you're letting\nthe renderer create the view for you, just set this to `undefined` if the\nbody gets modified in shape during the simulation.", "short_description": "Storage for use by the renderer.\n", - "line": 285, + "line": 252, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8251,7 +8252,7 @@ ], "description": "Get center of mass position from list of bodies.", "short_description": "Get center of mass position from list of bodies.", - "line": 542, + "line": 517, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8508,7 +8509,7 @@ "internal": true, "description": "Initialization. Internal use.", "short_description": "Initialization. Internal use.", - "line": 105, + "line": 72, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8557,7 +8558,7 @@ "related_to": "Physics.util.options", "description": "Set options on this instance.\n\nAccess options directly from the options object.\n\nExample:\n\n```javascript\nthis.options.someOption;\n```", "short_description": "Set options on this instance.\n", - "line": 126, + "line": 93, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8571,7 +8572,7 @@ "type": "namespace", "description": "The physical state container.\n\n- ``this.state.pos`` ([[Physics.vector]]) The position vector.\n- ``this.state.vel`` ([[Physics.vector]]) The velocity vector.\n- ``this.state.acc`` ([[Physics.vector]]) The acceleration vector.\n- ``this.state.angular.pos`` ([[Number]]) The angular position (in radians, positive is clockwise starting along the x axis)\n- ``this.state.angular.vel`` ([[Number]]) The angular velocity\n- ``this.state.angular.acc`` ([[Number]]) The angular acceleration\n\nProperties from the previous timestep are stored in:\n```javascript\nthis.state.old; // .pos, .vel, ...\n```", "short_description": "The physical state container.\n", - "line": 150, + "line": 117, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8594,7 +8595,7 @@ ], "description": "The unique id for the body", "short_description": "The unique id for the body", - "line": 195, + "line": 162, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8609,7 +8610,7 @@ "related_to": "Physics.geometry", "description": "The geometry for this body.\n\nBy default it is a `point` geometry which gets overridden.", "short_description": "The geometry for this body.\n", - "line": 204, + "line": 171, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8632,7 +8633,7 @@ ], "description": "The mass.", "short_description": "The mass.", - "line": 211, + "line": 178, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8646,7 +8647,7 @@ "type": "namespace", "description": "The vector offsetting the body's shape from its center of mass.", "short_description": "The vector offsetting the body's shape from its center of mass.", - "line": 217, + "line": 184, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8669,7 +8670,7 @@ ], "description": "The restitution.\n\nThis is the \"bounciness\" of the body.\nIt's a number between `0` and `1`.\n\nA restitution of 1 is the bounciest.\n\nA restitution of 0 is not bouncy.\n\nWhen colliding the restitutions of bodies are\nmultiplied together to get the restitution between two\nbodies.", "short_description": "The restitution.\n", - "line": 235, + "line": 202, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8692,7 +8693,7 @@ ], "description": "The coefficient of friction of the body.\n\nIt's how much \"slide\" it has during collisions.\n\nA `cof` of `0` will really slidy.\n\nA `cof` of `1` has no slide.\n\nThis is a very simplistic implementation at the moment.\nWhat would be better is to have both static and kinetic\nfriction. But that's not done yet.", "short_description": "The coefficient of friction of the body.\n", - "line": 251, + "line": 218, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8715,7 +8716,7 @@ ], "description": "How the body is treated by the simulation.\n\nThe body can be `dynamic`, `kinematic` or `static` as\ndescribed by the [analogous box2d docs](http://www.box2d.org/manual.html#_Toc258082973).\n\n* _dynamic_ bodies are treated \"normally\". They are integrated, and collide, and all that.\n* _kinematic_ bodies are bodies that move at a specified velocity. Other bodies collide with them, but they don't bounce off of other bodies.\n* _static_ bodies just stand still. They are like obstacles.", "short_description": "How the body is treated by the simulation.\n", - "line": 264, + "line": 231, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8738,7 +8739,7 @@ ], "description": "Determines whether the body should be hidden by the renderer.", "short_description": "Determines whether the body should be hidden by the renderer.", - "line": 270, + "line": 237, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8762,7 +8763,7 @@ "related_to": "Physics.renderer", "description": "Storage for use by the renderer.\n\nThe type of renderer will put different things in the view property.\nBasically, this is how the body \"looks\". It could be a HTMLElement, or\nan Image, etc...\n\nIf your body changes appearance (shape), you should modify this somehow\notherwise the renderer will keep using this same view. If you're letting\nthe renderer create the view for you, just set this to `undefined` if the\nbody gets modified in shape during the simulation.", "short_description": "Storage for use by the renderer.\n", - "line": 285, + "line": 252, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8777,7 +8778,7 @@ "related_to": "Physics.renderer", "description": "The styles the renderer should use for creating the view.\n\nThe styles depend on the renderer. See [[Renderer#createView]] for style options.", "short_description": "The styles the renderer should use for creating the view.\n", - "line": 293, + "line": 260, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8826,7 +8827,7 @@ ], "description": "Get and/or set whether the body is asleep.\n\nIf called with a time (in ms), the time will be added to the idle time and sleep conditions will be checked.", "short_description": "Get and/or set whether the body is asleep.\n", - "line": 304, + "line": 271, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8863,7 +8864,7 @@ ], "description": "Check if the body should be sleeping.\n\nCall with no arguments if some event could possibly wake up the body. This will force the body to recheck.", "short_description": "Check if the body should be sleeping.\n", - "line": 336, + "line": 303, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8904,7 +8905,7 @@ ], "description": "Set which world to apply to.\n\nUsually this is called internally. Shouldn't be a need to call this yourself usually.", "short_description": "Set which world to apply to.\n", - "line": 399, + "line": 374, "aliases": [], "children": [], "file": "src/core/body.js", @@ -8945,7 +8946,7 @@ ], "description": "Accelerate the body by adding supplied vector to its current acceleration", "short_description": "Accelerate the body by adding supplied vector to its current acceleration", - "line": 420, + "line": 395, "aliases": [], "children": [], "file": "src/core/body.js", @@ -9001,7 +9002,7 @@ ], "description": "Apply a force at center of mass, or at point `p` relative to the center of mass", "short_description": "Apply a force at center of mass, or at point `p` relative to the center of mass", - "line": 436, + "line": 411, "aliases": [], "children": [], "file": "src/core/body.js", @@ -9051,7 +9052,7 @@ "related_to": "Body#offset", "description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", "short_description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", - "line": 470, + "line": 445, "aliases": [], "children": [], "file": "src/core/body.js", @@ -9082,7 +9083,7 @@ "related_to": "Physics.aabb", "description": "Get the Axis aligned bounding box for the body in its current position and rotation", "short_description": "Get the Axis aligned bounding box for the body in its current position and rotation", - "line": 483, + "line": 458, "aliases": [], "children": [], "file": "src/core/body.js", @@ -9130,7 +9131,7 @@ ], "description": "Transform a vector into coordinates relative to this body.", "short_description": "Transform a vector into coordinates relative to this body.", - "line": 506, + "line": 481, "aliases": [], "children": [], "file": "src/core/body.js", @@ -9178,7 +9179,7 @@ ], "description": "Transform a vector from body coordinates into world coordinates.", "short_description": "Transform a vector from body coordinates into world coordinates.", - "line": 517, + "line": 492, "aliases": [], "children": [], "file": "src/core/body.js", @@ -9202,7 +9203,7 @@ ], "description": "Recalculate properties.\n\nIntended to be overridden by subclasses. Call when body physical properties are changed.", "short_description": "Recalculate properties.\n", - "line": 528, + "line": 503, "aliases": [], "children": [], "file": "src/core/body.js", @@ -9265,7 +9266,7 @@ ], "description": "Get center of mass position from list of bodies.", "short_description": "Get center of mass position from list of bodies.", - "line": 542, + "line": 517, "aliases": [], "children": [], "file": "src/core/body.js", @@ -14918,9 +14919,9 @@ "id": "PixiRenderer", "type": "class", "superclass": "Renderer", - "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", + "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C',\n strokeAlpha: 1,\n fillAlpha: 1\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", "short_description": "Physics.renderer('pixi')\n", - "line": 74, + "line": 76, "aliases": [], "children": [ { @@ -14957,7 +14958,7 @@ ], "description": "Event callback to attach a child to the stage", "short_description": "Event callback to attach a child to the stage", - "line": 234, + "line": 239, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -14993,7 +14994,7 @@ ], "description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", "short_description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", - "line": 614, + "line": 622, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15083,7 +15084,7 @@ ], "description": "Create a circle for use in PIXI stage", "short_description": "Create a circle for use in PIXI stage", - "line": 357, + "line": 362, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15145,7 +15146,7 @@ ], "description": "Create a PIXI sprite or movie clip.", "short_description": "Create a PIXI sprite or movie clip.", - "line": 555, + "line": 563, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15221,7 +15222,7 @@ ], "description": "Create a line for use in PIXI stage", "short_description": "Create a line for use in PIXI stage", - "line": 436, + "line": 441, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15283,7 +15284,7 @@ ], "description": "Create a polygon for use in PIXI stage", "short_description": "Create a polygon for use in PIXI stage", - "line": 394, + "line": 399, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15380,7 +15381,7 @@ ], "description": "Create a rectangle for use in PIXI stage", "short_description": "Create a rectangle for use in PIXI stage", - "line": 377, + "line": 382, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15423,7 +15424,7 @@ ], "description": "Event callback to detach a child from the stage", "short_description": "Event callback to detach a child from the stage", - "line": 215, + "line": 220, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15473,7 +15474,7 @@ ], "description": "Draw a PIXI.DisplayObject to the stage.", "short_description": "Draw a PIXI.DisplayObject to the stage.", - "line": 282, + "line": 287, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15528,7 +15529,7 @@ ], "description": "Loads textures defined in a spritesheet", "short_description": "Loads textures defined in a spritesheet", - "line": 254, + "line": 259, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -15590,7 +15591,7 @@ ], "description": "Set styles on pixi graphics object", "short_description": "Set styles on pixi graphics object", - "line": 317, + "line": 322, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17324,9 +17325,9 @@ "id": "PixiRenderer", "type": "class", "superclass": "Renderer", - "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", + "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C',\n strokeAlpha: 1,\n fillAlpha: 1\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", "short_description": "Physics.renderer('pixi')\n", - "line": 74, + "line": 76, "aliases": [], "children": [ { @@ -17363,7 +17364,7 @@ ], "description": "Event callback to attach a child to the stage", "short_description": "Event callback to attach a child to the stage", - "line": 234, + "line": 239, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17399,7 +17400,7 @@ ], "description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", "short_description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", - "line": 614, + "line": 622, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17489,7 +17490,7 @@ ], "description": "Create a circle for use in PIXI stage", "short_description": "Create a circle for use in PIXI stage", - "line": 357, + "line": 362, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17551,7 +17552,7 @@ ], "description": "Create a PIXI sprite or movie clip.", "short_description": "Create a PIXI sprite or movie clip.", - "line": 555, + "line": 563, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17627,7 +17628,7 @@ ], "description": "Create a line for use in PIXI stage", "short_description": "Create a line for use in PIXI stage", - "line": 436, + "line": 441, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17689,7 +17690,7 @@ ], "description": "Create a polygon for use in PIXI stage", "short_description": "Create a polygon for use in PIXI stage", - "line": 394, + "line": 399, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17786,7 +17787,7 @@ ], "description": "Create a rectangle for use in PIXI stage", "short_description": "Create a rectangle for use in PIXI stage", - "line": 377, + "line": 382, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17829,7 +17830,7 @@ ], "description": "Event callback to detach a child from the stage", "short_description": "Event callback to detach a child from the stage", - "line": 215, + "line": 220, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17879,7 +17880,7 @@ ], "description": "Draw a PIXI.DisplayObject to the stage.", "short_description": "Draw a PIXI.DisplayObject to the stage.", - "line": 282, + "line": 287, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17934,7 +17935,7 @@ ], "description": "Loads textures defined in a spritesheet", "short_description": "Loads textures defined in a spritesheet", - "line": 254, + "line": 259, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -17996,7 +17997,7 @@ ], "description": "Set styles on pixi graphics object", "short_description": "Set styles on pixi graphics object", - "line": 317, + "line": 322, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -22125,7 +22126,7 @@ "internal": true, "description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", "short_description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", - "line": 369, + "line": 366, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -22162,7 +22163,7 @@ "internal": true, "description": "Event callback to check all pairs of objects in the list for collisions", "short_description": "Event callback to check all pairs of objects in the list for collisions", - "line": 431, + "line": 428, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -22285,7 +22286,7 @@ "internal": true, "description": "Collide two bodies by modifying their positions and velocities to conserve momentum", "short_description": "Collide two bodies by modifying their positions and velocities to conserve momentum", - "line": 66, + "line": 88, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -22322,7 +22323,7 @@ "internal": true, "description": "Event callback to respond to collision data.", "short_description": "Event callback to respond to collision data.", - "line": 255, + "line": 281, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -23362,7 +23363,7 @@ "related_to": "Physics.util.decorator", "description": "Factory function for creating Bodies.\n\nVisit [the PhysicsJS wiki on Bodies](https://github.com/wellcaffeinated/PhysicsJS/wiki/Bodies)\nfor usage documentation.", "short_description": "Factory function for creating Bodies.\n", - "line": 91, + "line": 58, "aliases": [], "children": [ { @@ -23371,7 +23372,7 @@ "belongs_to": "Physics.body", "description": "The base class for bodies created by [[Physics.body]] factory function.", "short_description": "The base class for bodies created by [[Physics.body]] factory function.", - "line": 98, + "line": 65, "aliases": [ "PointBody" ], @@ -23398,7 +23399,7 @@ "related_to": "Physics.aabb", "description": "Get the Axis aligned bounding box for the body in its current position and rotation", "short_description": "Get the Axis aligned bounding box for the body in its current position and rotation", - "line": 483, + "line": 458, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23439,7 +23440,7 @@ ], "description": "Accelerate the body by adding supplied vector to its current acceleration", "short_description": "Accelerate the body by adding supplied vector to its current acceleration", - "line": 420, + "line": 395, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23495,7 +23496,7 @@ ], "description": "Apply a force at center of mass, or at point `p` relative to the center of mass", "short_description": "Apply a force at center of mass, or at point `p` relative to the center of mass", - "line": 436, + "line": 411, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23518,7 +23519,7 @@ ], "description": "The coefficient of friction of the body.\n\nIt's how much \"slide\" it has during collisions.\n\nA `cof` of `0` will really slidy.\n\nA `cof` of `1` has no slide.\n\nThis is a very simplistic implementation at the moment.\nWhat would be better is to have both static and kinetic\nfriction. But that's not done yet.", "short_description": "The coefficient of friction of the body.\n", - "line": 251, + "line": 218, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23533,7 +23534,7 @@ "related_to": "Physics.geometry", "description": "The geometry for this body.\n\nBy default it is a `point` geometry which gets overridden.", "short_description": "The geometry for this body.\n", - "line": 204, + "line": 171, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23583,7 +23584,7 @@ "related_to": "Body#offset", "description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", "short_description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", - "line": 470, + "line": 445, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23606,7 +23607,7 @@ ], "description": "Determines whether the body should be hidden by the renderer.", "short_description": "Determines whether the body should be hidden by the renderer.", - "line": 270, + "line": 237, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23643,7 +23644,7 @@ "internal": true, "description": "Initialization. Internal use.", "short_description": "Initialization. Internal use.", - "line": 105, + "line": 72, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23666,7 +23667,7 @@ ], "description": "The mass.", "short_description": "The mass.", - "line": 211, + "line": 178, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23680,7 +23681,7 @@ "type": "namespace", "description": "The vector offsetting the body's shape from its center of mass.", "short_description": "The vector offsetting the body's shape from its center of mass.", - "line": 217, + "line": 184, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23729,7 +23730,7 @@ "related_to": "Physics.util.options", "description": "Set options on this instance.\n\nAccess options directly from the options object.\n\nExample:\n\n```javascript\nthis.options.someOption;\n```", "short_description": "Set options on this instance.\n", - "line": 126, + "line": 93, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23753,7 +23754,7 @@ ], "description": "Recalculate properties.\n\nIntended to be overridden by subclasses. Call when body physical properties are changed.", "short_description": "Recalculate properties.\n", - "line": 528, + "line": 503, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23776,7 +23777,7 @@ ], "description": "The restitution.\n\nThis is the \"bounciness\" of the body.\nIt's a number between `0` and `1`.\n\nA restitution of 1 is the bounciest.\n\nA restitution of 0 is not bouncy.\n\nWhen colliding the restitutions of bodies are\nmultiplied together to get the restitution between two\nbodies.", "short_description": "The restitution.\n", - "line": 235, + "line": 202, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23817,7 +23818,7 @@ ], "description": "Set which world to apply to.\n\nUsually this is called internally. Shouldn't be a need to call this yourself usually.", "short_description": "Set which world to apply to.\n", - "line": 399, + "line": 374, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23866,7 +23867,7 @@ ], "description": "Get and/or set whether the body is asleep.\n\nIf called with a time (in ms), the time will be added to the idle time and sleep conditions will be checked.", "short_description": "Get and/or set whether the body is asleep.\n", - "line": 304, + "line": 271, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23903,7 +23904,7 @@ ], "description": "Check if the body should be sleeping.\n\nCall with no arguments if some event could possibly wake up the body. This will force the body to recheck.", "short_description": "Check if the body should be sleeping.\n", - "line": 336, + "line": 303, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23917,7 +23918,7 @@ "type": "namespace", "description": "The physical state container.\n\n- ``this.state.pos`` ([[Physics.vector]]) The position vector.\n- ``this.state.vel`` ([[Physics.vector]]) The velocity vector.\n- ``this.state.acc`` ([[Physics.vector]]) The acceleration vector.\n- ``this.state.angular.pos`` ([[Number]]) The angular position (in radians, positive is clockwise starting along the x axis)\n- ``this.state.angular.vel`` ([[Number]]) The angular velocity\n- ``this.state.angular.acc`` ([[Number]]) The angular acceleration\n\nProperties from the previous timestep are stored in:\n```javascript\nthis.state.old; // .pos, .vel, ...\n```", "short_description": "The physical state container.\n", - "line": 150, + "line": 117, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23932,7 +23933,7 @@ "related_to": "Physics.renderer", "description": "The styles the renderer should use for creating the view.\n\nThe styles depend on the renderer. See [[Renderer#createView]] for style options.", "short_description": "The styles the renderer should use for creating the view.\n", - "line": 293, + "line": 260, "aliases": [], "children": [], "file": "src/core/body.js", @@ -23980,7 +23981,7 @@ ], "description": "Transform a vector into coordinates relative to this body.", "short_description": "Transform a vector into coordinates relative to this body.", - "line": 506, + "line": 481, "aliases": [], "children": [], "file": "src/core/body.js", @@ -24028,7 +24029,7 @@ ], "description": "Transform a vector from body coordinates into world coordinates.", "short_description": "Transform a vector from body coordinates into world coordinates.", - "line": 517, + "line": 492, "aliases": [], "children": [], "file": "src/core/body.js", @@ -24051,7 +24052,7 @@ ], "description": "How the body is treated by the simulation.\n\nThe body can be `dynamic`, `kinematic` or `static` as\ndescribed by the [analogous box2d docs](http://www.box2d.org/manual.html#_Toc258082973).\n\n* _dynamic_ bodies are treated \"normally\". They are integrated, and collide, and all that.\n* _kinematic_ bodies are bodies that move at a specified velocity. Other bodies collide with them, but they don't bounce off of other bodies.\n* _static_ bodies just stand still. They are like obstacles.", "short_description": "How the body is treated by the simulation.\n", - "line": 264, + "line": 231, "aliases": [], "children": [], "file": "src/core/body.js", @@ -24074,7 +24075,7 @@ ], "description": "The unique id for the body", "short_description": "The unique id for the body", - "line": 195, + "line": 162, "aliases": [], "children": [], "file": "src/core/body.js", @@ -24098,7 +24099,7 @@ "related_to": "Physics.renderer", "description": "Storage for use by the renderer.\n\nThe type of renderer will put different things in the view property.\nBasically, this is how the body \"looks\". It could be a HTMLElement, or\nan Image, etc...\n\nIf your body changes appearance (shape), you should modify this somehow\notherwise the renderer will keep using this same view. If you're letting\nthe renderer create the view for you, just set this to `undefined` if the\nbody gets modified in shape during the simulation.", "short_description": "Storage for use by the renderer.\n", - "line": 285, + "line": 252, "aliases": [], "children": [], "file": "src/core/body.js", @@ -24161,7 +24162,7 @@ ], "description": "Get center of mass position from list of bodies.", "short_description": "Get center of mass position from list of bodies.", - "line": 542, + "line": 517, "aliases": [], "children": [], "file": "src/core/body.js", @@ -27784,9 +27785,9 @@ "id": "PixiRenderer", "type": "class", "superclass": "Renderer", - "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", + "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C',\n strokeAlpha: 1,\n fillAlpha: 1\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", "short_description": "Physics.renderer('pixi')\n", - "line": 74, + "line": 76, "aliases": [], "children": [ { @@ -27823,7 +27824,7 @@ ], "description": "Event callback to attach a child to the stage", "short_description": "Event callback to attach a child to the stage", - "line": 234, + "line": 239, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -27859,7 +27860,7 @@ ], "description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", "short_description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", - "line": 614, + "line": 622, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -27949,7 +27950,7 @@ ], "description": "Create a circle for use in PIXI stage", "short_description": "Create a circle for use in PIXI stage", - "line": 357, + "line": 362, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28011,7 +28012,7 @@ ], "description": "Create a PIXI sprite or movie clip.", "short_description": "Create a PIXI sprite or movie clip.", - "line": 555, + "line": 563, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28087,7 +28088,7 @@ ], "description": "Create a line for use in PIXI stage", "short_description": "Create a line for use in PIXI stage", - "line": 436, + "line": 441, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28149,7 +28150,7 @@ ], "description": "Create a polygon for use in PIXI stage", "short_description": "Create a polygon for use in PIXI stage", - "line": 394, + "line": 399, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28246,7 +28247,7 @@ ], "description": "Create a rectangle for use in PIXI stage", "short_description": "Create a rectangle for use in PIXI stage", - "line": 377, + "line": 382, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28289,7 +28290,7 @@ ], "description": "Event callback to detach a child from the stage", "short_description": "Event callback to detach a child from the stage", - "line": 215, + "line": 220, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28339,7 +28340,7 @@ ], "description": "Draw a PIXI.DisplayObject to the stage.", "short_description": "Draw a PIXI.DisplayObject to the stage.", - "line": 282, + "line": 287, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28394,7 +28395,7 @@ ], "description": "Loads textures defined in a spritesheet", "short_description": "Loads textures defined in a spritesheet", - "line": 254, + "line": 259, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -28456,7 +28457,7 @@ ], "description": "Set styles on pixi graphics object", "short_description": "Set styles on pixi graphics object", - "line": 317, + "line": 322, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -36281,6 +36282,175 @@ "path": "Physics.gjk", "outFile": "gjk.html#Physics.gjk" }, + "Physics.statistics.pushRunningAvg": { + "id": "Physics.statistics.pushRunningAvg", + "type": "class method", + "signatures": [ + { + "arguments": [ + { + "name": "v", + "types": [ + "Number" + ], + "description": " is value to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Number" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "types": [ + "Number" + ], + "description": " is current s value\n\n " + } + ], + "returns": [ + { + "type": "Array", + "description": " Returns a 2 element array containing the next mean, and s value\n\n " + } + ] + } + ], + "arguments": [ + { + "name": "v", + "types": [ + "Number" + ], + "description": " is value to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Number" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "types": [ + "Number" + ], + "description": " is current s value\n\n " + } + ], + "returns": [ + { + "type": "Array", + "description": " Returns a 2 element array containing the next mean, and s value\n\n " + } + ], + "description": "Push a value to a running average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n\nNote: variance can be calculated from the \"s\" value by multiplying it by `1/(k-1)`", + "short_description": "Push a value to a running average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n", + "line": 17, + "aliases": [], + "children": [], + "file": "src/math/statistics.js", + "name": "pushRunningAvg", + "name_prefix": "Physics.statistics.", + "path": "Physics.statistics.pushRunningAvg", + "outFile": "statistics.html#Physics.statistics.pushRunningAvg" + }, + "Physics.statistics.pushRunningVectorAvg": { + "id": "Physics.statistics.pushRunningVectorAvg", + "type": "class method", + "signatures": [ + { + "arguments": [ + { + "name": "v", + "types": [ + "Physics.vector" + ], + "description": " is vector to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Physics.vector" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "optional": true, + "types": [ + "Physics.vector" + ], + "description": " is current s value\n\n " + } + ] + } + ], + "arguments": [ + { + "name": "v", + "types": [ + "Physics.vector" + ], + "description": " is vector to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Physics.vector" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "types": [ + "Physics.vector" + ], + "description": " is current s value\n\n " + } + ], + "description": "Push a vector to a running vector average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n\nCalculations are done in place. The `m` and `s` parameters are altered.\n\nNote: variance can be calculated from the \"s\" vector by multiplying it by `1/(k-1)`\n\nIf s value is ommitted it won't be used.", + "short_description": "Push a vector to a running vector average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n", + "line": 44, + "aliases": [], + "children": [], + "file": "src/math/statistics.js", + "name": "pushRunningVectorAvg", + "name_prefix": "Physics.statistics.", + "path": "Physics.statistics.pushRunningVectorAvg", + "outFile": "statistics.html#Physics.statistics.pushRunningVectorAvg" + }, "Physics.transform": { "id": "Physics.transform", "type": "class", @@ -42840,9 +43010,9 @@ "id": "PixiRenderer", "type": "class", "superclass": "Renderer", - "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", + "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C',\n strokeAlpha: 1,\n fillAlpha: 1\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", "short_description": "Physics.renderer('pixi')\n", - "line": 74, + "line": 76, "aliases": [], "children": [ { @@ -42879,7 +43049,7 @@ ], "description": "Event callback to attach a child to the stage", "short_description": "Event callback to attach a child to the stage", - "line": 234, + "line": 239, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -42915,7 +43085,7 @@ ], "description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", "short_description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", - "line": 614, + "line": 622, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43005,7 +43175,7 @@ ], "description": "Create a circle for use in PIXI stage", "short_description": "Create a circle for use in PIXI stage", - "line": 357, + "line": 362, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43067,7 +43237,7 @@ ], "description": "Create a PIXI sprite or movie clip.", "short_description": "Create a PIXI sprite or movie clip.", - "line": 555, + "line": 563, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43143,7 +43313,7 @@ ], "description": "Create a line for use in PIXI stage", "short_description": "Create a line for use in PIXI stage", - "line": 436, + "line": 441, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43205,7 +43375,7 @@ ], "description": "Create a polygon for use in PIXI stage", "short_description": "Create a polygon for use in PIXI stage", - "line": 394, + "line": 399, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43302,7 +43472,7 @@ ], "description": "Create a rectangle for use in PIXI stage", "short_description": "Create a rectangle for use in PIXI stage", - "line": 377, + "line": 382, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43345,7 +43515,7 @@ ], "description": "Event callback to detach a child from the stage", "short_description": "Event callback to detach a child from the stage", - "line": 215, + "line": 220, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43395,7 +43565,7 @@ ], "description": "Draw a PIXI.DisplayObject to the stage.", "short_description": "Draw a PIXI.DisplayObject to the stage.", - "line": 282, + "line": 287, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43450,7 +43620,7 @@ ], "description": "Loads textures defined in a spritesheet", "short_description": "Loads textures defined in a spritesheet", - "line": 254, + "line": 259, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43512,7 +43682,7 @@ ], "description": "Set styles on pixi graphics object", "short_description": "Set styles on pixi graphics object", - "line": 317, + "line": 322, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43562,7 +43732,7 @@ ], "description": "Event callback to detach a child from the stage", "short_description": "Event callback to detach a child from the stage", - "line": 215, + "line": 220, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43605,7 +43775,7 @@ ], "description": "Event callback to attach a child to the stage", "short_description": "Event callback to attach a child to the stage", - "line": 234, + "line": 239, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43660,7 +43830,7 @@ ], "description": "Loads textures defined in a spritesheet", "short_description": "Loads textures defined in a spritesheet", - "line": 254, + "line": 259, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43710,7 +43880,7 @@ ], "description": "Draw a PIXI.DisplayObject to the stage.", "short_description": "Draw a PIXI.DisplayObject to the stage.", - "line": 282, + "line": 287, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43772,7 +43942,7 @@ ], "description": "Set styles on pixi graphics object", "short_description": "Set styles on pixi graphics object", - "line": 317, + "line": 322, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43862,7 +44032,7 @@ ], "description": "Create a circle for use in PIXI stage", "short_description": "Create a circle for use in PIXI stage", - "line": 357, + "line": 362, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -43959,7 +44129,7 @@ ], "description": "Create a rectangle for use in PIXI stage", "short_description": "Create a rectangle for use in PIXI stage", - "line": 377, + "line": 382, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -44021,7 +44191,7 @@ ], "description": "Create a polygon for use in PIXI stage", "short_description": "Create a polygon for use in PIXI stage", - "line": 394, + "line": 399, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -44097,7 +44267,7 @@ ], "description": "Create a line for use in PIXI stage", "short_description": "Create a line for use in PIXI stage", - "line": 436, + "line": 441, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -44159,7 +44329,7 @@ ], "description": "Create a PIXI sprite or movie clip.", "short_description": "Create a PIXI sprite or movie clip.", - "line": 555, + "line": 563, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -44195,7 +44365,7 @@ ], "description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", "short_description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", - "line": 614, + "line": 622, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -48543,7 +48713,7 @@ "internal": true, "description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", "short_description": "Event callback to check pairs of objects that have been flagged by broad phase for possible collisions.", - "line": 369, + "line": 366, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -48580,7 +48750,7 @@ "internal": true, "description": "Event callback to check all pairs of objects in the list for collisions", "short_description": "Event callback to check all pairs of objects in the list for collisions", - "line": 431, + "line": 428, "aliases": [], "children": [], "file": "src/behaviors/body-collision-detection.js", @@ -48703,7 +48873,7 @@ "internal": true, "description": "Collide two bodies by modifying their positions and velocities to conserve momentum", "short_description": "Collide two bodies by modifying their positions and velocities to conserve momentum", - "line": 66, + "line": 88, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -48740,7 +48910,7 @@ "internal": true, "description": "Event callback to respond to collision data.", "short_description": "Event callback to respond to collision data.", - "line": 255, + "line": 281, "aliases": [], "children": [], "file": "src/behaviors/body-impulse-response.js", @@ -49780,7 +49950,7 @@ "related_to": "Physics.util.decorator", "description": "Factory function for creating Bodies.\n\nVisit [the PhysicsJS wiki on Bodies](https://github.com/wellcaffeinated/PhysicsJS/wiki/Bodies)\nfor usage documentation.", "short_description": "Factory function for creating Bodies.\n", - "line": 91, + "line": 58, "aliases": [], "children": [ { @@ -49789,7 +49959,7 @@ "belongs_to": "Physics.body", "description": "The base class for bodies created by [[Physics.body]] factory function.", "short_description": "The base class for bodies created by [[Physics.body]] factory function.", - "line": 98, + "line": 65, "aliases": [ "PointBody" ], @@ -49816,7 +49986,7 @@ "related_to": "Physics.aabb", "description": "Get the Axis aligned bounding box for the body in its current position and rotation", "short_description": "Get the Axis aligned bounding box for the body in its current position and rotation", - "line": 483, + "line": 458, "aliases": [], "children": [], "file": "src/core/body.js", @@ -49857,7 +50027,7 @@ ], "description": "Accelerate the body by adding supplied vector to its current acceleration", "short_description": "Accelerate the body by adding supplied vector to its current acceleration", - "line": 420, + "line": 395, "aliases": [], "children": [], "file": "src/core/body.js", @@ -49913,7 +50083,7 @@ ], "description": "Apply a force at center of mass, or at point `p` relative to the center of mass", "short_description": "Apply a force at center of mass, or at point `p` relative to the center of mass", - "line": 436, + "line": 411, "aliases": [], "children": [], "file": "src/core/body.js", @@ -49936,7 +50106,7 @@ ], "description": "The coefficient of friction of the body.\n\nIt's how much \"slide\" it has during collisions.\n\nA `cof` of `0` will really slidy.\n\nA `cof` of `1` has no slide.\n\nThis is a very simplistic implementation at the moment.\nWhat would be better is to have both static and kinetic\nfriction. But that's not done yet.", "short_description": "The coefficient of friction of the body.\n", - "line": 251, + "line": 218, "aliases": [], "children": [], "file": "src/core/body.js", @@ -49951,7 +50121,7 @@ "related_to": "Physics.geometry", "description": "The geometry for this body.\n\nBy default it is a `point` geometry which gets overridden.", "short_description": "The geometry for this body.\n", - "line": 204, + "line": 171, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50001,7 +50171,7 @@ "related_to": "Body#offset", "description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", "short_description": "Get the body offset vector (from the center of mass) for the body's shape in global coordinates.", - "line": 470, + "line": 445, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50024,7 +50194,7 @@ ], "description": "Determines whether the body should be hidden by the renderer.", "short_description": "Determines whether the body should be hidden by the renderer.", - "line": 270, + "line": 237, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50061,7 +50231,7 @@ "internal": true, "description": "Initialization. Internal use.", "short_description": "Initialization. Internal use.", - "line": 105, + "line": 72, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50084,7 +50254,7 @@ ], "description": "The mass.", "short_description": "The mass.", - "line": 211, + "line": 178, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50098,7 +50268,7 @@ "type": "namespace", "description": "The vector offsetting the body's shape from its center of mass.", "short_description": "The vector offsetting the body's shape from its center of mass.", - "line": 217, + "line": 184, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50147,7 +50317,7 @@ "related_to": "Physics.util.options", "description": "Set options on this instance.\n\nAccess options directly from the options object.\n\nExample:\n\n```javascript\nthis.options.someOption;\n```", "short_description": "Set options on this instance.\n", - "line": 126, + "line": 93, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50171,7 +50341,7 @@ ], "description": "Recalculate properties.\n\nIntended to be overridden by subclasses. Call when body physical properties are changed.", "short_description": "Recalculate properties.\n", - "line": 528, + "line": 503, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50194,7 +50364,7 @@ ], "description": "The restitution.\n\nThis is the \"bounciness\" of the body.\nIt's a number between `0` and `1`.\n\nA restitution of 1 is the bounciest.\n\nA restitution of 0 is not bouncy.\n\nWhen colliding the restitutions of bodies are\nmultiplied together to get the restitution between two\nbodies.", "short_description": "The restitution.\n", - "line": 235, + "line": 202, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50235,7 +50405,7 @@ ], "description": "Set which world to apply to.\n\nUsually this is called internally. Shouldn't be a need to call this yourself usually.", "short_description": "Set which world to apply to.\n", - "line": 399, + "line": 374, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50284,7 +50454,7 @@ ], "description": "Get and/or set whether the body is asleep.\n\nIf called with a time (in ms), the time will be added to the idle time and sleep conditions will be checked.", "short_description": "Get and/or set whether the body is asleep.\n", - "line": 304, + "line": 271, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50321,7 +50491,7 @@ ], "description": "Check if the body should be sleeping.\n\nCall with no arguments if some event could possibly wake up the body. This will force the body to recheck.", "short_description": "Check if the body should be sleeping.\n", - "line": 336, + "line": 303, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50335,7 +50505,7 @@ "type": "namespace", "description": "The physical state container.\n\n- ``this.state.pos`` ([[Physics.vector]]) The position vector.\n- ``this.state.vel`` ([[Physics.vector]]) The velocity vector.\n- ``this.state.acc`` ([[Physics.vector]]) The acceleration vector.\n- ``this.state.angular.pos`` ([[Number]]) The angular position (in radians, positive is clockwise starting along the x axis)\n- ``this.state.angular.vel`` ([[Number]]) The angular velocity\n- ``this.state.angular.acc`` ([[Number]]) The angular acceleration\n\nProperties from the previous timestep are stored in:\n```javascript\nthis.state.old; // .pos, .vel, ...\n```", "short_description": "The physical state container.\n", - "line": 150, + "line": 117, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50350,7 +50520,7 @@ "related_to": "Physics.renderer", "description": "The styles the renderer should use for creating the view.\n\nThe styles depend on the renderer. See [[Renderer#createView]] for style options.", "short_description": "The styles the renderer should use for creating the view.\n", - "line": 293, + "line": 260, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50398,7 +50568,7 @@ ], "description": "Transform a vector into coordinates relative to this body.", "short_description": "Transform a vector into coordinates relative to this body.", - "line": 506, + "line": 481, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50446,7 +50616,7 @@ ], "description": "Transform a vector from body coordinates into world coordinates.", "short_description": "Transform a vector from body coordinates into world coordinates.", - "line": 517, + "line": 492, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50469,7 +50639,7 @@ ], "description": "How the body is treated by the simulation.\n\nThe body can be `dynamic`, `kinematic` or `static` as\ndescribed by the [analogous box2d docs](http://www.box2d.org/manual.html#_Toc258082973).\n\n* _dynamic_ bodies are treated \"normally\". They are integrated, and collide, and all that.\n* _kinematic_ bodies are bodies that move at a specified velocity. Other bodies collide with them, but they don't bounce off of other bodies.\n* _static_ bodies just stand still. They are like obstacles.", "short_description": "How the body is treated by the simulation.\n", - "line": 264, + "line": 231, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50492,7 +50662,7 @@ ], "description": "The unique id for the body", "short_description": "The unique id for the body", - "line": 195, + "line": 162, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50516,7 +50686,7 @@ "related_to": "Physics.renderer", "description": "Storage for use by the renderer.\n\nThe type of renderer will put different things in the view property.\nBasically, this is how the body \"looks\". It could be a HTMLElement, or\nan Image, etc...\n\nIf your body changes appearance (shape), you should modify this somehow\notherwise the renderer will keep using this same view. If you're letting\nthe renderer create the view for you, just set this to `undefined` if the\nbody gets modified in shape during the simulation.", "short_description": "Storage for use by the renderer.\n", - "line": 285, + "line": 252, "aliases": [], "children": [], "file": "src/core/body.js", @@ -50579,7 +50749,7 @@ ], "description": "Get center of mass position from list of bodies.", "short_description": "Get center of mass position from list of bodies.", - "line": 542, + "line": 517, "aliases": [], "children": [], "file": "src/core/body.js", @@ -54202,9 +54372,9 @@ "id": "PixiRenderer", "type": "class", "superclass": "Renderer", - "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", + "description": "Physics.renderer('pixi')\n\nRenderer that uses the PIXI.js library. [Documentation can be found here](https://github.com/wellcaffeinated/PhysicsJS/wiki/PIXI-Renderer).\n\nAdditional config options:\n\n- metaEl: HTMLElement to write meta information like FPS and IPF into. (default: autogenerated)\n- offset: Offset the shapes by this amount. (default: `{ x: 0, y: 0 }`)\n- styles: Styles to use to draw the shapes. (see below)\n\nThe styles property should contain _default_ styles for each shape you want to draw.\n\nExample:\n\n```javascript\nstyles: {\n // Defines the default canvas colour\n 'color': '0x66FF99',\n\n 'circle' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C',\n strokeAlpha: 1,\n fillAlpha: 1\n },\n\n 'convex-polygon' : {\n strokeStyle: '0xE8900C',\n lineWidth: 3,\n fillStyle: '0xD5DE4C',\n angleIndicator: '0xE8900C'\n }\n}\n```\n\nStyles can also be defined on a per-body basis. Use the \"styles\" property for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n strokeStyle: '0x542437',\n lineWidth: 1,\n fillStyle: '0x542437',\n angleIndicator: '0xFFFFFF'\n }\n});\n```\n\nYou can also define an image to use for a body:\n\nExample:\n\n```javascript\nPhysics.body('circle', {\n // ...\n styles: {\n src: 'path/to/image.jpg',\n width: 40,\n height: 50,\n anchor: { x: 0.5, y: 0.5 }\n }\n});\n```", "short_description": "Physics.renderer('pixi')\n", - "line": 74, + "line": 76, "aliases": [], "children": [ { @@ -54241,7 +54411,7 @@ ], "description": "Event callback to attach a child to the stage", "short_description": "Event callback to attach a child to the stage", - "line": 234, + "line": 239, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54277,7 +54447,7 @@ ], "description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", "short_description": "Centers the anchor to {x: 0.5, y: 0.5} of a view", - "line": 614, + "line": 622, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54367,7 +54537,7 @@ ], "description": "Create a circle for use in PIXI stage", "short_description": "Create a circle for use in PIXI stage", - "line": 357, + "line": 362, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54429,7 +54599,7 @@ ], "description": "Create a PIXI sprite or movie clip.", "short_description": "Create a PIXI sprite or movie clip.", - "line": 555, + "line": 563, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54505,7 +54675,7 @@ ], "description": "Create a line for use in PIXI stage", "short_description": "Create a line for use in PIXI stage", - "line": 436, + "line": 441, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54567,7 +54737,7 @@ ], "description": "Create a polygon for use in PIXI stage", "short_description": "Create a polygon for use in PIXI stage", - "line": 394, + "line": 399, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54664,7 +54834,7 @@ ], "description": "Create a rectangle for use in PIXI stage", "short_description": "Create a rectangle for use in PIXI stage", - "line": 377, + "line": 382, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54707,7 +54877,7 @@ ], "description": "Event callback to detach a child from the stage", "short_description": "Event callback to detach a child from the stage", - "line": 215, + "line": 220, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54757,7 +54927,7 @@ ], "description": "Draw a PIXI.DisplayObject to the stage.", "short_description": "Draw a PIXI.DisplayObject to the stage.", - "line": 282, + "line": 287, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54812,7 +54982,7 @@ ], "description": "Loads textures defined in a spritesheet", "short_description": "Loads textures defined in a spritesheet", - "line": 254, + "line": 259, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -54874,7 +55044,7 @@ ], "description": "Set styles on pixi graphics object", "short_description": "Set styles on pixi graphics object", - "line": 317, + "line": 322, "aliases": [], "children": [], "file": "src/renderers/pixi-renderer.js", @@ -60093,6 +60263,175 @@ "path": "wrapRule", "outFile": "query.html#wrapRule" }, + { + "id": "Physics.statistics.pushRunningAvg", + "type": "class method", + "signatures": [ + { + "arguments": [ + { + "name": "v", + "types": [ + "Number" + ], + "description": " is value to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Number" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "types": [ + "Number" + ], + "description": " is current s value\n\n " + } + ], + "returns": [ + { + "type": "Array", + "description": " Returns a 2 element array containing the next mean, and s value\n\n " + } + ] + } + ], + "arguments": [ + { + "name": "v", + "types": [ + "Number" + ], + "description": " is value to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Number" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "types": [ + "Number" + ], + "description": " is current s value\n\n " + } + ], + "returns": [ + { + "type": "Array", + "description": " Returns a 2 element array containing the next mean, and s value\n\n " + } + ], + "description": "Push a value to a running average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n\nNote: variance can be calculated from the \"s\" value by multiplying it by `1/(k-1)`", + "short_description": "Push a value to a running average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n", + "line": 17, + "aliases": [], + "children": [], + "file": "src/math/statistics.js", + "name": "pushRunningAvg", + "name_prefix": "Physics.statistics.", + "path": "Physics.statistics.pushRunningAvg", + "outFile": "statistics.html#Physics.statistics.pushRunningAvg" + }, + { + "id": "Physics.statistics.pushRunningVectorAvg", + "type": "class method", + "signatures": [ + { + "arguments": [ + { + "name": "v", + "types": [ + "Physics.vector" + ], + "description": " is vector to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Physics.vector" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "optional": true, + "types": [ + "Physics.vector" + ], + "description": " is current s value\n\n " + } + ] + } + ], + "arguments": [ + { + "name": "v", + "types": [ + "Physics.vector" + ], + "description": " is vector to push\n\n " + }, + { + "name": "k", + "types": [ + "Number" + ], + "description": " is num elements\n\n " + }, + { + "name": "m", + "types": [ + "Physics.vector" + ], + "description": " is current mean\n\n " + }, + { + "name": "s", + "types": [ + "Physics.vector" + ], + "description": " is current s value\n\n " + } + ], + "description": "Push a vector to a running vector average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n\nCalculations are done in place. The `m` and `s` parameters are altered.\n\nNote: variance can be calculated from the \"s\" vector by multiplying it by `1/(k-1)`\n\nIf s value is ommitted it won't be used.", + "short_description": "Push a vector to a running vector average calculation.\nsee [http://www.johndcook.com/blog/standard_deviation]\n", + "line": 44, + "aliases": [], + "children": [], + "file": "src/math/statistics.js", + "name": "pushRunningVectorAvg", + "name_prefix": "Physics.statistics.", + "path": "Physics.statistics.pushRunningVectorAvg", + "outFile": "statistics.html#Physics.statistics.pushRunningVectorAvg" + }, { "id": "special", "type": "section", diff --git a/docs/index.html b/docs/index.html index c91c51e0..48c5877e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,4 +1,4 @@ -

Physics

The top-level namespace. All of PhysicsJS is contained in +

Physics

The top-level namespace. All of PhysicsJS is contained in the Physics namespace.

It may (and should) be invoked as a function to create a world instance. For all intensive purposes, Physics and Physics.world are the same thing.

See new Physics.world for config options and function signature.

@@ -356,9 +356,9 @@

source: src/behaviors/body-collision-detection.js : 27

BodyImpulseResponseBehavior
extends:Behavior

Physics.behavior('body-impulse-response').

Responds to collisions by applying impulses.

Additional options include:

    @@ -375,9 +375,9 @@
    point
    (Vector)

    Contact point of the collision

    mtrans
    (Vector)

    Minimum transit vector that is the smallest displacement to separate the bodies

    contact
    (Boolean)

    Are the bodies in resting contact relative to each other

    -

source: src/behaviors/body-impulse-response.js : 66

ConstantAccelerationBehavior
extends:Behavior

Physics.behavior('constant-acceleration').

Constant acceleration behavior.

Basically the "gravity" behavior. Used to give "earth-like gravity" to the world.

Additional options include:

@@ -570,8 +570,8 @@

returns

Body

Visit the PhysicsJS wiki on Bodies for usage documentation.

-
Related to:Physics.util.decorator

source: src/core/body.js : 91

Body

The base class for bodies created by Physics.body factory function.

-

source: src/core/body.js : 98

CircleBody
extends:Body

Physics.body('circle')

+
Related to:Physics.util.decorator

source: src/core/body.js : 58

Body

The base class for bodies created by Physics.body factory function.

+

source: src/core/body.js : 65

this.cof

The coefficient of friction of the body.

  • this.cof = 0.8;

It's how much "slide" it has during collisions.

A cof of 0 will really slidy.

A cof of 1 has no slide.

This is a very simplistic implementation at the moment. What would be better is to have both static and kinetic friction. But that's not done yet.

-

source: src/core/body.js : 251

this.options()

Set options on this instance.

  • this.options(options); // -> Object

    accepts

    options
    (Object)

    The options to set as an object

    returns

    Object

    The options

Access options directly from the options object.

@@ -689,9 +689,9 @@
-
Related to:Physics.util.options

source: src/core/body.js : 126

this.restitution

The restitution.

  • this.restitution = 1;

This is the "bounciness" of the body. It's a number between 0 and 1.

A restitution of 1 is the bounciest.

@@ -699,16 +699,16 @@

When colliding the restitutions of bodies are multiplied together to get the restitution between two bodies.

-

source: src/core/body.js : 235

this.sleep()

Get and/or set whether the body is asleep.

If called with a time (in ms), the time will be added to the idle time and sleep conditions will be checked.

-

source: src/core/body.js : 304

this.sleepCheck()

Check if the body should be sleeping.

  • this.sleepCheck(dt); // -> void

    accepts

    dt
    (Number)optional

    Time to advance the idle time

Call with no arguments if some event could possibly wake up the body. This will force the body to recheck.

-

source: src/core/body.js : 336

source: src/core/body.js : 150

this.treatment

How the body is treated by the simulation.

  • this.treatment = String;

The body can be dynamic, kinematic or static as described by the analogous box2d docs.

    @@ -738,8 +738,8 @@
  • kinematic bodies are bodies that move at a specified velocity. Other bodies collide with them, but they don't bounce off of other bodies.
  • static bodies just stand still. They are like obstacles.
-

source: src/core/body.js : 264

this.view

Storage for use by the renderer.

  • this.view = it_depends;

The type of renderer will put different things in the view property. Basically, this is how the body "looks". It could be a HTMLElement, or an Image, etc...

@@ -747,11 +747,11 @@ otherwise the renderer will keep using this same view. If you're letting the renderer create the view for you, just set this to undefined if the body gets modified in shape during the simulation.

-
Related to:Physics.renderer

source: src/core/body.js : 285

Physics.geometry()

Factory function for creating Geometries.

  • Physics.geometry(name, options); // -> Geometry

    accepts

    name
    (String)

    The name of the geometry to create

    options
    (Object)optional

    The configuration for that geometry ( depends on geometry ).

    returns

    Geometry

Visit the PhysicsJS wiki on Geometries @@ -1271,7 +1271,9 @@ strokeStyle: '0xE8900C', lineWidth: 3, fillStyle: '0xD5DE4C', - angleIndicator: '0xE8900C' + angleIndicator: '0xE8900C', + strokeAlpha: 1, + fillAlpha: 1 }, 'convex-polygon' : { @@ -1312,48 +1314,48 @@

-

source: src/renderers/pixi-renderer.js : 74

this.attach()

Event callback to attach a child to the stage

+

source: src/renderers/pixi-renderer.js : 76

Physics.statistics.pushRunningAvg()

Push a value to a running average calculation. +see [http://www.johndcook.com/blog/standard_deviation]

+
  • Physics.statistics.pushRunningAvg(v, k, m, s); // -> Array

    accepts

    v
    (Number)

    is value to push

    +
    k
    (Number)

    is num elements

    +
    m
    (Number)

    is current mean

    +
    s
    (Number)

    is current s value

    +

    returns

    Array

    Returns a 2 element array containing the next mean, and s value

    +

Note: variance can be calculated from the "s" value by multiplying it by 1/(k-1)

+

source: src/math/statistics.js : 17

Physics.statistics.pushRunningVectorAvg()

Push a vector to a running vector average calculation. +see [http://www.johndcook.com/blog/standard_deviation]

+

Calculations are done in place. The m and s parameters are altered.

+

Note: variance can be calculated from the "s" vector by multiplying it by 1/(k-1)

+

If s value is ommitted it won't be used.

+

source: src/math/statistics.js : 44

Special

This section contains miscellaneous functionality.

source: src/intro.js : 54

Vectorish

Any object with .x and .y properties.

A Vectorish isn't really a class. In this documentation, when an argument is specified as a Vectorish it means either a true diff --git a/examples/physicsjs-full.js b/examples/physicsjs-full.js index ba321745..96309861 100644 --- a/examples/physicsjs-full.js +++ b/examples/physicsjs-full.js @@ -1,5 +1,5 @@ /** - * PhysicsJS v0.7.0 - 2014-12-04 + * PhysicsJS v0.7.0 - 2014-12-08 * A modular, extendable, and easy-to-use physics engine for javascript * http://wellcaffeinated.net/PhysicsJS * @@ -573,6 +573,73 @@ Physics.util = {}; })(); +// --- +// inside: src/math/statistics.js + +(function(){ + + Physics.statistics = { + /** + * Physics.statistics.pushRunningAvg( v, k, m, s ) -> Array + * - v (Number): is value to push + * - k (Number): is num elements + * - m (Number): is current mean + * - s (Number): is current s value + * + (Array): Returns a 2 element array containing the next mean, and s value + * + * Push a value to a running average calculation. + * see [http://www.johndcook.com/blog/standard_deviation] + * + * Note: variance can be calculated from the "s" value by multiplying it by `1/(k-1)` + **/ + pushRunningAvg: function( v, k, m, s ){ + + var x = v - m; + + // Mk = Mk-1+ (xk – Mk-1)/k + // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). + m += x / k; + s += x * (v - m); + return [m, s]; + }, + + /** + * Physics.statistics.pushRunningVectorAvg( v, k, m[, s] ) + * - v (Physics.vector): is vector to push + * - k (Number): is num elements + * - m (Physics.vector): is current mean + * - s (Physics.vector): is current s value + * + * Push a vector to a running vector average calculation. + * see [http://www.johndcook.com/blog/standard_deviation] + * + * Calculations are done in place. The `m` and `s` parameters are altered. + * + * Note: variance can be calculated from the "s" vector by multiplying it by `1/(k-1)` + * + * If s value is ommitted it won't be used. + **/ + pushRunningVectorAvg: function( v, k, m, s ){ + var invK = 1/k + ,x = v.get(0) - m.get(0) + ,y = v.get(1) - m.get(1) + ; + + // Mk = Mk-1+ (xk – Mk-1)/k + // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). + m.add( x * invK, y * invK ); + + if ( s ){ + x *= v.get(0) - m.get(0); + y *= v.get(1) - m.get(1); + + s.add( x, y ); + } + } + }; +})(); + + // --- // inside: src/math/transform.js @@ -3524,46 +3591,13 @@ Physics.scratchpad = (function(){ view: null }; - // Running average - // http://www.johndcook.com/blog/standard_deviation - // k is num elements - // m is current mean - // s is current std deviation - // v is value to push - function pushRunningAvg( k, m, s, v ){ - - var x = v - m; - - // Mk = Mk-1+ (xk – Mk-1)/k - // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). - m += x / k; - s += x * (v - m); - } - - // Running vector average - // http://www.johndcook.com/blog/standard_deviation - // k is num elements - // m is current mean (vector) - // s is current std deviation (vector) - // v is vector to push - function pushRunningVectorAvg( k, m, s, v ){ - var invK = 1/k - ,x = v.get(0) - m.get(0) - ,y = v.get(1) - m.get(1) - ; - - // Mk = Mk-1+ (xk – Mk-1)/k - // Sk = Sk-1 + (xk – Mk-1)*(xk – Mk). - m.add( x * invK, y * invK ); - - x *= v.get(0) - m.get(0); - y *= v.get(1) - m.get(1); + var uidGen = 1; - s.add( x, y ); + var Pi2 = Math.PI * 2; + function cycleAngle( ang ){ + return ((ang % Pi2) + Pi2) % Pi2; } - var uidGen = 1; - /** related to: Physics.util.decorator * Physics.body( name[, options] ) -> Body * - name (String): The name of the body to create @@ -3857,6 +3891,8 @@ Physics.scratchpad = (function(){ ,scratch = Physics.scratchpad() ,diff = scratch.vector() ,diff2 = scratch.vector() + ,kfac + ,stats ; dt = dt || 0; @@ -3875,11 +3911,17 @@ Physics.scratchpad = (function(){ } this._sleepMeanK++; - pushRunningVectorAvg( this._sleepMeanK, this._sleepPosMean, this._sleepPosVariance, this.state.pos ); - pushRunningAvg( this._sleepMeanK, this._sleepAngPosMean, this._sleepAngPosVariance, this.state.angular.pos ); - v = this._sleepPosVariance.norm() + Math.abs(r * this._sleepAngPosVariance); + kfac = this._sleepMeanK > 1 ? 1/(this._sleepMeanK - 1) : 0; + Physics.statistics.pushRunningVectorAvg( this.state.pos, this._sleepMeanK, this._sleepPosMean, this._sleepPosVariance ); + // we take the sin because that maps the discontinuous angle to a continuous value + // then the statistics calculations work better + stats = Physics.statistics.pushRunningAvg( Math.sin(this.state.angular.pos), this._sleepMeanK, this._sleepAngPosMean, this._sleepAngPosVariance ); + this._sleepAngPosMean = stats[0]; + this._sleepAngPosVariance = stats[1]; + v = this._sleepPosVariance.norm() + Math.abs(r * Math.asin(stats[1])); + v *= kfac; limit = this.sleepVarianceLimit || (opts && opts.sleepVarianceLimit) || 0; - + // console.log(v, limit, kfac, this._sleepPosVariance.norm(), stats[1]) if ( v <= limit ){ // check idle time limit = this.sleepTimeLimit || (opts && opts.sleepTimeLimit) || 0; @@ -5000,9 +5042,9 @@ Physics.geometry.nearestPointOnLine = function nearestPointOnLine( pt, linePt1, // is sleeping disabled? sleepDisabled: false, // speed at which bodies wake up - sleepSpeedLimit: 0.1, + sleepSpeedLimit: 0.05, // variance in position below which bodies fall asleep - sleepVarianceLimit: 2, + sleepVarianceLimit: 0.02, // time (ms) before sleepy bodies fall asleep sleepTimeLimit: 500 }; @@ -7234,11 +7276,8 @@ Physics.behavior('body-collision-detection', function( parent ){ bodyB: bodyB }; - // figure out how much the bodies moved relative to each other - tmp.clone( bodyA.state.pos ).vsub( bodyA.state.old.pos ).vsub( bodyB.state.pos ).vadd( bodyB.state.old.pos ); - inc = Math.abs(tmp.proj( d )); - // let's increment the margin by half this value each iteration - inc = Math.max( 0.5 * inc, 1 ); + // inc by 1% of the smallest dim. + inc = 1e-2 * Math.min(dimA || 1, dimB || 1); // first get the min distance of between core objects support.useCore = true; @@ -7328,7 +7367,7 @@ Physics.behavior('body-collision-detection', function( parent ){ }; /* - * checkPair( bodyA, bodyB ) -> Object + * checkPair( bodyA, bodyB[, disp] ) -> Object * - bodyA (Object): First body * - bodyB (Object): Second body * + (Object): Collision result @@ -7623,6 +7662,26 @@ Physics.behavior('body-impulse-response', function( parent ){ ,forceWakeupAboveOverlapThreshold: true }; + function getUid( b ){ + return b.uid; + } + + function clampMTV( totalV, mtv, into ){ + + var m, n; + n = mtv.norm(); + m = n - totalV.proj( mtv ); + m = Math.max( 0, Math.min( n, m ) ); + + if ( n === 0 ){ + into.zero(); + } else { + into.clone( mtv ).mult( m/n ); + } + + return into; + } + return { // extended @@ -7631,6 +7690,8 @@ Physics.behavior('body-impulse-response', function( parent ){ parent.init.call( this ); this.options.defaults( defaults ); this.options( options ); + + this._bodyList = []; }, // no applyTo method @@ -7712,38 +7773,34 @@ Physics.behavior('body-impulse-response', function( parent ){ ,impulse ,sign ,max + ,ratio ,inContact = contact ; if ( contact ){ - if ( mtv.normSq() < this.options.mtvThreshold ){ - mtv.mult( this.options.bodyExtractDropoff ); - } else if ( this.options.forceWakeupAboveOverlapThreshold ) { - // wake up bodies if necessary - bodyA.sleep( false ); - bodyB.sleep( false ); - } if ( fixedA ){ - // extract bodies - bodyB.state.pos.vadd( mtv ); - bodyB.state.old.pos.vadd( mtv ); + clampMTV( bodyB._mtvTotal, mtv, tmp ); + bodyB._mtvTotal.vadd( tmp ); } else if ( fixedB ){ - // extract bodies - bodyA.state.pos.vsub( mtv ); - bodyA.state.old.pos.vsub( mtv ); + clampMTV( bodyA._mtvTotal, mtv.negate(), tmp ); + bodyA._mtvTotal.vadd( tmp ); + mtv.negate(); } else { - // extract bodies - mtv.mult( 0.5 ); - bodyA.state.pos.vsub( mtv ); - bodyA.state.old.pos.vsub( mtv ); - bodyB.state.pos.vadd( mtv ); - bodyB.state.old.pos.vadd( mtv ); + ratio = 0.5; //bodyA.mass / ( bodyA.mass + bodyB.mass ); + mtv.mult( ratio ); + clampMTV( bodyB._mtvTotal, mtv, tmp ); + bodyB._mtvTotal.vadd( tmp ); + + mtv.clone( mtrans ).mult( ratio - 1 ); + clampMTV( bodyA._mtvTotal, mtv, tmp ); + bodyA._mtvTotal.vadd( tmp ); + } } @@ -7842,6 +7899,14 @@ Physics.behavior('body-impulse-response', function( parent ){ scratch.done(); }, + // internal + _pushUniq: function( body ){ + var idx = Physics.util.sortedIndex( this._bodyList, body, getUid ); + if ( this._bodyList[ idx ] !== body ){ + this._bodyList.splice( idx, 0, body ); + } + }, + /** internal * BodyImpulseResponseBehavior#respond( data ) * - data (Object): event data @@ -7852,12 +7917,22 @@ Physics.behavior('body-impulse-response', function( parent ){ var self = this ,col - ,collisions = Physics.util.shuffle(data.collisions) + ,collisions = data.collisions// Physics.util.shuffle(data.collisions) + ,i,l,b ; - for ( var i = 0, l = collisions.length; i < l; ++i ){ + for ( i = 0, l = collisions.length; i < l; ++i ){ col = collisions[ i ]; + // add bodies to list for later + this._pushUniq( col.bodyA ); + this._pushUniq( col.bodyB ); + // ensure they have mtv stat vectors + col.bodyA._mtvTotal = col.bodyA._mtvTotal || new Physics.vector(); + col.bodyB._mtvTotal = col.bodyB._mtvTotal || new Physics.vector(); + col.bodyA._oldmtvTotal = col.bodyA._oldmtvTotal || new Physics.vector(); + col.bodyB._oldmtvTotal = col.bodyB._oldmtvTotal || new Physics.vector(); + self.collideBodies( col.bodyA, col.bodyB, @@ -7867,6 +7942,24 @@ Physics.behavior('body-impulse-response', function( parent ){ col.collidedPreviously ); } + + // apply mtv vectors from the average mtv vector + for ( i = 0, l = this._bodyList.length; i < l; ++i ){ + b = this._bodyList.pop(); + // clampMTV( b._oldmtvTotal, b._mtvTotal, b._mtvTotal ); + + if ( b._mtvTotal.normSq() < this.options.mtvThreshold ){ + b._mtvTotal.mult( this.options.bodyExtractDropoff ); + } else if ( this.options.forceWakeupAboveOverlapThreshold ) { + // wake up bodies if necessary + b.sleep( false ); + } + + b.state.pos.vadd( b._mtvTotal ); + b.state.old.pos.vadd( b._mtvTotal ); + b._oldmtvTotal.swap( b._mtvTotal ); + b._mtvTotal.zero(); + } } }; }); @@ -8573,7 +8666,7 @@ Physics.behavior('interactive', function( parent ){ // --- // inside: src/behaviors/newtonian.js -/** +/** * class NewtonianBehavior < Behavior * * `Physics.behavior('newtonian')`. @@ -8611,42 +8704,95 @@ Physics.behavior('newtonian', function( parent ){ }); this.options( options ); }, - + + calcPotential: function( posA, posB, out ){ + + var strength = this.options.strength + ,minDistSq = this._minDistSq + ,maxDistSq = this._maxDistSq + ,normsq + ,g + ,pos + ; + + pos = out || new Physics.vector(); + + // clone the position + pos.clone( posB ).vsub( posA ); + // get the square distance + normsq = pos.normSq(); + + if (normsq > minDistSq && normsq < maxDistSq){ + + g = strength / normsq; + return pos.normalize().mult( g ); + } + + return pos.zero(); + }, + // extended behave: function( data ){ var bodies = this.getTargets() ,body ,other - ,strength = this.options.strength - ,minDistSq = this._minDistSq - ,maxDistSq = this._maxDistSq ,scratch = Physics.scratchpad() - ,pos = scratch.vector() - ,normsq - ,g + ,potential = scratch.vector() + ,comp + ,bodyA + ,bodyB + ,posA = scratch.vector() + ,posB = scratch.vector() + ,i, j, k, m, l, ll, lll ; - for ( var j = 0, l = bodies.length; j < l; j++ ){ - + for ( j = 0, l = bodies.length; j < l; j++ ){ + body = bodies[ j ]; - for ( var i = j + 1; i < l; i++ ){ - + for ( i = j + 1; i < l; i++ ){ + other = bodies[ i ]; - // clone the position - pos.clone( other.state.pos ); - pos.vsub( body.state.pos ); - // get the square distance - normsq = pos.normSq(); - if (normsq > minDistSq && normsq < maxDistSq){ + if ( body.name === 'compound' ){ + comp = body; + } else if ( other.name === 'compound' ){ + comp = other; + other = body; + } - g = strength / normsq; + if ( comp ){ + if ( other.name === 'compound' ){ + for ( k = 0, ll = comp.children.length; k < ll; k++ ){ + bodyA = comp.children[ k ]; + comp.toWorldCoords( posA.clone( bodyA.state.pos ).vadd( comp.offset ) ); + for ( m = 0, lll = other.children.length; m < lll; m++ ){ + bodyB = other.children[ m ]; + other.toWorldCoords( posB.clone( bodyB.state.pos ).vadd( other.offset ) ); + this.calcPotential( posA, posB, potential ); + comp.accelerate( potential.mult( bodyB.mass ) ); + other.accelerate( potential.mult( bodyA.mass/bodyB.mass ).negate() ); + } + } + } else { + for ( k = 0, ll = comp.children.length; k < ll; k++ ){ + bodyA = comp.children[ k ]; + comp.toWorldCoords( posA.clone( bodyA.state.pos ).vadd( comp.offset ) ); + this.calcPotential( posA, other.state.pos, potential ); + comp.accelerate( potential.mult( other.mass ) ); + other.accelerate( potential.mult( bodyA.mass/other.mass ).negate() ); + } + } - body.accelerate( pos.normalize().mult( g * other.mass ) ); - other.accelerate( pos.mult( body.mass/other.mass ).negate() ); + } else { + + this.calcPotential( body.state.pos, other.state.pos, potential ); + body.accelerate( potential.mult( other.mass ) ); + other.accelerate( potential.mult( body.mass/other.mass ).negate() ); } + + comp = null; } } @@ -11208,7 +11354,9 @@ Physics.renderer('dom', function( proto ){ * strokeStyle: '0xE8900C', * lineWidth: 3, * fillStyle: '0xD5DE4C', - * angleIndicator: '0xE8900C' + * angleIndicator: '0xE8900C', + * strokeAlpha: 1, + * fillAlpha: 1 * }, * * 'convex-polygon' : { @@ -11290,6 +11438,7 @@ Physics.renderer('pixi', function( parent ){ fillStyle: colors.blue, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 }, @@ -11299,6 +11448,7 @@ Physics.renderer('pixi', function( parent ){ fillStyle: colors.violet, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 }, @@ -11308,6 +11458,7 @@ Physics.renderer('pixi', function( parent ){ fillStyle: colors.violet, angleIndicator: colors.white, fillAlpha: 1, + strokeAlpha: 1, alpha: 1 } } @@ -11501,14 +11652,14 @@ Physics.renderer('pixi', function( parent ){ if ( styles.fillStyle && styles.fillStyle !== 'transparent' ){ graphics.beginFill( styles.fillStyle ); - graphics.fillAlpha = styles.fillAlpha || 1; + graphics.fillAlpha = styles.fillAlpha !== undefined ? styles.fillAlpha : 1; } else { graphics.beginFill(); graphics.fillAlpha = 0; } - graphics.lineStyle( styles.lineWidth || 0, styles.strokeStyle ); - graphics.alpha = styles.alpha || 1; + graphics.lineStyle( styles.lineWidth || 0, styles.strokeStyle, styles.strokeAlpha !== undefined ? styles.strokeAlpha : 1 ); + graphics.alpha = styles.alpha !== undefined ? styles.alpha : 1; } else { @@ -11697,6 +11848,9 @@ Physics.renderer('pixi', function( parent ){ view.lineStyle( styles.lineWidth, styles.angleIndicator ); view.moveTo( 0, 0 ); view.lineTo( hw, 0 ); + } + + if ( name !== 'compound' ){ view.cacheAsBitmap = true; }