根据世界级flash 大师Keith Peters的网格算法,我们可以将上百个小球的互相碰撞变成现实.

根据个人看法,他这种方法是将大的东西简化成小方块之间的球体检测,通过循环来布满整个stage区域.

本人理解具体的逻辑应该如下,如有不准确,还请各位指正

(1)首先根据屏幕,规定网格大小,然后通过两层循环来布满整个场景.

(2)要求网格的大小最起码要大过DisplayObject的大小,否则会出错

(3)通过数组将小球push到每个网格Array里,然后在在当前网格本身,以及与它相邻的(右,左下,下,右下)4个方

向的格子里push进在格子内的小球,*注意格子是从[0][0]算起的*,具体小球在哪个格里通过

var xpos:int = Math.floor(ball.x / GRID_SIZE);
var ypos:int = Math.floor(ball.y / GRID_SIZE);

即可得到,

(4)最后我们通过检测当前格,以及其他4个相邻的格子之间小球的距离来检测是否碰撞到.代码应该如下

//小球碰撞检测
   private function checkCollision(ballA:Ball,ballB:Ball) {
    _numChecks++;
    trace(_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;
    }
   }

下面给出没有优化过的代码

package 
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.geom.Rectangle
/**
* ...
* @author spade-A
*/
public class Main extends Sprite
{
   private const GRID_SIZE:Number = 50;
   private const RADIUS:Number = 25;
   private var _balls:Array;
   private var _grid:Array;
   private var _numBalls:int = 80;
   private var _numChecks:int = 0;
   public function Main() 
   {
    stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;
   
    makeBalls();
    makeGrid();
    drawGrid();
    assignBallsToGrid();
    checkGrid();
   }
  
   private function makeBalls() {
    _balls = new Array();
    for (var i:int = 0; i < _numBalls;i++ ) {
     var ball:Ball = new Ball(RADIUS/2);
     ball.x = Math.random() * stage.stageWidth;
     ball.y = Math.random() * stage.stageHeight;
     addChild(ball);
     _balls.push(ball);
    }
   }
  
   private function makeGrid() {
    _grid = new Array();
    for (var i:int = 0; i < stage.stageWidth / GRID_SIZE; i++ ) {
     _grid[i] = new Array();
     for (var j:int = 0; j < stage.stageHeight / GRID_SIZE; j++ ) {
      _grid[i][j] = new Array();
     }
    }
   }
  
   private function drawGrid() {
    graphics.lineStyle(0, 0.5);
    for (var i:int = 0; i <= stage.stageWidth; i += GRID_SIZE ) {
     graphics.moveTo(i, 0);
     graphics.lineTo(i, stage.stageHeight);
    }
   
    for (i = 0; i <= stage.stageHeight;i+=GRID_SIZE) {
     graphics.moveTo(0, i);
     graphics.lineTo(stage.stageWidth,i);
    }
   }
  
   private function assignBallsToGrid() {
    for (var i:int = 0; i < _numBalls;i++ ) {
     var ball:Ball = _balls[i] as Ball;
     //球的位置/格子大小,可得所在的行,列
     var xpos:int = Math.floor(ball.x / GRID_SIZE);
     var ypos:int = Math.floor(ball.y / GRID_SIZE);
     _grid[xpos][ypos].push(ball);
    }
   }
   //检测格子
   private function checkGrid() {
    //i=列,j=行
    for (var i:int = 0; i < _grid.length;i++ ) {
     for (var j:int = 0; j < _grid[i].length;j++ ) {
      checkOneCell(i, j);
      checkTowCell(i, j, i + 1, j);//右边
      checkTowCell(i, j, i - 1, j + 1);//左下方
      checkTowCell(i, j, i, j + 1);//正下方
      checkTowCell(i, j, i + 1, j + 1);//右下方
     }
    }
   }
  
   private function checkOneCell(x:int,y:int) {
    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 checkTowCell(x1:int,y1:int,x2:int,y2:int) {
    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) {
    _numChecks++;
    trace(_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;
    }
   }
}

}

具体优化的代码还请查看作者的代码.