UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

204 lines (170 loc) 6.42 kB
/** * 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: [], collisions: [], 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 = []; detector.collisions = []; }; /** * 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 pairs = detector.pairs, bodies = detector.bodies, bodiesLength = bodies.length, canCollide = Detector.canCollide, collides = Collision.collides, collisions = detector.collisions, collisionIndex = 0, 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[collisionIndex++] = 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[collisionIndex++] = collision; } } } } } } if (collisions.length !== collisionIndex) { collisions.length = collisionIndex; } 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 [] */ /** * The array of `Matter.Collision` found in the last call to `Detector.collisions` on this detector. * @property collisions * @type collision[] * @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 */ })();