四叉樹與碰撞檢測 !Cocos Creator !

四叉樹與引擎內置碰撞檢測的結合運用。

效果預覽

綠色爲參加檢測的對象(當前四叉樹節點),紅色爲碰撞對象。

image

如何使用

引入腳本 QuadtreeCollision.ts , 新建一個 QuadtreeCollision ,並初始化爲世界座標系下的對齊軸向的包圍盒(AABB)。

// 這邊是掛載在canvas下的腳本,用canvas的rect初始化創建。
this._quadCollision = new QuadtreeCollision(this.node.getBoundingBoxToWorld())

傳入待檢測的碰撞數組 cc.Collider[] 和測試對象的 cc.Collider

返回準備測試的 cc.Collider[] 和發生碰撞的 cc.Collider[]

// check(colliders: cc.Collider[], testCollider: cc.Collider)
const { retrieve, contacts } = this._quadCollision.check(this._all_collider, this.collider_role);
// retrieve 準備測試的對象(預覽圖中的綠色)   cc.Collider[]
// contacts 碰撞對象(預覽圖中的紅色)   cc.Collider[]

實現原理

四叉樹是什麼?

白玉無冰是這樣理解的,四叉樹本身是樹結構的一種,如果物體過多的話,先根據物體所處位置劃分成四塊,如果每個塊的中的物體數量還是很多的話,繼續劃分成四塊。如下圖紅線所示。

image

檢測的時候,就是根據待測試對象的位置,去找屬於哪個塊,再把這個塊中的物體告訴你。如下圖中的綠色物體。

image

那麼怎麼實現四叉樹呢?用好 github 就行了(誤),搜了一下,找到一個庫,直接拿來改改就行了。

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

//export default class QuadtreeCollision {
private _tree;
constructor(rect: { x: number, y: number, width: number, height: number }) {
    this._tree = new Quadtree(rect);
}

image

那麼怎麼檢測碰撞呢?

先看看引擎(v2.3.3)的 CollisionManager 是怎麼處理的。

cc.Collider 這個組件 onEnable 時,會把這個組件加入 CollisionManager 中。

CollisionManager 添加 Collider 時,會遍歷所有的 Collider ,根據分組創建一個碰撞連接。

image

所以,我們碰撞檢測的思路,就在源碼中搬過來改改。

image

將上面的代碼整理出我們要用的檢測代碼如下。

function testContact(collider1, collider2) {
    // 分組不通過
    if (!cc.director.getCollisionManager()['shouldCollide'](collider1, collider2)) {
        return false;
    }

    let world1 = collider1.world;
    let world2 = collider2.world;
    if (!world1.aabb.intersects(world2.aabb)) {
        return false;
    }

    let isCollider1Polygon = (collider1 instanceof cc.BoxCollider) || (collider1 instanceof cc.PolygonCollider);
    let isCollider2Polygon = (collider2 instanceof cc.BoxCollider) || (collider2 instanceof cc.PolygonCollider);
    let isCollider1Circle = collider1 instanceof cc.CircleCollider;
    let isCollider2Circle = collider2 instanceof cc.CircleCollider;

    if (isCollider1Polygon && isCollider2Polygon) {
        return cc.Intersection.polygonPolygon(world1.points, world2.points);
    } else if (isCollider1Circle && isCollider2Circle) {
        return cc.Intersection.circleCircle(world1, world2);
    } else if (isCollider1Polygon && isCollider2Circle) {
        return cc.Intersection.polygonCircle(world1.points, world2);
    } else if (isCollider1Circle && isCollider2Polygon) {
        return cc.Intersection.polygonCircle(world2.points, world1);
    } else {
        // cc.errorID(6601, cc.js.getClassName(collider1), cc.js.getClassName(collider2));
    }
    return false;
}

最後再結合四叉樹碰撞,檢測代碼如下。

check(colliders: cc.Collider[], testCollider: cc.Collider) {
    const ret: { retrieve: cc.Collider[], contacts: cc.Collider[] } = { retrieve: [], contacts: [] };

    // 四叉樹清理
    this._tree.clear();
    const collisionManager = cc.director.getCollisionManager();
    collisionManager['updateCollider'](testCollider);
    for (let i = 0, l = colliders.length; i < l; i++) {
        const collider = colliders[i];
        // 更新碰撞體世界aabb
        collisionManager['updateCollider'](collider);
        const aabb = collider['world'].aabb;
        const rect = { x: aabb.x, y: aabb.y, height: aabb.height, width: aabb.width, collider: collider };
        // 四叉樹插入
        this._tree.insert(rect)
    }
    // 四叉樹抓出待檢查的對象(屬於那個塊的所有節點)
    const retrieveObjects = this._tree.retrieve(testCollider['world'].aabb);
    retrieveObjects.forEach(element => {
        ret.retrieve.push(element.collider);
        // 抓出來後檢查碰撞
        if (testContact(element.collider, testCollider)) {
            ret.contacts.push(element.collider);
        }
    });

    return ret;
}

更多精彩

shader頂點動畫之旗子水紋
2D實現背景圖3D滾動效果
物理挖洞系列
畫線紋理之繩子

█ 漸變色的實現 █ █ 精靈之網格模式 █ █ shader動畫之loading █ █ js的三位一體 █ █ shader 之攻擊閃白(+入門資料整理) █ █ 物理流體(歡樂水杯) █ █ 瞄準線之拋物線 █ █ 隨機(正態分佈)飛濺運動 █ █ 貪喫蛇之平滑移動 █ █ 雷達圖的實現 █ █ 分形着色器(數學之美) █ █ shader 之漸變過渡 █ █ 初探 gizmo 使用 █ █ shader 之卷積濾鏡 █ █ 旗幟效果(meshRenderer) █ █ 多邊形裁剪(meshRenderer) █ █ 高拋平拋發射 █ █ 水紋效果(片元着色器) █ █ 2019年原創(黑歷史) █ █ 原創文章導航 █

小結

分塊!尋找對應的分塊檢測!

以上爲白玉無冰使用 Cocos Creator v2.3.3 實現 "四叉樹與碰撞檢測" 的技術分享。如果對你有點幫助,歡迎分享給身邊的朋友。

成就我們的恰恰就是那些不斷重複做的事情。因此,優秀不是一種行爲,而是一種習慣。

原文鏈接
完整代碼(見readme)
原創文章導航

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章