`

AS3 四叉树

 
阅读更多

转载:http://developbbs.com/?p=115

AS3 四叉树

 

首先要弄清一个问题,那就是为什么要用四叉树?它的优点是什么?

我们都知道,在游戏中,特别是大场景上,如果有很多元素,往往我们都需要遍历所有的元素。一个简单的例子:如果场景上有1000个元素,我用鼠标框 选了多个元素,怎么判断我选中了哪些元素?最古老的方法就是遍历所有的元素,查看是否在我的鼠标框里,但问题也就来了,如果是1万个元素在场景上呢。那每 次框选一次岂不是都要遍历一次所有的元素。这样会造成CPU极度紧张,甚至flash player崩溃。

所以下面就引入了四叉树


从上面的图可以看出,我们将场景先分成四等份,然后再分,再分下去。但也不是永远分不完,大约分四五层,这个分的层数需要你自己的测试多少层效率最高。

当我们用鼠标框选的时候,就可以先使用矩形区域排除法来排除一些矩形区域中的元素。

 

package bing.utils
{
     import flash.display.DisplayObject;
     import flash.geom.Point;
     import flash.geom.Rectangle;
 
     /**
      * 四叉树 ,主要用于渲染动态地表和建筑
      * @author zhouzhanglin
      * @date 2010/9/11
      */
     public class QuadTree
     {
         //四叉树的层数
         private var _layerNum: int = 0 ;
         //最大的范围
         private var _maxRect:Rectangle  = null ;
         //主节点
         private var _mainNode:Node = null ;
         //节点集合
         private var _nodeList:Vector.<Node> = null ;
 
         /**
          *  四叉树构造函数
          * @param layerNum 四叉树的层数
          * @param maxRect 最大的范围
          */
         public function QuadTree( layerNum: int , maxRect:Rectangle )
         {
             this ._layerNum = layerNum+ 1 ; //四叉树的层数
             _maxRect = maxRect ;
             _nodeList = new Vector.<Node>();
             //初始化树的根节点
             _mainNode = new Node();
             _mainNode.hasSon = true ;
             _mainNode.rect = this ._maxRect ;
             initTree( _mainNode );
         }
         /**
          * 初始化树
          * @node 树节点
          */
         private function initTree( node:Node): void {
             if (node== null || node.rect.width<= this ._maxRect.width/Math.pow( 2 ,_layerNum ) || node.rect.height<= this ._maxRect.height/Math.pow( 2 ,_layerNum ) ){
                 node.hasSon = false ;
                 return ;
             }
             _nodeList.push( node );
             //设置子节点
             for ( var i: int = 0 ; i<node.sonNodeList.length; ++i){
                 node.sonNodeList[i]= new Node();
                 node.sonNodeList[i].parentNode = node;
                 node.sonNodeList[i].rect = new Rectangle( node.rect.x + (i % 2 ) * node.rect.width* 0.5 , node.rect.y + int ( i > 1 ) * node.rect.height* 0.5 , node.rect.width* 0.5 , node.rect.height* 0.5 );
                 initTree(node.sonNodeList[i]);
             }
         }
 
         /**
          * 添加可视对象到树中
          * @param obj 类型为DisplayObjects
          */
         public function insertObj( obj:DisplayObject ): void {
             var sonNode:Node = searchNodeByPoint( new Point(obj.x,obj.y) , _mainNode );
             sonNode.objVec.push( obj );
         }
 
         /**
          * 从树中删除对象
          * @param obj
          */
         public function deleteObj (obj:DisplayObject): void {
             var sonNode:Node = searchNodeByPoint( new Point(obj.x,obj.y) , _mainNode );
             for ( var i: int = 0 ;i<sonNode.objVec.length ; i++){
                 if (sonNode.objVec[i]==obj){
                     sonNode.objVec.splice(i, 1 );
                     break ;
                 }
             }
         }
 
         /**
          * 通过矩形区域,查询显示对象
          * @param rect 矩形区域
          * @param exact true表示精确查询
          * @return 该区域的显示对象集合
          */
         public function searchByRect( rect:Rectangle , exact: Boolean ):Vector.<DisplayObject>{
             var objVec:Vector.<DisplayObject> = new Vector.<DisplayObject>();
             if (_mainNode!= null ){
                 queryAndAdd(objVec , rect , _mainNode ,exact ) ;
             }
             return objVec ;
         }
 
         /**
          * 遍历节点和儿子节点,查找最终的对象
          * @param objVec 查询结果
          * @param rect 范围
          * @param tempNode
          */
         private function queryAndAdd(objVec:Vector.<DisplayObject>,rect:Rectangle ,  tempNode:Node ,exact: Boolean ): void {
             //如果没有交集,则返回
             if (!rect.intersects(tempNode.rect)){
                 return ;
             }
             //判断是否有儿子节点,递归找儿子
             if (tempNode.hasSon){
                 //遍历儿子节点
                 for each ( var son:Node in tempNode.sonNodeList){
                     if (son.rect.intersects(rect)){
                         queryAndAdd(objVec,rect, son ,exact);
                     }
                 }
             } else {
                 //如果是最后的节点,则把里面的对象加入数组中
                 for each ( var obj:DisplayObject in tempNode.objVec){
                     if (exact){
                         var sonRect:Rectangle = new Rectangle(obj.x,obj.y,obj.width,obj.height) ;
                         if (sonRect.intersects(rect)){
                             objVec.push( obj );
                         }
                     } else {
                         objVec.push( obj );
                     }
                 }
             }
         }
 
         /**
          * 通过坐标来找节点
          * @param point
          * @return
          */
         private function searchNodeByPoint( point:Point ,node:Node ):Node{
             if (node.hasSon){
                 if (node.checkPointIsIn(point)){
                     //遍历儿子节点
                     for each ( var son:Node in node.sonNodeList){
                         if (son.checkPointIsIn(point )){
                             node = searchNodeByPoint( point , son );
                         }
                     }
                 }
             }
             return node ;
         }
 
         /**
          * 从四叉树中移除所有
          */
         public function removeAll(): void
         {
             for each ( var node:Node in _nodeList)
             {
                 node.dispose() ;
             }
         }
     }
}
 
//===============================
 
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.geom.Rectangle;
 
/**
  *  四叉树的节点
  * @author zhouzhanglin
  * @date 2010/9/11
  */
class Node{
     //四个子节点
     private var oneNode:Node = null ;
     private var twoNode:Node = null ;
     private var threeNode:Node = null ;
     private var fourNode:Node = null ;
     //此节点的范围
     public var rect:Rectangle  = null ;
     //此节点的父亲节点
     public var parentNode:Node = null ;
     //是否有子节点
     public var hasSon: Boolean = true ;
     //此节点下所有的对象集合
     public var objVec:Vector.<DisplayObject> = new Vector.<DisplayObject>();
     //此节点的儿子节点集合
     public var sonNodeList:Vector.<Node> = new Vector.<Node>();
 
     public function Node(){
         sonNodeList.push(oneNode);
         sonNodeList.push(twoNode);
         sonNodeList.push(threeNode);
         sonNodeList.push(fourNode);
     }
 
     /**
      * 判断点是否在此节点中
      * @param point
      * @return
      */
     public function checkPointIsIn(point:Point): Boolean {
         if (point.x>= this .rect.x&&point.y>= this .rect.y&&point.x< this .rect.x+ this .rect.width&&point.y< this .rect.y+ this .rect.height){
             return true ;
         }
         return false ;
     }
 
     /**
      * 判断是否是叶子节点
      * @param node
      * @return
      */
     public function isLeaf(node:Node): Boolean {
         if ( this .parentNode!= null &&node.parentNode!= null && this .parentNode==node.parentNode){
             return true ;
         }
         return false ;
     }
 
     public function dispose(): void
     {
         if (sonNodeList)
         {
             for each ( var node:Node in sonNodeList)
             {
                 if (node) node.dispose() ;
             }
         }
 
         if (objVec)
         {
             for each ( var mc:DisplayObject in objVec)
             {
                 mc = null ;
             }
             objVec = new Vector.<DisplayObject>(); ;
         }
     }
}
 

你可以点击此处下载源代码

分享到:
评论

相关推荐

    4叉树做的碰撞检测demo

    在AS3(ActionScript 3)中实现四叉树碰撞检测,首先要创建四叉树节点类,包含物体信息、子节点以及分割空间的相关属性。然后,我们需要实现插入物体、分割和合并节点、以及遍历和查询等核心功能。物体插入时,会...

    未完成四叉树代码AS3实现

    总结来说,"未完成四叉树代码AS3实现"项目涉及到的是使用AS3语言构建和操作四叉树数据结构,以解决二维空间对象的组织和检索问题。通过深入理解四叉树的工作原理和AS3的特性,可以进一步优化这个实现,提升其在实际...

    基于自适应扫描次序和最优截断的四叉树编码matlab代码

    首先,我们提出了一种自适应扫描顺序,它从先前有效节点的邻居遍历四叉树,从而指定的比特率下对更多的有效系数进行编码。其次,我们将整个小波图像划分成几个块,并对它们进行单独编码。因为失真率通常随着树节点的...

    AS数据结构

    标题“AS数据结构”暗示我们将探讨AS3中实现的不同数据结构,如链表、二叉堆和四叉树。这些数据结构各有特点,适用于不同的场景。 1. **链表**:链表是一种线性数据结构,其中元素并不在内存中连续存储。每个元素...

    STL 风格的 N叉树

    The library is available under the terms of the GNU General Public License version 2 or 3.Documentation is available in the form of a pdf file (also available in the tarball as a LaTeX file)....

    flash as3 游戏寻路系统

    1. 阻挡物处理:通过减少需要计算的节点数量,例如使用四叉树或Octree数据结构。 2. 缓存已计算的路径:对于重复的寻路请求,可以直接复用之前的路径结果。 3. 并行计算:如果硬件支持,可以使用多线程或异步处理来...

    AS3简单的寻路程序

    - 使用网格索引(Grid Indexing)减少搜索空间,如四叉树或瓦片地图数据结构。 - 实现内存高效的邻接列表或邻接矩阵来存储节点关系。 - 优化启发式函数以减少误差,保持一致性。 在实际应用中,开发者需要根据具体...

    AS3 Data Structures For Game Developers.zip

    例如,用于构建场景图或实现高效的空间分区算法(如四叉树或八叉树)。 9. **堆(Heap)** 堆通常用于实现优先队列,其中元素根据优先级进行排列。在游戏定时器或调度系统中,堆可以帮助高效地处理事件和任务。 ...

    AS3 高级游戏编程

    学习如何使用算法如Bresenham线算法、四叉树进行碰撞检测,以及如何实现简单的物理引擎。 6. **音频和视频处理**:AS3提供了强大的音频和视频播放功能,理解如何加载、播放和控制媒体,为游戏增加音效和背景音乐。 ...

    clj-quadtree:使用四叉树的空间搜索索引

    clj-四叉树 使用四叉树进行空间索引和搜索的库。 查看以获取详细说明。 用法 ; ; Create a function for searching on a square divided into 2^15 tiles, ; ; each side of which is 64 ( use 'clj-quadtree.core)...

    python使用turtle绘制分形树

    import turtle as tl def draw_smalltree(tree_length,tree_angle): ''' 绘制分形树函数 ''' if tree_length &gt;= 3: tl.forward(tree_length) #往前画 tl.right(tree_angle) #往右转 draw_smallt

    ID3决策树的Python代码

    ID3(Iterative Dichotomiser 3)决策树算法是一种经典的分类算法,主要用于处理离散型特征的数据。它的核心思想是通过信息增益来选择最优的特征进行划分,以达到最大信息熵的减少。在Python中实现ID3决策树,我们...

    rtl8723as.rar

    例如,添加或修改设备树节点、初始化函数、中断处理函数等,以适应安卓系统的设备管理和中断处理机制。 4. **编译驱动**:将修改后的驱动源码编译为适合目标设备的ko(kernel object)模块。这通常涉及到设置正确的...

    GameCheetah:一个免费的开源 AS3 游戏引擎

    修复了四叉树哈希表问题和重复代理 ID ###v1.2新功能: 改进的用户界面更加人性化 重写设计器包 允许大写用于标记名称 用自定义组件替换 MinimalComps 组件 暴露的 &lt;Space&gt;.remove() 方法 新的 &lt;Renderable&gt;....

    VB6采用递归思想绘制树的源码

    3. **绘制函数**:定义一个函数,用于绘制单个节点及其子节点。这个函数应该接受当前节点和当前的x、y坐标作为参数,以确定节点的位置。 ```vb Sub DrawTree(ByVal node As TreeNode, ByVal x As Integer, ByVal y ...

    CART算法训练决策树的简单实现_python_代码_下载

    import pandas as pd ``` 假设我们有一个CSV数据集`data.csv`,包含特征列`features`和目标列`target`。首先加载数据: ```python data = pd.read_csv('data.csv') X = data['features'] y = data['target'] ``` ...

    西门子PCS7 7.0 SP1版本交叉管理器使用指南.pdf

    3. **组件比较**:可以对比自动化站(AS站)、操作系统站(OS站)等组件。 4. **工程数据比较**:包括图表(如CFC图表)、类型(如过程标签ProcessTag、SFC类型SFCType)、图表文件夹、块文件夹等的比较。 5. **共享...

    二叉排序树统计文档中单词的个数

    二叉排序树(Binary Search Tree,BST)是一种特殊的数据结构,它在每个节点上都遵循一个重要的性质:左子树中的所有节点值都小于当前节点,而右子树中的所有节点值都大于当前节点。这种特性使得二叉排序树非常适合...

    python实现决策树模型.docx

    import pandas as pd from sklearn.model_selection import train_test_split df = pd.read_excel('员工离职预测模型.xlsx') df = df.replace({'工资': {'低': 0, '中': 1, '高': 2}}) X = df.drop(columns='离职')...

    最小生成树算法报告-研究生报告

    3. 更新:重复上述过程直到所有顶点都在同一棵树中。 **伪代码**: ``` function Boruvka(G) // G is an undirected weighted graph initialize each vertex v as a separate tree while there is more than one...

Global site tag (gtag.js) - Google Analytics