衝突検出方式(クワッド)
最近、同社は同様のプロジェクト球の主要な戦闘を行うには、ゲームが衝突検出、衝突検出方式を適応させる必要があるの多くを実行し続け、その統計でインターネット検索します。ここではそれが見つけたいくつかのプログラムがあります。
オプション1:ループを通っ:
- ゲームシーンの動作中に、各フレームは()の呼び出しを更新し、更新機能に衝突オブジェクトかどうかを決定するために、シーン内のすべてのオブジェクト、距離計算によってオブジェクトの中心点を通ってループします。
- Nオブジェクトがシーンに存在する場合、それぞれ2つのオブジェクトが非効率的な衝突検出、N ^ 2を持っている時間の複雑さを、持っているため、想像してみてください。そして、実際には、衝突オブジェクトの右上隅にあるシーンと被写界の左下隅には、大幅に発生することはできません
オプションII:使用すると、独自のシマリス物理エンジンをcocos2dx:
- あなたがシーンに物理的な世界を追加することができ、すべてのオブジェクトは、シマリスの衝突コールバックの実装により、剛体物理学、衝突検出に設定されています
- ゲームを行う前に剛体衝突浸透現象が速すぎて起こる会ったので、これは、このプログラムを使用していません。
オプション3:4分木は、衝突検出を最適化します:
- 大幅に演算量を減少させる、横断するのに必要なオブジェクトの数を減らす、四分木空間インデックスを使用して。
私は四分木を使用していないので、~~試してみたい主にあまりにも多くの話
四分木原則
多くは、クワッドツリーに関する情報をオンラインで見つけることができます。四分木は、各親ノードは、4つの子ノードを持つツリーデータ構造です。我々は異なる位置にオブジェクトを区別するために、4つの領域に分割された画面、適切な四分木4つの正ノードは、4つの領域を表しています。
利便性は、4つの象限の領域は、1、2、3、4に指定します。
当社は、以下に示すように、完全象限に対応した子ノードに格納されたオブジェクトの1つの象限に、当然のことながら、オブジェクト間の象限が複数存在している、我々は、彼らの親ノードに存在するようになります。
象限内のオブジェクトの過剰な数が、それはまた、4つのサブ象限に分割され、その上になる場合:
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