在一些游戏中,当地图上有很多元素时,或者有一张很大的地图需要渲染。通常的做法是遍历所有的显示对象,但是这样做,可能会占用大量的CPU,所以为了处理这种情况。我们可以使用四叉树,这里的四叉树,就是把场景划分为四等分,然后每一小份再分成四等分,这下分下去,通常情况分四五次就行了。具体分几层,可以在实践中去测试,以获得最高的效率。
下面是四叉树中的公开的类,其实很简单,就是先建树,然后往里面添加对象,移除对象,清空所有的对象。最重要的就是搜索显示对象。
/**
* 构造函数
* @param 四叉树的层数
* @param 整个地图的长和度
*/
public function QuadTree( layerNum:int , maxRect:Rectangle )
//添加一个显示对象
public function insertObj( obj:DisplayObject ):void
//删除一个显示对象从四叉树中
public function deleteObj (obj:DisplayObject):void
//清空四叉树中的所有元素
public function removeAll():void
/**
* 查询显示对象
* @param rect 查询区域
* @param exact 是否精确查找
* @return 返回查询集合
*/
public function searchByRect( rect:Rectangle , exact:Boolean ):Vector.<DisplayObject>
下面是测试四叉树,现在场景上有一千个元素,我们可以用鼠标快速地选择你想要的
package
{
import bing.utils.QuadTree;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import test.Model;
[SWF(backgroundColor="0x000000")]
public class QuadTreeTest extends Sprite
{
private var _modelContainer:Sprite = new Sprite();
private var _selectContainer:Sprite =new Sprite();
private var _selectModels:Vector.<DisplayObject> ;
private var _tree:QuadTree;
private var _downLoc:Point = new Point();;
public function QuadTreeTest()
{
addChild(_modelContainer);
addChild(_selectContainer);
if(stage) init();
else addEventListener(Event.ADDED_TO_STAGE , init );
}
private function init( e:Event = null ):void
{
stage.scaleMode="noScale";
stage.align="TL";
removeEventListener(Event.ADDED_TO_STAGE , init );
stage.addEventListener(MouseEvent.MOUSE_DOWN , onDown );
stage.addEventListener(MouseEvent.MOUSE_MOVE , onMove);
stage.addEventListener(MouseEvent.MOUSE_UP , onUp);
_tree = new QuadTree( 4 , new Rectangle(0,0,1200,750));
var model:Model ;
for( var i:int = 0 ; i<40 ; i++)
{
for(var j:int = 0 ; j<25 ; j++)
{
model = new Model();
model.x = i*model.width + i*10 ;
model.y = j*model.height + j*10 ;
_modelContainer.addChild( model );
_tree.insertObj( model );
}
}
}
private function onDown(e:MouseEvent):void
{
_downLoc.x = mouseX;
_downLoc.y = mouseY;
//清除最后选择的
if(_selectModels)
{
for each( var obj:DisplayObject in _selectModels)
{
obj.alpha =1 ;
}
}
}
private function onMove(e:MouseEvent):void
{
if(e.buttonDown)
{
_selectContainer.graphics.clear();
_selectContainer.graphics.beginFill(0x000000,.5);
_selectContainer.graphics.lineStyle(1,0xCCCCCC,.5);
_selectContainer.graphics.drawRect( _downLoc.x,_downLoc.y,mouseX-_downLoc.x,mouseY-_downLoc.y);
_selectContainer.graphics.endFill();
}
}
private function onUp(e:MouseEvent):void
{
var time:int = getTimer();
_selectModels = _tree.searchByRect( new Rectangle( _downLoc.x,_downLoc.y,mouseX-_downLoc.x,mouseY-_downLoc.y ),true);
trace( getTimer()-time); //ms
for each( var obj:DisplayObject in _selectModels)
{
obj.alpha = 0.5 ;
}
_selectContainer.graphics.clear();
}
}
}
转载http://blog.163.com/fll_0601/blog/static/5499988201171651141898/