1)碰撞检测有两种常用方法:将所有物件两两测试,当物件数量少的时候,用这种方式既简单又快速; 基于网格检测,先将整个区域划分成格子,再基于格子检测,遍历所有格式,先检查本格中的所有物件,再将本格和相邻格中的物件一一检测,当物件数量多时,需要用这种方式进行检测,将大大减少检测数量;
2)划分格式时,应确保格子的尺寸比“最大的物件”尺寸还要大,必须能保证格式一定能将物件包住;
3)每个格子在检测时,只用检测“右边”、”左下边“、”下边“、”右下边“这四个格子就行,不用检测周边的八个格子;
4) 用一维数组来保存格子,通过在索引上做文章来识别它以属于第几行,这样能提高性能。
==========================================
private function checkGrid(): void
{
for(var i: int=0; i < _grid.length; i++)
{
for(var j: int=0; j < _grid[ i ].length; j++)
{
// 检测第一个格子内的对象间是否发生碰撞
checkOneCell(i, j);
checkTwoCells(i, j, i+1, j); // 右边的格子
checkTwoCells(i, j, i-1, j+1); // 左下角的格子
checkTwoCells(i, j, i, j+1); // 下边的格子
checkTwoCells(i, j, i+1, j+1); // 右下角的格子
}
}
}
private function checkOneCell(x: int, y: int): void
{
// 检测当前格子内所有的对象
var cell:Array = _grid[ x ][ y ] as Array;
for(var i: int=0; i < cell.length-1; i++)
{
var ballA: Ball = cell[ i ] as Ball;
for(var j: int=i+1; j < cell.length; j++)
{
var ballB: Ball = cell[ j ] as Ball;
checkCollision(ballA, ballB);
}
}
}
private function checkTwoCells(x1: int, y1: int, x2: int, y2: int): void
{
// 确保要检测的格子存在
if(x2 < 0) return;
if(x2 >= _grid.length) return;
if(y2 >= _grid[ x2 ].length) return;
var cell0:Array = _grid[ x1 ][ y1 ] as Array;
var cell1:Array = _grid[ x2 ][ y2 ] as Array;
// 检测当前格子和邻接格子内所有的对象
for(var i: int=0; i < cell0.length; i++)
{
var ballA: Ball = cell0[ i ] as Ball;
for(var j: int=0; j < cell1.length; j++)
{
var ballB: Ball = cell1[ j ] as Ball;
checkCollision(ballA, ballB);
}
}
}
private function checkCollision(ballA: Ball, ballB: Ball):void
{
// 判断距离的碰撞检测
_numChecks++;
var dx: Number = ballB.x - ballA.x;
var dy: Number = ballB.y - ballA.y;
var dist: Number = Math.sqrt(dx * dx + dy * dy);
if(dist < ballA.radius + ballB.radius)
{
ballA.color = 0xff0000;
ballB.color = 0xff0000;
}
}