1. 程式人生 > >matter.js技術 | collisionFilter 設定碰撞規則

matter.js技術 | collisionFilter 設定碰撞規則

matter.js QQ交流群:796728825

collisionFilter屬性分析

Collisions between two bodies will obey the following rules:
* - If the two bodies have the same non-zero value of collisionFilter.group,
* they will always collide if the value is positive, and they will never collide
* if the value is negative.
* - If the two bodies have different values of collisionFilter.group

or if one
* (or both) of the bodies has a value of 0, then the category/mask rules apply as follows:
*
* Each body belongs to a collision category, given by collisionFilter.category. This
* value is used as a bit field and the category should have only one bit set, meaning that
* the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32
* different collision categories available.
*
* Each body also defines a collision bitmask, given by collisionFilter.mask
which specifies
* the categories it collides with (the value is the bitwise AND value of all these categories).
*
* Using the category/mask rules, two bodies A and B collide if each includes the other’s
* category in its mask, i.e. (categoryA & maskB) !== 0 and (categoryB & maskA) !== 0

* are both true.

漢化解釋:
collisionFilter有三個屬性:group category mask
簡單的碰撞規則可以用group解決:

group屬性為數字型別。在兩個物體的group屬性值相同的前提下,如果這個數字為負數,則這兩個物體不會碰撞,如果這個數字為正數,則這兩個物體會碰撞。
如果兩個物體的group屬性不相同,或者有一個為0(或兩個都為0),則需要根據其他兩個屬性來判斷碰撞規則。

更復雜的碰撞關係:

category屬性為16進位制數字,預設為0x0001,其值只能為2的冪級數,如0x0002,0x0004,0x0008,(比如,0x0007是不合法的,不會觸發碰撞規則)
mask屬性設定可以與該物體碰撞的category。

舉例:
A物體的category為0x0002,B物體的category為0x0004
C物體若要與A物體碰撞,其mask應為A的category,即0x0002
C物體若要與B物體碰撞,其mask應為B的category,即0x0004
C物體若要與A物體、B物體同時碰撞,其mask應同時包含為A和B的category,即 0x0002 | 0x0004

category必須與mask配合使用才有效,因為mask的預設值包含了所有的category,預設可以與所有物體發生碰撞。

例子A、設定group值,使得同類物體不能碰撞,不同類物體可以碰撞:

紅綠藍三種顏色的物體,同種顏色的不會發生碰撞,不同顏色的才會發生碰撞

這裡寫圖片描述

    var stack_red=Composites.stack(200,200,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"red",
                lineWidth:4
            },
            collisionFilter:{
                group:-1
            }
        })
    });
    var stack_green=Composites.stack(200,400,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"green",
                lineWidth:4
            },
            collisionFilter:{
                group:-2
            }
        })
    });
    var stack_blue=Composites.stack(200,500,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"blue",
                lineWidth:4
            },
            collisionFilter:{
                group:-3
            }
        })
    });

*三種顏色物體的group不同,所以不同顏色的會發生碰撞
而同色物體的group都相同且為負數,所以同色物體不會發生碰撞*

例子B、設定category與mask,使得同類物體可以碰撞,不同類物體不可以碰撞:

紅綠藍三種顏色的物體,同種顏色的發生碰撞,不同顏色的不會發生碰撞

這裡寫圖片描述

    var stack_red=Composites.stack(0,200,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"red"
            },
            collisionFilter:{
                category:0x0002,
                mask:0x0002 | 0x0001
            }
        })
    });
    var stack_green=Composites.stack(100,400,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"green"
            },
            collisionFilter:{
                category:0x0004,
                mask:0x0004  | 0x0001
            }
        })
    });
    var stack_blue=Composites.stack(400,500,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"blue"
            },
            collisionFilter:{
                category:0x0008,
                mask:0x0008 | 0x0001
            }
        })
    });


    var ground=Bodies.rectangle(400,900,900,20,{
        isStatic:true,
    });

    World.add(world,[stack_red,stack_green,stack_blue,ground]);

由於ground未設定collisionFilter,所以,其category為預設的0x0001(滑鼠也是),為了讓三種物體能與地面碰撞(及與滑鼠互動),所以,三種顏色的mask都包含了0x0001
三種顏色的物體的mask分別包含了自身的category,所以,每種顏色的物體可以與本色物體碰撞。
如果其mask不包含0x0001,則該物體會穿透地面,亦不能與滑鼠互動。

例子C、設定category與mask,使得同類物體可以碰撞,紅色與藍色物體也可碰撞:

紅綠藍三種顏色的物體,同種顏色的發生碰撞,紅色和藍色也可以碰撞,紅色和綠色不能碰撞。綠色和藍色也不能碰撞

    var stack_red=Composites.stack(0,200,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"red"
            },
            collisionFilter:{
                category:0x0002,
                mask:0x0002 | 0x0001 | 0x0008   //此處改動,增加藍色物體的category
            }
        })
    });
    var stack_green=Composites.stack(100,400,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"green"
            },
            collisionFilter:{
                category:0x0004,
                mask:0x0004  | 0x0001 
            }
        })
    });
    var stack_blue=Composites.stack(400,500,4,1,0,0,function(x,y){
        return Bodies.circle(x,y,20,{
            render:{
                fillStyle:"blue"
            },
            collisionFilter:{
                category:0x0008,
                mask:0x0008 | 0x0001 | 0x0002   //此處改動,增加紅色物體的category
            }
        })
    });


    var ground=Bodies.rectangle(400,900,900,20,{
        isStatic:true,
    });

    World.add(world,[stack_red,stack_green,stack_blue,ground]);

紅色與藍色物體若要碰撞,要分別為其mask新增*對方的*category