mirror of
https://github.com/liabru/matter-js.git
synced 2024-11-30 10:20:52 -05:00
190 lines
5.8 KiB
JavaScript
190 lines
5.8 KiB
JavaScript
/**
|
|
* The `Matter.Detector` module contains methods for efficiently detecting collisions between a list of bodies using a broadphase algorithm.
|
|
*
|
|
* @class Detector
|
|
*/
|
|
|
|
var Detector = {};
|
|
|
|
module.exports = Detector;
|
|
|
|
var Common = require('../core/Common');
|
|
var Collision = require('./Collision');
|
|
|
|
(function() {
|
|
|
|
/**
|
|
* Creates a new collision detector.
|
|
* @method create
|
|
* @param {} options
|
|
* @return {detector} A new collision detector
|
|
*/
|
|
Detector.create = function(options) {
|
|
var defaults = {
|
|
bodies: [],
|
|
pairs: null
|
|
};
|
|
|
|
return Common.extend(defaults, options);
|
|
};
|
|
|
|
/**
|
|
* Sets the list of bodies in the detector.
|
|
* @method setBodies
|
|
* @param {detector} detector
|
|
* @param {body[]} bodies
|
|
*/
|
|
Detector.setBodies = function(detector, bodies) {
|
|
detector.bodies = bodies.slice(0);
|
|
};
|
|
|
|
/**
|
|
* Clears the detector including its list of bodies.
|
|
* @method clear
|
|
* @param {detector} detector
|
|
*/
|
|
Detector.clear = function(detector) {
|
|
detector.bodies = [];
|
|
};
|
|
|
|
/**
|
|
* Efficiently finds all collisions among all the bodies in `detector.bodies` using a broadphase algorithm.
|
|
*
|
|
* _Note:_ The specific ordering of collisions returned is not guaranteed between releases and may change for performance reasons.
|
|
* If a specific ordering is required then apply a sort to the resulting array.
|
|
* @method collisions
|
|
* @param {detector} detector
|
|
* @return {collision[]} collisions
|
|
*/
|
|
Detector.collisions = function(detector) {
|
|
var collisions = [],
|
|
pairs = detector.pairs,
|
|
bodies = detector.bodies,
|
|
bodiesLength = bodies.length,
|
|
canCollide = Detector.canCollide,
|
|
collides = Collision.collides,
|
|
i,
|
|
j;
|
|
|
|
bodies.sort(Detector._compareBoundsX);
|
|
|
|
for (i = 0; i < bodiesLength; i++) {
|
|
var bodyA = bodies[i],
|
|
boundsA = bodyA.bounds,
|
|
boundXMax = bodyA.bounds.max.x,
|
|
boundYMax = bodyA.bounds.max.y,
|
|
boundYMin = bodyA.bounds.min.y,
|
|
bodyAStatic = bodyA.isStatic || bodyA.isSleeping,
|
|
partsALength = bodyA.parts.length,
|
|
partsASingle = partsALength === 1;
|
|
|
|
for (j = i + 1; j < bodiesLength; j++) {
|
|
var bodyB = bodies[j],
|
|
boundsB = bodyB.bounds;
|
|
|
|
if (boundsB.min.x > boundXMax) {
|
|
break;
|
|
}
|
|
|
|
if (boundYMax < boundsB.min.y || boundYMin > boundsB.max.y) {
|
|
continue;
|
|
}
|
|
|
|
if (bodyAStatic && (bodyB.isStatic || bodyB.isSleeping)) {
|
|
continue;
|
|
}
|
|
|
|
if (!canCollide(bodyA.collisionFilter, bodyB.collisionFilter)) {
|
|
continue;
|
|
}
|
|
|
|
var partsBLength = bodyB.parts.length;
|
|
|
|
if (partsASingle && partsBLength === 1) {
|
|
var collision = collides(bodyA, bodyB, pairs);
|
|
|
|
if (collision) {
|
|
collisions.push(collision);
|
|
}
|
|
} else {
|
|
var partsAStart = partsALength > 1 ? 1 : 0,
|
|
partsBStart = partsBLength > 1 ? 1 : 0;
|
|
|
|
for (var k = partsAStart; k < partsALength; k++) {
|
|
var partA = bodyA.parts[k],
|
|
boundsA = partA.bounds;
|
|
|
|
for (var z = partsBStart; z < partsBLength; z++) {
|
|
var partB = bodyB.parts[z],
|
|
boundsB = partB.bounds;
|
|
|
|
if (boundsA.min.x > boundsB.max.x || boundsA.max.x < boundsB.min.x
|
|
|| boundsA.max.y < boundsB.min.y || boundsA.min.y > boundsB.max.y) {
|
|
continue;
|
|
}
|
|
|
|
var collision = collides(partA, partB, pairs);
|
|
|
|
if (collision) {
|
|
collisions.push(collision);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return collisions;
|
|
};
|
|
|
|
/**
|
|
* Returns `true` if both supplied collision filters will allow a collision to occur.
|
|
* See `body.collisionFilter` for more information.
|
|
* @method canCollide
|
|
* @param {} filterA
|
|
* @param {} filterB
|
|
* @return {bool} `true` if collision can occur
|
|
*/
|
|
Detector.canCollide = function(filterA, filterB) {
|
|
if (filterA.group === filterB.group && filterA.group !== 0)
|
|
return filterA.group > 0;
|
|
|
|
return (filterA.mask & filterB.category) !== 0 && (filterB.mask & filterA.category) !== 0;
|
|
};
|
|
|
|
/**
|
|
* The comparison function used in the broadphase algorithm.
|
|
* Returns the signed delta of the bodies bounds on the x-axis.
|
|
* @private
|
|
* @method _sortCompare
|
|
* @param {body} bodyA
|
|
* @param {body} bodyB
|
|
* @return {number} The signed delta used for sorting
|
|
*/
|
|
Detector._compareBoundsX = function(bodyA, bodyB) {
|
|
return bodyA.bounds.min.x - bodyB.bounds.min.x;
|
|
};
|
|
|
|
/*
|
|
*
|
|
* Properties Documentation
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* The array of `Matter.Body` between which the detector finds collisions.
|
|
*
|
|
* _Note:_ The order of bodies in this array _is not fixed_ and will be continually managed by the detector.
|
|
* @property bodies
|
|
* @type body[]
|
|
* @default []
|
|
*/
|
|
|
|
/**
|
|
* Optional. A `Matter.Pairs` object from which previous collision objects may be reused. Intended for internal `Matter.Engine` usage.
|
|
* @property pairs
|
|
* @type {pairs|null}
|
|
* @default null
|
|
*/
|
|
|
|
})();
|