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 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
* 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