diff --git a/build/p2.js b/build/p2.js index b862ac0e..8835ae42 100644 --- a/build/p2.js +++ b/build/p2.js @@ -2025,6 +2025,7 @@ Narrowphase.prototype.createContactEquation = function(bodyA,bodyB,shapeA,shapeB c.shapeB = shapeB; c.restitution = this.restitution; c.firstImpact = !this.collidedLastStep(bodyA,bodyB); + c.enabled = true; if(bodyA.allowSleep && (bodyA.motionState & Body.DYNAMIC) && !(bodyB.motionState & Body.STATIC || bodyB.sleepState === Body.SLEEPY)) bodyA.wakeUp(); @@ -2050,6 +2051,7 @@ Narrowphase.prototype.createFrictionEquation = function(bodyA,bodyB,shapeA,shape c.setSlipForce(this.slipForce); c.frictionCoefficient = this.frictionCoefficient; c.relativeVelocity = this.surfaceVelocity; + c.enabled = true; return c; }; @@ -2082,9 +2084,12 @@ Narrowphase.prototype.createFrictionFromContact = function(c){ * @todo Implement me! */ Narrowphase.prototype[Shape.LINE | Shape.CONVEX] = -Narrowphase.prototype.convexLine = function(bi,si,xi,ai, bj,sj,xj,aj){ +Narrowphase.prototype.convexLine = function(bi,si,xi,ai, bj,sj,xj,aj, justTest){ // TODO - return 0; + if(justTest) + return false; + else + return 0; }; /** @@ -2101,9 +2106,12 @@ Narrowphase.prototype.convexLine = function(bi,si,xi,ai, bj,sj,xj,aj){ * @todo Implement me! */ Narrowphase.prototype[Shape.LINE | Shape.RECTANGLE] = -Narrowphase.prototype.lineRectangle = function(bi,si,xi,ai, bj,sj,xj,aj){ +Narrowphase.prototype.lineRectangle = function(bi,si,xi,ai, bj,sj,xj,aj, justTest){ // TODO - return 0; + if(justTest) + return false; + else + return 0; }; /** @@ -2120,9 +2128,12 @@ Narrowphase.prototype.lineRectangle = function(bi,si,xi,ai, bj,sj,xj,aj){ * @todo Implement me! */ Narrowphase.prototype[Shape.CAPSULE | Shape.RECTANGLE] = -Narrowphase.prototype.rectangleCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ +Narrowphase.prototype.rectangleCapsule = function(bi,si,xi,ai, bj,sj,xj,aj, justTest){ // TODO - return 0; + if(justTest) + return false; + else + return 0; }; /** @@ -2139,9 +2150,12 @@ Narrowphase.prototype.rectangleCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ * @todo Implement me! */ Narrowphase.prototype[Shape.CAPSULE | Shape.CONVEX] = -Narrowphase.prototype.convexCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ +Narrowphase.prototype.convexCapsule = function(bi,si,xi,ai, bj,sj,xj,aj, justTest){ // TODO - return 0; + if(justTest) + return false; + else + return 0; }; /** @@ -2158,9 +2172,12 @@ Narrowphase.prototype.convexCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ * @todo Implement me! */ Narrowphase.prototype[Shape.CAPSULE | Shape.LINE] = -Narrowphase.prototype.lineCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ +Narrowphase.prototype.lineCapsule = function(bi,si,xi,ai, bj,sj,xj,aj, justTest){ // TODO - return 0; + if(justTest) + return false; + else + return 0; }; /** @@ -2177,9 +2194,12 @@ Narrowphase.prototype.lineCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ * @todo Implement me! */ Narrowphase.prototype[Shape.CAPSULE | Shape.CAPSULE] = -Narrowphase.prototype.capsuleCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ +Narrowphase.prototype.capsuleCapsule = function(bi,si,xi,ai, bj,sj,xj,aj, justTest){ // TODO - return 0; + if(justTest) + return false; + else + return 0; }; /** @@ -2196,9 +2216,12 @@ Narrowphase.prototype.capsuleCapsule = function(bi,si,xi,ai, bj,sj,xj,aj){ * @todo Implement me! */ Narrowphase.prototype[Shape.LINE | Shape.LINE] = -Narrowphase.prototype.lineLine = function(bi,si,xi,ai, bj,sj,xj,aj){ +Narrowphase.prototype.lineLine = function(bi,si,xi,ai, bj,sj,xj,aj, justTest){ // TODO - return 0; + if(justTest) + return false; + else + return 0; }; /** @@ -2215,7 +2238,7 @@ Narrowphase.prototype.lineLine = function(bi,si,xi,ai, bj,sj,xj,aj){ */ Narrowphase.prototype[Shape.PLANE | Shape.LINE] = Narrowphase.prototype.planeLine = function(planeBody, planeShape, planeOffset, planeAngle, - lineBody, lineShape, lineOffset, lineAngle){ + lineBody, lineShape, lineOffset, lineAngle, justTest){ var worldVertex0 = tmp1, worldVertex1 = tmp2, worldVertex01 = tmp3, @@ -2263,6 +2286,9 @@ Narrowphase.prototype.planeLine = function(planeBody, planeShape, planeOffset, p if(d < 0){ + if(justTest) + return true; + var c = this.createContactEquation(planeBody,lineBody,planeShape,lineShape); numContacts++; @@ -2391,7 +2417,7 @@ Narrowphase.prototype.circleLine = function(bi,si,xi,ai, bj,sj,xj,aj, justTest, if(pos > pos0 && pos < pos1){ // We got contact! - if(justTest) return 1; + if(justTest) return true; var c = this.createContactEquation(circleBody,lineBody,si,sj); @@ -2428,7 +2454,7 @@ Narrowphase.prototype.circleLine = function(bi,si,xi,ai, bj,sj,xj,aj, justTest, if(vec2.squaredLength(dist) < (circleRadius+lineRadius)*(circleRadius+lineRadius)){ - if(justTest) return 1; + if(justTest) return true; var c = this.createContactEquation(circleBody,lineBody,si,sj); @@ -2603,6 +2629,10 @@ Narrowphase.prototype.circleConvex = function( bi,si,xi,ai, bj,sj,xj,aj, justTe } if(found){ + + if(justTest) + return true; + var c = this.createContactEquation(circleBody,convexBody,si,sj); vec2.sub(c.ni, minCandidate, circleOffset) vec2.normalize(c.ni, c.ni); @@ -2657,7 +2687,7 @@ Narrowphase.prototype.circleConvex = function( bi,si,xi,ai, bj,sj,xj,aj, justTe sub(dist, worldVertex, circleOffset); if(vec2.squaredLength(dist) < circleRadius*circleRadius){ - if(justTest) return 1; + if(justTest) return true; var c = this.createContactEquation(circleBody,convexBody,si,sj); @@ -2778,6 +2808,8 @@ Narrowphase.prototype.particleConvex = function( bi,si,xi,ai, bj,sj,xj,aj, just if(!pointInConvex(particleOffset,convexShape,convexOffset,convexAngle)) return 0; + if(justTest) return true; + // Check edges first var lastCross = null; for(var i=0; i!==verts.length+1; i++){ @@ -2895,11 +2927,10 @@ Narrowphase.prototype.circleCircle = function( bi,si,xi,ai, bj,sj,xj,aj, justTe sub(dist,xi,xj); var r = si.radius + sj.radius; - if(vec2.squaredLength(dist) > r*r){ + if(vec2.squaredLength(dist) > r*r) return 0; - } - if(justTest) return 1; + if(justTest) return true; var c = this.createContactEquation(bodyA,bodyB,si,sj); sub(c.ni, offsetB, offsetA); @@ -2935,7 +2966,7 @@ Narrowphase.prototype.circleCircle = function( bi,si,xi,ai, bj,sj,xj,aj, justTe * @param {Number} aj */ Narrowphase.prototype[Shape.PLANE | Shape.CONVEX] = -Narrowphase.prototype.planeConvex = function( bi,si,xi,ai, bj,sj,xj,aj ){ +Narrowphase.prototype.planeConvex = function( bi,si,xi,ai, bj,sj,xj,aj, justTest ){ var convexBody = bj, convexOffset = xj, convexShape = sj, @@ -2961,6 +2992,8 @@ Narrowphase.prototype.planeConvex = function( bi,si,xi,ai, bj,sj,xj,aj ){ if(dot(dist,worldNormal) < 0){ + if(justTest) return true; + // Found vertex numReported++; @@ -3001,9 +3034,9 @@ Narrowphase.prototype.planeConvex = function( bi,si,xi,ai, bj,sj,xj,aj ){ * @method convexPlane * @deprecated Use .planeConvex() instead! */ -Narrowphase.prototype.convexPlane = function( bi,si,xi,ai, bj,sj,xj,aj ){ +Narrowphase.prototype.convexPlane = function( bi,si,xi,ai, bj,sj,xj,aj, justTest ){ console.warn("Narrowphase.prototype.convexPlane is deprecated. Use planeConvex instead!"); - return this.planeConvex( bj,sj,xj,aj, bi,si,xi,ai ); + return this.planeConvex( bj,sj,xj,aj, bi,si,xi,ai, justTest ); } /** @@ -3039,7 +3072,7 @@ Narrowphase.prototype.particlePlane = function( bi,si,xi,ai, bj,sj,xj,aj, justTe var d = dot(dist, worldNormal); if(d > 0) return 0; - if(justTest) return 1; + if(justTest) return true; var c = this.createContactEquation(planeBody,particleBody,sj,si); @@ -3086,7 +3119,7 @@ Narrowphase.prototype.circleParticle = function( bi,si,xi,ai, bj,sj,xj,aj, jus sub(dist, particleOffset, circleOffset); if(vec2.squaredLength(dist) > circleShape.radius*circleShape.radius) return 0; - if(justTest) return 1; + if(justTest) return true; var c = this.createContactEquation(circleBody,particleBody,si,sj); vec2.copy(c.ni, dist); @@ -3115,7 +3148,7 @@ var capsulePlane_tmpCircle = new Circle(1), capsulePlane_tmp3 = vec2.create(); Narrowphase.prototype[Shape.PLANE | Shape.CAPSULE] = -Narrowphase.prototype.planeCapsule = function( bi,si,xi,ai, bj,sj,xj,aj ){ +Narrowphase.prototype.planeCapsule = function( bi,si,xi,ai, bj,sj,xj,aj, justTest ){ var end1 = capsulePlane_tmp1, end2 = capsulePlane_tmp2, circle = capsulePlane_tmpCircle, @@ -3133,19 +3166,22 @@ Narrowphase.prototype.planeCapsule = function( bi,si,xi,ai, bj,sj,xj,aj ){ circle.radius = sj.radius; // Do Narrowphase as two circles - var numContacts1 = this.circlePlane(bj,circle,end1,0, bi,si,xi,ai), - numContacts2 = this.circlePlane(bj,circle,end2,0, bi,si,xi,ai); + var numContacts1 = this.circlePlane(bj,circle,end1,0, bi,si,xi,ai, justTest), + numContacts2 = this.circlePlane(bj,circle,end2,0, bi,si,xi,ai, justTest); - return numContacts1 + numContacts2; + if(justTest) + return numContacts1 || numContacts2; + else + return numContacts1 + numContacts2; }; /** * @method capsulePlane * @deprecated Use .planeCapsule() instead! */ -Narrowphase.prototype.capsulePlane = function( bi,si,xi,ai, bj,sj,xj,aj ){ +Narrowphase.prototype.capsulePlane = function( bi,si,xi,ai, bj,sj,xj,aj, justTest ){ console.warn("Narrowphase.prototype.capsulePlane() is deprecated. Use .planeCapsule() instead!"); - return this.planeCapsule( bj,sj,xj,aj, bi,si,xi,ai ); + return this.planeCapsule( bj,sj,xj,aj, bi,si,xi,ai, justTest ); } /** @@ -3160,7 +3196,7 @@ Narrowphase.prototype.capsulePlane = function( bi,si,xi,ai, bj,sj,xj,aj ){ * @param {Number} aj Extra angle to apply to the plane */ Narrowphase.prototype[Shape.CIRCLE | Shape.PLANE] = -Narrowphase.prototype.circlePlane = function( bi,si,xi,ai, bj,sj,xj,aj ){ +Narrowphase.prototype.circlePlane = function( bi,si,xi,ai, bj,sj,xj,aj, justTest ){ var circleBody = bi, circleShape = si, circleOffset = xi, // Offset from body center, rotated! @@ -3186,6 +3222,8 @@ Narrowphase.prototype.circlePlane = function( bi,si,xi,ai, bj,sj,xj,aj ){ if(d > circleShape.radius) return 0; // No overlap. Abort. + if(justTest) return true; + // Create contact var contact = this.createContactEquation(planeBody,circleBody,sj,si); @@ -3226,7 +3264,7 @@ Narrowphase.prototype.circlePlane = function( bi,si,xi,ai, bj,sj,xj,aj ){ * @param {Number} aj */ Narrowphase.prototype[Shape.CONVEX] = -Narrowphase.prototype.convexConvex = function( bi,si,xi,ai, bj,sj,xj,aj, precision ){ +Narrowphase.prototype.convexConvex = function( bi,si,xi,ai, bj,sj,xj,aj, justTest, precision ){ var sepAxis = tmp1, worldPoint = tmp2, worldPoint0 = tmp3, @@ -3312,6 +3350,8 @@ Narrowphase.prototype.convexConvex = function( bi,si,xi,ai, bj,sj,xj,aj, precis if(insideNumEdges == 3){ + if(justTest) return true; + // worldPoint was on the "inside" side of each of the 3 checked edges. // Project it to the center edge and use the projection direction as normal @@ -5242,6 +5282,12 @@ function Equation(bi,bj,minForce,maxForce){ * @property {Number} relativeVelocity */ this.relativeVelocity = 0; + + /** + * Whether this equation is enabled or not. If true, it will be added to the solver. + * @property {Boolean} enabled + */ + this.enabled = true; }; Equation.prototype.constructor = Equation; @@ -7877,7 +7923,8 @@ Line.prototype.computeAABB = function(out, position, angle){ },{"../math/vec2":33,"./Shape":44}],41:[function(require,module,exports){ -var Shape = require('./Shape'); +var Shape = require('./Shape') +, vec2 = require('../math/vec2') module.exports = Particle; @@ -7911,7 +7958,7 @@ Particle.prototype.computeAABB = function(out, position, angle){ vec2.copy(out.upperBound, position); }; -},{"./Shape":44}],42:[function(require,module,exports){ +},{"../math/vec2":33,"./Shape":44}],42:[function(require,module,exports){ var Shape = require('./Shape') , vec2 = require('../math/vec2') , Utils = require('../utils/Utils') @@ -8162,6 +8209,12 @@ function Shape(type){ */ this.area = 0; + /** + * Set to true if you want this shape to be a sensor. A sensor does not generate contacts, but it still reports contact events. This is good if you want to know if a shape is overlapping another shape, without them generating contacts. + * @property {Boolean} sensor + */ + this.sensor = false; + this.updateArea(); }; @@ -8764,7 +8817,8 @@ Solver.prototype.sortEquations = function(){ * @param {Equation} eq */ Solver.prototype.addEquation = function(eq){ - this.equations.push(eq); + if(eq.enabled) + this.equations.push(eq); }; /** @@ -8774,7 +8828,12 @@ Solver.prototype.addEquation = function(eq){ * @param {Array} eqs */ Solver.prototype.addEquations = function(eqs){ - Utils.appendArray(this.equations,eqs); + //Utils.appendArray(this.equations,eqs); + for(var i=0, N=eqs.length; i!==N; i++){ + var eq = eqs[i]; + if(eq.enabled) + this.equations.push(eq); + } }; /** @@ -9126,6 +9185,15 @@ function World(options){ */ this.enableBodySleeping = false; + /** + * Fired when two shapes starts start to touch (and create contacts). + * @event beginContact + * @param {Shape} shapeA + * @param {Shape} shapeB + * @param {Body} bodyA + * @param {Body} bodyB + * @param {Array} contactEquations + */ this.beginContactEvent = { type:"beginContact", shapeA : null, @@ -9135,10 +9203,33 @@ function World(options){ contactEquations : [], }; + /** + * Fired when two shapes stop touching. + * @event endContact + * @param {Shape} shapeA + * @param {Shape} shapeB + * @param {Body} bodyA + * @param {Body} bodyB + * @param {Array} contactEquations + */ this.endContactEvent = { type:"endContact", shapeA : null, shapeB : null, + bodyA : null, + bodyB : null, + }; + + /** + * Fired just before equations are added to the solver to be solved. Can be used to control what equations goes into the solver. + * @event preSolve + * @param {Array} contactEquations An array of contacts to be solved. + * @param {Array} frictionEquations An array of friction equations to be solved. + */ + this.preSolveEvent = { + type:"preSolve", + contactEquations:null, + frictionEquations:null, }; // For keeping track of overlapping shapes @@ -9405,6 +9496,10 @@ World.prototype.internalStep = function(dt){ this.overlappingShapesLastState = this.overlappingShapesCurrentState; this.overlappingShapesCurrentState = tmp; + var preSolveEvent = this.preSolveEvent; + preSolveEvent.contactEquations = np.contactEquations; + preSolveEvent.frictionEquations = np.frictionEquations; + this.emit(preSolveEvent); // Add contact equations to solver solver.addEquations(np.contactEquations); @@ -9539,10 +9634,11 @@ World.prototype.runNarrowphase = function(np,bi,si,xi,ai,bj,sj,xj,aj,mu,restitut var resolver = np[si.type | sj.type], numContacts = 0; if (resolver) { + var sensor = si.sensor || sj.sensor; if (si.type < sj.type) { - numContacts = resolver.call(np, bi,si,xiw,aiw, bj,sj,xjw,ajw); + numContacts = resolver.call(np, bi,si,xiw,aiw, bj,sj,xjw,ajw, sensor); } else { - numContacts = resolver.call(np, bj,sj,xjw,ajw, bi,si,xiw,aiw); + numContacts = resolver.call(np, bj,sj,xjw,ajw, bi,si,xiw,aiw, sensor); } if(numContacts){ diff --git a/examples/wip/contact1.js b/examples/wip/contact1.js index e0826be5..1e889b20 100644 --- a/examples/wip/contact1.js +++ b/examples/wip/contact1.js @@ -1,5 +1,5 @@ -var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }, false, false, { gravity: [0, 10] } ); +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }); function preload() { @@ -23,7 +23,7 @@ function create() { bg = game.add.tileSprite(0, 0, 800, 600, 'background'); bg.fixedToCamera = true; - // game.physics.gravity.y = 20; + game.physics.gravity.y = 20; game.physics.friction = 0.5;