Show:

File: src/collision/Grid.js

                                /**
                                * This module has now been replaced by `Matter.Detector`.
                                *
                                * All usage should be migrated to `Matter.Detector` or another alternative.
                                * For back-compatibility purposes this module will remain for a short term and then later removed in a future release.
                                *
                                * The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures.
                                *
                                * @class Grid
                                * @deprecated
                                */
                                
                                var Grid = {};
                                
                                module.exports = Grid;
                                
                                var Pair = require('./Pair');
                                var Common = require('../core/Common');
                                var deprecated = Common.deprecated;
                                
                                (function() {
                                
                                    /**
                                     * Creates a new grid.
                                     * @deprecated replaced by Matter.Detector
                                     * @method create
                                     * @param {} options
                                     * @return {grid} A new grid
                                     */
                                    Grid.create = function(options) {
                                        var defaults = {
                                            buckets: {},
                                            pairs: {},
                                            pairsList: [],
                                            bucketWidth: 48,
                                            bucketHeight: 48
                                        };
                                
                                        return Common.extend(defaults, options);
                                    };
                                
                                    /**
                                     * The width of a single grid bucket.
                                     *
                                     * @property bucketWidth
                                     * @type number
                                     * @default 48
                                     */
                                
                                    /**
                                     * The height of a single grid bucket.
                                     *
                                     * @property bucketHeight
                                     * @type number
                                     * @default 48
                                     */
                                
                                    /**
                                     * Updates the grid.
                                     * @deprecated replaced by Matter.Detector
                                     * @method update
                                     * @param {grid} grid
                                     * @param {body[]} bodies
                                     * @param {engine} engine
                                     * @param {boolean} forceUpdate
                                     */
                                    Grid.update = function(grid, bodies, engine, forceUpdate) {
                                        var i, col, row,
                                            world = engine.world,
                                            buckets = grid.buckets,
                                            bucket,
                                            bucketId,
                                            gridChanged = false;
                                
                                        for (i = 0; i < bodies.length; i++) {
                                            var body = bodies[i];
                                
                                            if (body.isSleeping && !forceUpdate)
                                                continue;
                                
                                            // temporary back compatibility bounds check
                                            if (world.bounds && (body.bounds.max.x < world.bounds.min.x || body.bounds.min.x > world.bounds.max.x
                                                || body.bounds.max.y < world.bounds.min.y || body.bounds.min.y > world.bounds.max.y))
                                                continue;
                                
                                            var newRegion = Grid._getRegion(grid, body);
                                
                                            // if the body has changed grid region
                                            if (!body.region || newRegion.id !== body.region.id || forceUpdate) {
                                
                                                if (!body.region || forceUpdate)
                                                    body.region = newRegion;
                                
                                                var union = Grid._regionUnion(newRegion, body.region);
                                
                                                // update grid buckets affected by region change
                                                // iterate over the union of both regions
                                                for (col = union.startCol; col <= union.endCol; col++) {
                                                    for (row = union.startRow; row <= union.endRow; row++) {
                                                        bucketId = Grid._getBucketId(col, row);
                                                        bucket = buckets[bucketId];
                                
                                                        var isInsideNewRegion = (col >= newRegion.startCol && col <= newRegion.endCol
                                                                                && row >= newRegion.startRow && row <= newRegion.endRow);
                                
                                                        var isInsideOldRegion = (col >= body.region.startCol && col <= body.region.endCol
                                                                                && row >= body.region.startRow && row <= body.region.endRow);
                                
                                                        // remove from old region buckets
                                                        if (!isInsideNewRegion && isInsideOldRegion) {
                                                            if (isInsideOldRegion) {
                                                                if (bucket)
                                                                    Grid._bucketRemoveBody(grid, bucket, body);
                                                            }
                                                        }
                                
                                                        // add to new region buckets
                                                        if (body.region === newRegion || (isInsideNewRegion && !isInsideOldRegion) || forceUpdate) {
                                                            if (!bucket)
                                                                bucket = Grid._createBucket(buckets, bucketId);
                                                            Grid._bucketAddBody(grid, bucket, body);
                                                        }
                                                    }
                                                }
                                
                                                // set the new region
                                                body.region = newRegion;
                                
                                                // flag changes so we can update pairs
                                                gridChanged = true;
                                            }
                                        }
                                
                                        // update pairs list only if pairs changed (i.e. a body changed region)
                                        if (gridChanged)
                                            grid.pairsList = Grid._createActivePairsList(grid);
                                    };
                                
                                    deprecated(Grid, 'update', 'Grid.update ➤ replaced by Matter.Detector');
                                
                                    /**
                                     * Clears the grid.
                                     * @deprecated replaced by Matter.Detector
                                     * @method clear
                                     * @param {grid} grid
                                     */
                                    Grid.clear = function(grid) {
                                        grid.buckets = {};
                                        grid.pairs = {};
                                        grid.pairsList = [];
                                    };
                                
                                    deprecated(Grid, 'clear', 'Grid.clear ➤ replaced by Matter.Detector');
                                
                                    /**
                                     * Finds the union of two regions.
                                     * @method _regionUnion
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} regionA
                                     * @param {} regionB
                                     * @return {} region
                                     */
                                    Grid._regionUnion = function(regionA, regionB) {
                                        var startCol = Math.min(regionA.startCol, regionB.startCol),
                                            endCol = Math.max(regionA.endCol, regionB.endCol),
                                            startRow = Math.min(regionA.startRow, regionB.startRow),
                                            endRow = Math.max(regionA.endRow, regionB.endRow);
                                
                                        return Grid._createRegion(startCol, endCol, startRow, endRow);
                                    };
                                
                                    /**
                                     * Gets the region a given body falls in for a given grid.
                                     * @method _getRegion
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} grid
                                     * @param {} body
                                     * @return {} region
                                     */
                                    Grid._getRegion = function(grid, body) {
                                        var bounds = body.bounds,
                                            startCol = Math.floor(bounds.min.x / grid.bucketWidth),
                                            endCol = Math.floor(bounds.max.x / grid.bucketWidth),
                                            startRow = Math.floor(bounds.min.y / grid.bucketHeight),
                                            endRow = Math.floor(bounds.max.y / grid.bucketHeight);
                                
                                        return Grid._createRegion(startCol, endCol, startRow, endRow);
                                    };
                                
                                    /**
                                     * Creates a region.
                                     * @method _createRegion
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} startCol
                                     * @param {} endCol
                                     * @param {} startRow
                                     * @param {} endRow
                                     * @return {} region
                                     */
                                    Grid._createRegion = function(startCol, endCol, startRow, endRow) {
                                        return { 
                                            id: startCol + ',' + endCol + ',' + startRow + ',' + endRow,
                                            startCol: startCol, 
                                            endCol: endCol, 
                                            startRow: startRow, 
                                            endRow: endRow 
                                        };
                                    };
                                
                                    /**
                                     * Gets the bucket id at the given position.
                                     * @method _getBucketId
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} column
                                     * @param {} row
                                     * @return {string} bucket id
                                     */
                                    Grid._getBucketId = function(column, row) {
                                        return 'C' + column + 'R' + row;
                                    };
                                
                                    /**
                                     * Creates a bucket.
                                     * @method _createBucket
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} buckets
                                     * @param {} bucketId
                                     * @return {} bucket
                                     */
                                    Grid._createBucket = function(buckets, bucketId) {
                                        var bucket = buckets[bucketId] = [];
                                        return bucket;
                                    };
                                
                                    /**
                                     * Adds a body to a bucket.
                                     * @method _bucketAddBody
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} grid
                                     * @param {} bucket
                                     * @param {} body
                                     */
                                    Grid._bucketAddBody = function(grid, bucket, body) {
                                        var gridPairs = grid.pairs,
                                            pairId = Pair.id,
                                            bucketLength = bucket.length,
                                            i;
                                
                                        // add new pairs
                                        for (i = 0; i < bucketLength; i++) {
                                            var bodyB = bucket[i];
                                
                                            if (body.id === bodyB.id || (body.isStatic && bodyB.isStatic))
                                                continue;
                                
                                            // keep track of the number of buckets the pair exists in
                                            // important for Grid.update to work
                                            var id = pairId(body, bodyB),
                                                pair = gridPairs[id];
                                
                                            if (pair) {
                                                pair[2] += 1;
                                            } else {
                                                gridPairs[id] = [body, bodyB, 1];
                                            }
                                        }
                                
                                        // add to bodies (after pairs, otherwise pairs with self)
                                        bucket.push(body);
                                    };
                                
                                    /**
                                     * Removes a body from a bucket.
                                     * @method _bucketRemoveBody
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} grid
                                     * @param {} bucket
                                     * @param {} body
                                     */
                                    Grid._bucketRemoveBody = function(grid, bucket, body) {
                                        var gridPairs = grid.pairs,
                                            pairId = Pair.id,
                                            i;
                                
                                        // remove from bucket
                                        bucket.splice(Common.indexOf(bucket, body), 1);
                                
                                        var bucketLength = bucket.length;
                                
                                        // update pair counts
                                        for (i = 0; i < bucketLength; i++) {
                                            // keep track of the number of buckets the pair exists in
                                            // important for _createActivePairsList to work
                                            var pair = gridPairs[pairId(body, bucket[i])];
                                
                                            if (pair)
                                                pair[2] -= 1;
                                        }
                                    };
                                
                                    /**
                                     * Generates a list of the active pairs in the grid.
                                     * @method _createActivePairsList
                                     * @deprecated replaced by Matter.Detector
                                     * @private
                                     * @param {} grid
                                     * @return [] pairs
                                     */
                                    Grid._createActivePairsList = function(grid) {
                                        var pair,
                                            gridPairs = grid.pairs,
                                            pairKeys = Common.keys(gridPairs),
                                            pairKeysLength = pairKeys.length,
                                            pairs = [],
                                            k;
                                
                                        // iterate over grid.pairs
                                        for (k = 0; k < pairKeysLength; k++) {
                                            pair = gridPairs[pairKeys[k]];
                                
                                            // if pair exists in at least one bucket
                                            // it is a pair that needs further collision testing so push it
                                            if (pair[2] > 0) {
                                                pairs.push(pair);
                                            } else {
                                                delete gridPairs[pairKeys[k]];
                                            }
                                        }
                                
                                        return pairs;
                                    };
                                    
                                })();