首先要弄清一个问题,那就是为什么要用四叉树?它的优点是什么?
我们都知道,在游戏中,特别是大场景上,如果有很多元素,往往我们都需要遍历所有的元素。一个简单的例子:如果场景上有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>(); ; } } }
相关推荐
在AS3(ActionScript 3)中实现四叉树碰撞检测,首先要创建四叉树节点类,包含物体信息、子节点以及分割空间的相关属性。然后,我们需要实现插入物体、分割和合并节点、以及遍历和查询等核心功能。物体插入时,会...
总结来说,"未完成四叉树代码AS3实现"项目涉及到的是使用AS3语言构建和操作四叉树数据结构,以解决二维空间对象的组织和检索问题。通过深入理解四叉树的工作原理和AS3的特性,可以进一步优化这个实现,提升其在实际...
首先,我们提出了一种自适应扫描顺序,它从先前有效节点的邻居遍历四叉树,从而指定的比特率下对更多的有效系数进行编码。其次,我们将整个小波图像划分成几个块,并对它们进行单独编码。因为失真率通常随着树节点的...
标题“AS数据结构”暗示我们将探讨AS3中实现的不同数据结构,如链表、二叉堆和四叉树。这些数据结构各有特点,适用于不同的场景。 1. **链表**:链表是一种线性数据结构,其中元素并不在内存中连续存储。每个元素...
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)....
1. 阻挡物处理:通过减少需要计算的节点数量,例如使用四叉树或Octree数据结构。 2. 缓存已计算的路径:对于重复的寻路请求,可以直接复用之前的路径结果。 3. 并行计算:如果硬件支持,可以使用多线程或异步处理来...
- 使用网格索引(Grid Indexing)减少搜索空间,如四叉树或瓦片地图数据结构。 - 实现内存高效的邻接列表或邻接矩阵来存储节点关系。 - 优化启发式函数以减少误差,保持一致性。 在实际应用中,开发者需要根据具体...
例如,用于构建场景图或实现高效的空间分区算法(如四叉树或八叉树)。 9. **堆(Heap)** 堆通常用于实现优先队列,其中元素根据优先级进行排列。在游戏定时器或调度系统中,堆可以帮助高效地处理事件和任务。 ...
学习如何使用算法如Bresenham线算法、四叉树进行碰撞检测,以及如何实现简单的物理引擎。 6. **音频和视频处理**:AS3提供了强大的音频和视频播放功能,理解如何加载、播放和控制媒体,为游戏增加音效和背景音乐。 ...
clj-四叉树 使用四叉树进行空间索引和搜索的库。 查看以获取详细说明。 用法 ; ; Create a function for searching on a square divided into 2^15 tiles, ; ; each side of which is 64 ( use 'clj-quadtree.core)...
import turtle as tl def draw_smalltree(tree_length,tree_angle): ''' 绘制分形树函数 ''' if tree_length >= 3: tl.forward(tree_length) #往前画 tl.right(tree_angle) #往右转 draw_smallt
ID3(Iterative Dichotomiser 3)决策树算法是一种经典的分类算法,主要用于处理离散型特征的数据。它的核心思想是通过信息增益来选择最优的特征进行划分,以达到最大信息熵的减少。在Python中实现ID3决策树,我们...
例如,添加或修改设备树节点、初始化函数、中断处理函数等,以适应安卓系统的设备管理和中断处理机制。 4. **编译驱动**:将修改后的驱动源码编译为适合目标设备的ko(kernel object)模块。这通常涉及到设置正确的...
修复了四叉树哈希表问题和重复代理 ID ###v1.2新功能: 改进的用户界面更加人性化 重写设计器包 允许大写用于标记名称 用自定义组件替换 MinimalComps 组件 暴露的 <Space>.remove() 方法 新的 <Renderable>....
3. **绘制函数**:定义一个函数,用于绘制单个节点及其子节点。这个函数应该接受当前节点和当前的x、y坐标作为参数,以确定节点的位置。 ```vb Sub DrawTree(ByVal node As TreeNode, ByVal x As Integer, ByVal y ...
import pandas as pd ``` 假设我们有一个CSV数据集`data.csv`,包含特征列`features`和目标列`target`。首先加载数据: ```python data = pd.read_csv('data.csv') X = data['features'] y = data['target'] ``` ...
3. **组件比较**:可以对比自动化站(AS站)、操作系统站(OS站)等组件。 4. **工程数据比较**:包括图表(如CFC图表)、类型(如过程标签ProcessTag、SFC类型SFCType)、图表文件夹、块文件夹等的比较。 5. **共享...
二叉排序树(Binary Search Tree,BST)是一种特殊的数据结构,它在每个节点上都遵循一个重要的性质:左子树中的所有节点值都小于当前节点,而右子树中的所有节点值都大于当前节点。这种特性使得二叉排序树非常适合...
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...