天天看點

Cocos Creator | 碰撞檢測優化-四叉樹

擷取更多筆記和源碼

公衆号:CocosCreator筆記

Cocos Creator | 碰撞檢測優化-四叉樹

 四叉樹原理本人就不贅述了,很多前輩都有詳細的講解

首先說明下四叉樹并不是一個碰撞引擎,它隻是一種減少碰撞候選者的算法,是以在利用四叉樹得到碰撞候選元素後,還需要去檢測這些候選元素與目标元素是否發生碰撞

2D中是四叉樹,3D中則對應的為八叉樹

項目(微信小遊戲《宇宙少女》)中實測:

同屏極限情況下,可碰撞元素為:

200左右子彈+70左右怪物+若幹buff+玩家

碰撞關系為:

子彈和怪物碰撞

特定怪物和其他怪物碰撞反彈

玩家和怪物碰撞

玩家和buff碰撞

使用cocos的碰撞系統,在H5表現良好,微信小遊戲的Android平台也還可以,但是在ios平台上,FPS隻有20+

使用四叉樹做空間規劃,對子彈做進一步的優化,減少碰撞元素

碰撞檢測使用圓圓碰撞和圓矩碰撞,放棄了pow()和sqrt()方法, 其相對于加減乘除會消耗更多的CPU(之前在QQ群讨論過)

改良後的碰撞檢測在微信小遊戲的Android平台性能良好,IOS平台的FPS也達到了50+

項目中使用每幀重建四叉樹,當然也可以自己維護四叉樹中碰撞元素的位置

Cocos Creator | 碰撞檢測優化-四叉樹

1四叉樹概念

四叉樹(quad-tree)是一種資料結構,是一種每個節點最多有四個子樹的資料結構。四叉樹是在二維圖檔中定位像素的唯一适合的算法。因為二維空間(圖經常被描述的方式)中,平面像素可以重複的被分為四部分,樹的深度由圖檔、計算機記憶體和圖形的複雜度決定。四叉樹可以用來在資料庫中放置和定位檔案(稱作記錄或鍵)。這一算法通過不停的把要查找的記錄分成4部分來進行比對查找直到僅剩下一條記錄為止。

2空間規劃

遊戲程式設計模式-空間分區

将對象存儲在根據位置組織的資料結構中來高效地定位它們。  你有一組對象(可能還挺多),将對象存儲在一個根據對象位置來組織的資料結構中,該資料結構可以讓你高效查詢位于或靠近某處的對象。當對象位置改變時,更新并繼續維護該空間資料對象。用更複雜的資料結構(空間)來換取大量查詢時的性能優化(時間)。

部落格園中一篇講解詳細的blog

https://www.cnblogs.com/xin-lover/p/12216053.html

廣告

遊戲程式設計模式

作者:[美]Robert Nystrom(尼斯卓姆)

京東

3

quadtree-js

在GitHub上找到的一個前輩實作的四叉樹:

https://github.com/timohausmann/quadtree-js

并提供了兩個線上示範的demo,其中紅色為四叉樹節點,空白方塊為四叉樹中的元素,灰色方塊為滑鼠的位置,即目标元素,綠色方塊為碰撞候選元素

1.手動添加靜态對象并檢視四叉樹拆分:

https://timohausmann.de/quadtree.js/simple.html
Cocos Creator | 碰撞檢測優化-四叉樹

2.在持續運動的對象中檢視四叉樹拆分:

https://timohausmann.de/quadtree.js/dynamic.html
Cocos Creator | 碰撞檢測優化-四叉樹

4使用方法

1.引入quadtree.js

①通過代碼引入:

import * as Quadtree from "../R-framework/quadtree.js";
           

②插件引入:

将quadtree.js檔案導入編輯器的時候選擇為插件

2.建立四叉樹

區域為整個螢幕

let myTree = new Quadtree({              x: -cc.winSize.width / 2,              y: -cc.winSize.height / 2,              width: cc.winSize.width / 2,              height: cc.winSize.height / 2              });
           

3.插入元素

參數為元素的左下角坐标及其寬高

myTree.insert({                x: 200,                y: 150,              width: 20,              height: 20              });
           

4.檢索元素

參數為目标元素的左下角坐标及其寬高

傳回值為碰撞候選元素數組

let elements = myTree.retrieve({              x: 150,              y: 100,              width: 20,              height: 20              });
           

5.碰撞檢測

在得到碰撞候選元素後,需要檢測是否與目标元素發生碰撞,檢測的方法可以用cocos的碰撞元件,也可以根據項目需求定制碰撞檢測

6.清除四叉樹

檢測完畢後,需要清除四叉樹中的元素,以友善下次繼續檢測

myTree.clear();
           

或者維護四叉樹空間中碰撞元素的位置

繼續閱讀