衝突検出方式(クワッド)

衝突検出方式(クワッド)

96 
LofterAltairの 
2018年8月4日13:04 *  単語653は、  887件の読んコメント0

最近、同社は同様のプロジェクト球の主要な戦闘を行うには、ゲームが衝突検出、衝突検出方式を適応させる必要があるの多くを実行し続け、その統計でインターネット検索します。ここではそれが見つけたいくつかのプログラムがあります。

オプション1:ループを通っ:

  • ゲームシーンの動作中に、各フレームは()の呼び出しを更新し、更新機能に衝突オブジェクトかどうかを決定するために、シーン内のすべてのオブジェクト、距離計算によってオブジェクトの中心点を通ってループします。
  • Nオブジェクトがシーンに存在する場合、それぞれ2つのオブジェクトが非効率的な衝突検出、N ^ 2を持っている時間の複雑さを、持っているため、想像してみてください。そして、実際には、衝突オブジェクトの右上隅にあるシーンと被写界の左下隅には、大幅に発生することはできません

オプションII:使用すると、独自のシマリス物理エンジンをcocos2dx:

  • あなたがシーンに物理的な世界を追加することができ、すべてのオブジェクトは、シマリスの衝突コールバックの実装により、剛体物理学、衝突検出に設定されています
  • ゲームを行う前に剛体衝突浸透現象が速すぎて起こる会ったので、これは、このプログラムを使用していません。

オプション3:4分木は、衝突検出を最適化します:

  • 大幅に演算量を減少させる、横断するのに必要なオブジェクトの数を減らす、四分木空間インデックスを使用して。
    私は四分木を使用していないので、~~試してみたい主にあまりにも多くの話

四分木原則


多くは、クワッドツリーに関する情報をオンラインで見つけることができます。四分木は、各親ノードは、4つの子ノードを持つツリーデータ構造です。我々は異なる位置にオブジェクトを区別するために、4つの領域に分割された画面、適切な四分木4つの正ノードは、4つの領域を表しています。
利便性は、4つの象限の領域は、1、2、3、4に指定します。

 
image.png

当社は、以下に示すように、完全象限に対応した子ノードに格納されたオブジェクトの1つの象限に、当然のことながら、オブジェクト間の象限が複数存在している、我々は、彼らの親ノードに存在するようになります。

 
image.png

象限内のオブジェクトの過剰な数が、それはまた、4つのサブ象限に分割され、その上になる場合:

 
image.png

LUAは、四分木を達成します


local QuadTree = {}
QuadTree.__index = QuadTree

QuadTree.MAX_OBJECTS = 10
QuadTree.MAX_LEVELS = 5

local function checkbounds(quadrant, box)
    local list = {
        cc.p(box.x + box.width, box.y + box.height),
        cc.p(box.x + box.width, box.y + box.height),
        cc.p(box.x + box.width, box.y + box.height),
        cc.p(box.x + box.width, box.y + box.height),
    }
    for _, pos in pairs(list) do if not (pos.x >= quadrant.x and pos.x <= quadrant.x + quadrant.width and pos.y >= quadrant.y and pos.y <= quadrant.y + quadrant.height) then return false end end return true end --bounds 屏幕范围 --level 四叉树层级 function QuadTree:new(bounds, level) local o = {} o = setmetatable(o,QuadTree) o.objects = {} o.nodes = {} o.level = level and level or 0 o.bounds = bounds return o end -- 获取物体对应的象限序号,以屏幕中心为界限,切割屏幕: -- - 右上:象限一 -- - 左上:象限二 -- - 左下:象限三 -- - 右下:象限四 function QuadTree:getIndex(node) local rect = node:getBoundingBox() if not checkbounds(self.bounds, rect) then return nil end local x = self.bounds.x local y = self.bounds.y local width = self.bounds.width / 2 local height = self.bounds.height / 2 local quadrant1 = cc.rect(x + width, y + height, width, height) local quadrant2 = cc.rect(x, y + height, width, height) local quadrant3 = cc.rect(x, y, width, height) local quadrant4 = cc.rect(x + width, y, width, height) if checkbounds(quadrant1, rect) then return 1 elseif checkbounds(quadrant2, rect) then return 2 elseif checkbounds(quadrant3, rect) then return 3 elseif checkbounds(quadrant4, rect) then return 4 end --如果物体跨越多个象限,则放回-1 return - 1 end function QuadTree:split() if #self.nodes > 0 then return end local x = self.bounds.x local y = self.bounds.y local width = self.bounds.width / 2 local height = self.bounds.height / 2 local tree1 = QuadTree:new(cc.rect(x + width, y + height, width, height), self.level + 1) local tree2 = QuadTree:new(cc.rect(x, y + height, width, height), self.level + 1) local tree3 = QuadTree:new(cc.rect(x, y, width, height), self.level + 1) local tree4 = QuadTree:new(cc.rect(x + width, y, width, height), self.level + 1) table.insert(self.nodes, tree1) table.insert(self.nodes, tree2) table.insert(self.nodes, tree3) table.insert(self.nodes, tree4) end -- 插入功能: -- - 如果当前节点[ 存在 ]子节点,则检查物体到底属于哪个子节点,如果能匹配到子节点,则将该物体插入到该子节点中 -- - 如果当前节点[ 不存在 ]子节点,将该物体存储在当前节点。随后,检查当前节点的存储数量,如果超过了最大存储数量,则对当前节点进行划分,划分完成后,将当前节点存储的物体重新分配到四个子节点中。 function QuadTree:insert(node) --如果该节点下存在子节点 print("!!!!!!!!!!!!!!!!!!!!!!!!",tolua.type(node)) if #self.nodes > 0 then local index = self:getIndex(node) if index and index ~= - 1 then self.nodes[index]:insert(node) return end end --否则存储在当前节点下 table.insert(self.objects, node) --如果当前节点存储的数量超过了MAX_OBJECTS if #self.nodes <= 0 and #self.objects > QuadTree.MAX_OBJECTS and self.level < QuadTree.MAX_LEVELS then self:split() for i = #self.objects, 1, - 1 do local index = self:getIndex(self.objects[i]) if index and index ~= - 1 then self.nodes[index]:insert(self.objects[i]) table.remove(self.objects, i) end end end end -- 检索功能: -- 给出一个物体对象,该函数负责将该物体可能发生碰撞的所有物体选取出来。该函数先查找物体所属的象限,该象限下的物体都是有可能发生碰撞的,然后再递归地查找子象限... function QuadTree:retrieve(node) local result = {} if #self.nodes > 0 then local index = self:getIndex(node) if index and index ~= - 1 then local list = self.nodes[index]:retrieve(node) for _,value in pairs(list) do table.insert(result, value) end elseif index and index == - 1 then local x = self.bounds.x local y = self.bounds.y local width = self.bounds.width / 2 local height = self.bounds.height / 2 local quadrant1 = cc.rect(x + width, y + height, width, height) local quadrant2 = cc.rect(x, y + height, width, height) local quadrant3 = cc.rect(x, y, width, height) local quadrant4 = cc.rect(x + width, y, width, height) local rect = node:getBoundingBox() if checkbounds(quadrant1, rect) then local list = self.nodes[1]:retrieve(node) for _,value in pairs(list) do table.insert(result, value) end end if checkbounds(quadrant2, rect) then local list = self.nodes[2]:retrieve(node) for _,value in pairs(list) do table.insert(result, value) end end if checkbounds(quadrant3, rect) then local list = self.nodes[3]:retrieve(node) for _,value in pairs(list) do table.insert(result, value) end end if checkbounds(quadrant4, rect) then local list = self.nodes[4]:retrieve(node) for _,value in pairs(list) do table.insert(result, value) end end end end for _,value in pairs(self.objects) do table.insert(result, value) end return result end --判断矩形是否在象限范围内 function QuadTree:isInner(node, bounds) local rect = node:getBoundingBox() return rect.x >= bounds.x and rect.x + rect.width <= bounds.x + bounds.width and rect.y >= bounds.y and rect.y + rect.height <= bounds.y + bounds.height end -- 动态更新: -- 从根节点深入四叉树,检查四叉树各个节点存储的物体是否依旧属于该节点(象限)的范围之内,如果不属于,则重新插入该物体。 function QuadTree:refresh(root) root = root or self for i = #self.objects, 1, - 1 do local node = self.objects[i] local index = self:getIndex(node) if index then --如果矩形不属于该象限,则将该矩形重新插入 if not self:isInner(node, self.bounds) then if self ~= root then root:insert(self.objects[i]) table.remove(self.objects, i) end -- 如果矩形属于该象限 且 该象限具有子象限,则 -- 将该矩形安插到子象限中 elseif #self.nodes > 0 then self.nodes[index]:insert(self.objects[i]) table.remove(self.objects, i) end end end for i = 1, #self.nodes do self.nodes[i]:refresh(root) end end return QuadTree 

私はまた、ノードの欠如を発見したプロジェクトの後半に実用化を除去し、そして明確なインターフェース全体の四分木され
、私が保存されて四分木オブジェクト構造はCCNODEあります

--移除四叉树节点中的object
function QuadTree:remove(removeNode)
    for i = #self.objects, 1, - 1 do
        local node = self.objects[i]
        if node and node:getTag() == removeNode:getTag() then table.remove(self.objects, i) return true end end for i = 1, #self.nodes do if self.nodes[i]:remove(removeNode) then return true end end return false end --清理四叉树 function QuadTree:clear() for i = #self.objects, 1, - 1 do table.remove(self.objects,i) end self.objects = {} for i = 1, #self.nodes do self.nodes[i]:clear() end end

おすすめ

転載: www.cnblogs.com/vana/p/10948789.html