Lua实现四叉树(QuadTree)类与测试场景实例

本文介绍了四叉树的数据结构及其在二维空间资料分析中的应用,由Raphael Finkel和J.L. Bentley于1974年提出。在游戏开发中,四叉树常用于大地图资源管理和粒子碰撞检测。作者分享了用Lua实现的QuadTree类,并在Unity的Lua层编写了测试Demo,包括四叉树边界绘制和粒子碰撞检测两个测试场景。
摘要由CSDN通过智能技术生成

四叉树是一种树状数据结构,在每一个节点上会有四个子区块。四叉树常应用于二维空间资料的分析与分类。
它将资料区分成为四个象限。资料范围可以是方形或矩形或其他任意形状。这种数据结构是由 拉斐尔·芬科尔(Raphael Finkel) 与 J.
L. Bentley 在1974年发展出来 。 类似的资料分割方法也称为 Q-tree。 所有的四叉树法有共同之特点:
1.可分解成为各自的区块
2.每个区块都有节点容量。当节点达到最大容量时,节点分裂
3.树状数据结构依造四叉树法加以区分

以上定义描述引用于wiki链接(四叉树定义),在游戏开发中主要用于大地图资源逻辑管理,粒子碰撞检测等,引入四叉树/八叉树用于二维/三维的空间管理。下面是我用Lua实现的QuadTree类。

local QuadTree = Class("QuadTree")

local Dir = {
   
    LeftBottom = 0,     -- 00
    LeftTop = 1,        -- 01
    RightBottom = 2,    -- 10
    RightTop = 3,       -- 11
}

-- centre_x, centre_y, width, height为最大layout
-- capacity为每个节点最多容纳的点容量
local function __init(self, centre_x, centre_y, width, height, capacity)
    self.centre_x = centre_x
    self.centre_y = centre_y
    self.width = width
    self.height = height
    
    -- 存放transList
    self.transList = {
   }
    -- 最大容纳trans数量
    self.capacity = capacity

    -- 是否已被拆分
    self.divided = false
    -- 子节点
    self.children = {
   }
end

local function __delete(self)
    if self.children and not table.empty(self.children) then
        for _, childrenNode in pairs(self.children) do
            childrenNode:Delete()
        end
    end
    self.children = nil
    self.transList = nil
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
四叉树碰撞算法是一种常用的空间分割算法,可以有效地优化碰撞检测的性能。下面是使用Lua语言实现四叉树碰撞算法的基本步骤: 1. 定义四叉树节点 首先我们需要定义四叉树节点的数据结构,一个四叉树节点包含四个子节点和一个节点范围(即矩形区域)。可以使用Lua的table来表示节点。 ```lua local QuadNode = { children = {}, -- 子节点 bounds = {}, -- 节点范围 objects = {}, -- 包含的物体 } ``` 2. 构建四叉树 接下来,我们需要构建四叉树。构建四叉树的过程就是不断地将物体插入到四叉树节点中,如果一个节点已经包含了足够数量的物体或者达到了最大深度,则需要将该节点分割成四个子节点。 ```lua function QuadNode:insert(obj) if #self.objects < MAX_OBJECTS or self.depth >= MAX_DEPTH then table.insert(self.objects, obj) else if not self.children[1] then self:split() end for i = 1, #self.children do if self.children[i]:contains(obj) then self.children[i]:insert(obj) break end end end end function QuadNode:split() local x, y, w, h = self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height local half_w, half_h = w / 2, h / 2 self.children[1] = QuadNode:new(x, y, half_w, half_h, self.depth + 1) self.children[2] = QuadNode:new(x + half_w, y, half_w, half_h, self.depth + 1) self.children[3] = QuadNode:new(x, y + half_h, half_w, half_h, self.depth + 1) self.children[4] = QuadNode:new(x + half_w, y + half_h, half_w, half_h, self.depth + 1) for i = 1, #self.objects do local obj = self.objects[i] for j = 1, #self.children do if self.children[j]:contains(obj) then self.children[j]:insert(obj) break end end end self.objects = {} end ``` 3. 碰撞检测 最后,我们需要进行碰撞检测。对于一个物体,我们首先找到它所在的叶子节点,然后检测该节点中所有物体是否与该物体相交。如果相交,则进行进一步的检测。 ```lua function QuadNode:query(obj, results) if not results then results = {} end for i = 1, #self.objects do local other = self.objects[i] if obj ~= other and obj:intersects(other) then table.insert(results, other) end end if self.children[1] then for i = 1, #self.children do if self.children[i]:intersects(obj) then self.children[i]:query(obj, results) end end end return results end ``` 完整代码如下: ```lua QuadNode = { MAX_OBJECTS = 10, MAX_DEPTH = 5, } function QuadNode:new(x, y, w, h, depth) local node = { children = {}, bounds = {x = x, y = y, width = w, height = h}, objects = {}, depth = depth or 0, } setmetatable(node, {__index = QuadNode}) return node end function QuadNode:insert(obj) if #self.objects < QuadNode.MAX_OBJECTS or self.depth >= QuadNode.MAX_DEPTH then table.insert(self.objects, obj) else if not self.children[1] then self:split() end for i = 1, #self.children do if self.children[i]:contains(obj) then self.children[i]:insert(obj) break end end end end function QuadNode:split() local x, y, w, h = self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height local half_w, half_h = w / 2, h / 2 self.children[1] = QuadNode:new(x, y, half_w, half_h, self.depth + 1) self.children[2] = QuadNode:new(x + half_w, y, half_w, half_h, self.depth + 1) self.children[3] = QuadNode:new(x, y + half_h, half_w, half_h, self.depth + 1) self.children[4] = QuadNode:new(x + half_w, y + half_h, half_w, half_h, self.depth + 1) for i = 1, #self.objects do local obj = self.objects[i] for j = 1, #self.children do if self.children[j]:contains(obj) then self.children[j]:insert(obj) break end end end self.objects = {} end function QuadNode:contains(obj) local x, y, w, h = self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height local ox, oy, ow, oh = obj.x, obj.y, obj.width, obj.height return ox >= x and ox + ow <= x + w and oy >= y and oy + oh <= y + h end function QuadNode:intersects(obj) local x, y, w, h = self.bounds.x, self.bounds.y, self.bounds.width, self.bounds.height local ox, oy, ow, oh = obj.x, obj.y, obj.width, obj.height return x < ox + ow and x + w > ox and y < oy + oh and y + h > oy end function QuadNode:query(obj, results) if not results then results = {} end for i = 1, #self.objects do local other = self.objects[i] if obj ~= other and obj:intersects(other) then table.insert(results, other) end end if self.children[1] then for i = 1, #self.children do if self.children[i]:intersects(obj) then self.children[i]:query(obj, results) end end end return results end ``` 使用示例: ```lua -- 创建四叉树 local tree = QuadNode:new(0, 0, 640, 480) -- 插入物体 tree:insert({x=10, y=10, width=20, height=20}) tree:insert({x=30, y=30, width=20, height=20}) tree:insert({x=50, y=50, width=20, height=20}) -- 查询物体相交的物体 local results = tree:query({x=40, y=40, width=20, height=20}) for i = 1, #results do print('object', i, results[i].x, results[i].y) end ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值