/* * Vector 的使用。Vector是 Flash10 的新内容,相当于一个具有类型的数组。由于编译器 知道 vector 中的每个元素都是同样的类型,所以就能为之创建出更有效的字节码,从而提高执行效率。 以这段程序为例,从数组改为 vector 差不多使运行效率翻了一倍。 drawGrid 函数一点没变,它依旧用来画出网格。 check 函数是这个类对外交互的主要函数。其接收参数的类型是元素类型为 DisplayObject 的 vector。 选择 Displayobject 的原因是因为碰撞检测通常用于 Sprite,MovieClip,Shape 和Bitmap, 而这些类都继承自 Displayobject。Displayobject 也有x和y 两个位置属性。 所以要用自定义的对象时,请确保继承自 Displayobject。 函数一开始定义了一个名为_grid 的 vector,还有一个名为_checks 的 vector。 _grid 应该不陌生,但在实现上有点不同,这里用一维 vector 加索引技巧取代了二维数组。 因为这么做,可以使访问元素速度更快并减少了循环。等下会有详细介绍。 _checks 用来保存需要进行碰撞检测的对象。注意 CollisionGrid 类不处理具体的碰撞检测,它只 用来创建网格,分配对象,以及生成一组需要被检测的对象。具体的碰撞检测算法由你而定。 接着,check 函数对给定的 vector 进行遍历,把其中每个 Displayobject 都分配进网格。 */ package { import flash.display.DisplayObject; import flash.display.Graphics; import flash.events.EventDispatcher; public class CollisionGrid extends EventDispatcher { private var _checks:Vector.; private var _grid:Vector.>; private var _gridSize:Number; private var _height:Number; private var _numCells:int; private var _numCols:int; private var _numRows:int; private var _width:Number; public function CollisionGrid(width:Number, height:Number, gridSize:Number) { _width=width; _height=height; _gridSize=gridSize; _numCols=Math.ceil(_width/_gridSize); _numRows=Math.ceil(_height/_gridSize); _numCells=_numCols*_numRows; } public function drawGrid(graphics:Graphics):void { graphics.lineStyle(0, .5); for (var i:int = 0; i <= _width; i += _gridSize) { graphics.moveTo(i, 0); graphics.lineTo(i, _height); } for (i = 0; i <= _height; i += _gridSize) { graphics.moveTo(0, i); graphics.lineTo(_width, i); } } public function check(objects:Vector.):void { var numObjects:int=objects.length; _grid=new Vector.>(_numCells); _checks = new Vector.(); for (var i:int = 0; i < numObjects; i++) { var obj:DisplayObject=objects[i]; var index:int=Math.floor(obj.y/_gridSize)*_numCols+Math.floor(obj.x/_gridSize); if (_grid[index]==null) { _grid[index]=new Vector. ; } _grid[index].push(obj); } checkGrid(); } private function checkGrid():void { for (var i:int = 0; i < _numCols; i++) { for (var j:int = 0; j < _numRows; 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:Vector.=_grid[y*_numCols+x]; if (cell==null) { return; } var cellLength:int=cell.length; for (var i:int = 0; i < cellLength - 1; i++) { var objA:DisplayObject=cell[i]; for (var j:int = i + 1; j < cellLength; j++) { var objB:DisplayObject=cell[j]; _checks.push(objA, objB); } } } private function checkTwoCells(x1:int, y1:int, x2:int, y2:int):void { if (x2>=_numCols||x2<0||y2>=_numRows) { return; } var cellA:Vector.=_grid[y1*_numCols+x1]; var cellB:Vector.=_grid[y2*_numCols+x2]; if (cellA==null||cellB==null) { return; } var cellALength:int=cellA.length; var cellBLength:int=cellB.length; for (var i:int = 0; i < cellALength; i++) { var objA:DisplayObject=cellA[i]; for (var j:int = 0; j < cellBLength; j++) { var objB:DisplayObject=cellB[j]; _checks.push(objA, objB); } } } public function get checks():Vector. { return _checks; } } }