diff --git a/src/collision/Collision.js b/src/collision/Collision.js index 1f24db9..58ae8f7 100644 --- a/src/collision/Collision.js +++ b/src/collision/Collision.js @@ -47,7 +47,8 @@ var Pair = require('./Pair'); normal: { x: 0, y: 0 }, tangent: { x: 0, y: 0 }, penetration: { x: 0, y: 0 }, - supports: [] + supports: [null, null], + supportCount: 0 }; }; @@ -152,10 +153,8 @@ var Pair = require('./Pair'); supports[supportCount++] = supportsB[0]; } - // update supports array size if changed - if (supports.length !== supportCount) { - supports.length = supportCount; - } + // update support count + collision.supportCount = supportCount; return collision; }; @@ -374,6 +373,10 @@ var Pair = require('./Pair'); /** * An array of body vertices that represent the support points in the collision. + * + * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active. + * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports. + * * These are the deepest vertices (along the collision normal) of each body that are contained by the other body's vertices. * * @property supports @@ -381,4 +384,15 @@ var Pair = require('./Pair'); * @default [] */ + /** + * The number of active supports for this collision found in `collision.supports`. + * + * _Note:_ Only the first `collision.supportCount` items of `collision.supports` are active. + * Therefore use `collision.supportCount` instead of `collision.supports.length` when iterating the active supports. + * + * @property supportCount + * @type number + * @default 0 + */ + })(); diff --git a/src/collision/Contact.js b/src/collision/Contact.js index 56f16cc..5ec9f0b 100644 --- a/src/collision/Contact.js +++ b/src/collision/Contact.js @@ -13,7 +13,7 @@ module.exports = Contact; /** * Creates a new contact. * @method create - * @param {vertex} vertex + * @param {vertex} [vertex] * @return {contact} A new contact */ Contact.create = function(vertex) { diff --git a/src/collision/Pair.js b/src/collision/Pair.js index b4ae5bb..72c54f4 100644 --- a/src/collision/Pair.js +++ b/src/collision/Pair.js @@ -28,8 +28,8 @@ var Contact = require('./Contact'); bodyA: bodyA, bodyB: bodyB, collision: collision, - contacts: [], - activeContacts: [], + contacts: [Contact.create(), Contact.create()], + contactCount: 0, separation: 0, isActive: true, confirmedActive: true, @@ -56,12 +56,11 @@ var Contact = require('./Contact'); * @param {number} timestamp */ Pair.update = function(pair, collision, timestamp) { - var contacts = pair.contacts, - supports = collision.supports, - activeContacts = pair.activeContacts, + var supports = collision.supports, + supportCount = collision.supportCount, + contacts = pair.contacts, parentA = collision.parentA, - parentB = collision.parentB, - parentAVerticesLength = parentA.vertices.length; + parentB = collision.parentB; pair.isActive = true; pair.timeUpdated = timestamp; @@ -73,27 +72,31 @@ var Contact = require('./Contact'); pair.restitution = parentA.restitution > parentB.restitution ? parentA.restitution : parentB.restitution; pair.slop = parentA.slop > parentB.slop ? parentA.slop : parentB.slop; + pair.contactCount = supportCount; collision.pair = pair; - var activeContactIndex = 0, - supportsLength = supports.length; - - for (var i = 0; i < supportsLength; i++) { - var support = supports[i], - contactId = support.body === parentA ? support.index : parentAVerticesLength + support.index, - contact = contacts[contactId]; + var support = supports[0], + contact = contacts[0]; - if (contact) { - activeContacts[activeContactIndex++] = contact; - } else { - contact = Contact.create(support); - activeContacts[activeContactIndex++] = contact; - contacts[contactId] = contact; - } + // reset first contact if support changed + if (contact.vertex !== support) { + contact.vertex = support; + contact.normalImpulse = 0; + contact.tangentImpulse = 0; } - if (activeContacts.length !== activeContactIndex) { - activeContacts.length = activeContactIndex; + if (supportCount < 2) { + return; + } + + support = supports[1]; + contact = contacts[1]; + + // reset second contact if support changed + if (contact.vertex !== support) { + contact.vertex = support; + contact.normalImpulse = 0; + contact.tangentImpulse = 0; } }; @@ -110,7 +113,7 @@ var Contact = require('./Contact'); pair.timeUpdated = timestamp; } else { pair.isActive = false; - pair.activeContacts.length = 0; + pair.contactCount = 0; } }; diff --git a/src/collision/Resolver.js b/src/collision/Resolver.js index 9fd7d39..0335902 100644 --- a/src/collision/Resolver.js +++ b/src/collision/Resolver.js @@ -29,7 +29,7 @@ var Bounds = require('../geometry/Bounds'); Resolver.preSolvePosition = function(pairs) { var i, pair, - activeCount, + contactCount, pairsLength = pairs.length; // find total contacts on each body @@ -39,9 +39,9 @@ var Bounds = require('../geometry/Bounds'); if (!pair.isActive) continue; - activeCount = pair.activeContacts.length; - pair.collision.parentA.totalContacts += activeCount; - pair.collision.parentB.totalContacts += activeCount; + contactCount = pair.contactCount; + pair.collision.parentA.totalContacts += contactCount; + pair.collision.parentB.totalContacts += contactCount; } }; @@ -176,8 +176,8 @@ var Bounds = require('../geometry/Bounds'); if (!pair.isActive || pair.isSensor) continue; - var contacts = pair.activeContacts, - contactsLength = contacts.length, + var contacts = pair.contacts, + contactCount = pair.contactCount, collision = pair.collision, bodyA = collision.parentA, bodyB = collision.parentB, @@ -185,7 +185,7 @@ var Bounds = require('../geometry/Bounds'); tangent = collision.tangent; // resolve each contact - for (j = 0; j < contactsLength; j++) { + for (j = 0; j < contactCount; j++) { var contact = contacts[j], contactVertex = contact.vertex, normalImpulse = contact.normalImpulse, @@ -254,9 +254,9 @@ var Bounds = require('../geometry/Bounds'); normalY = collision.normal.y, tangentX = collision.tangent.x, tangentY = collision.tangent.y, - contacts = pair.activeContacts, - contactsLength = contacts.length, - contactShare = 1 / contactsLength, + contacts = pair.contacts, + contactCount = pair.contactCount, + contactShare = 1 / contactCount, inverseMassTotal = bodyA.inverseMass + bodyB.inverseMass, friction = pair.friction * pair.frictionStatic * frictionNormalMultiplier; @@ -269,7 +269,7 @@ var Bounds = require('../geometry/Bounds'); bodyB.angularVelocity = bodyB.angle - bodyB.anglePrev; // resolve each contact - for (j = 0; j < contactsLength; j++) { + for (j = 0; j < contactCount; j++) { var contact = contacts[j], contactVertex = contact.vertex; diff --git a/src/render/Render.js b/src/render/Render.js index 1002a42..af5a833 100644 --- a/src/render/Render.js +++ b/src/render/Render.js @@ -1205,8 +1205,8 @@ var Mouse = require('../core/Mouse'); continue; collision = pair.collision; - for (j = 0; j < pair.activeContacts.length; j++) { - var contact = pair.activeContacts[j], + for (j = 0; j < pair.contactCount; j++) { + var contact = pair.contacts[j], vertex = contact.vertex; c.rect(vertex.x - 1.5, vertex.y - 1.5, 3.5, 3.5); } @@ -1230,13 +1230,13 @@ var Mouse = require('../core/Mouse'); collision = pair.collision; - if (pair.activeContacts.length > 0) { - var normalPosX = pair.activeContacts[0].vertex.x, - normalPosY = pair.activeContacts[0].vertex.y; + if (pair.contactCount > 0) { + var normalPosX = pair.contacts[0].vertex.x, + normalPosY = pair.contacts[0].vertex.y; - if (pair.activeContacts.length === 2) { - normalPosX = (pair.activeContacts[0].vertex.x + pair.activeContacts[1].vertex.x) / 2; - normalPosY = (pair.activeContacts[0].vertex.y + pair.activeContacts[1].vertex.y) / 2; + if (pair.contactCount === 2) { + normalPosX = (pair.contacts[0].vertex.x + pair.contacts[1].vertex.x) / 2; + normalPosY = (pair.contacts[0].vertex.y + pair.contacts[1].vertex.y) / 2; } if (collision.bodyB === collision.supports[0].body || collision.bodyA.isStatic === true) {