Matter-JS collisionFilter 碰撞過濾器
collisionFilter 碰撞過濾器
1、Matter.js 建立的物體可以為它們設定碰撞規則,如哪些物體相互應該碰撞,而哪些物體相互之間則不應該發生碰撞。
2、Body(剛體)提供了一個 collisionFilter 屬性,其值是一個 json 陣列,可選值有:group,category,mask。預設值如下:
collisionFilter: {
category: 0x0001,
mask: 0xFFFFFFFF,
group: 0
}
3、使用這三個屬性,可以設計出很複雜的碰撞關係,其中碰撞規則如下:
物體的 group 相等,且 group > 0 時,則物體之間會發生碰撞;Matter.Body.nextGroup(false)可以生成從-1開始遞減的整數
物體的 group 相等,且 group < 0 時,則物體之間不發生碰撞;Matter.Body.nextGroup(true)可以生成從1開始遞增的整數
--不滿足上述兩種情況時,則根據category和mask進行判斷--
category 代表一個碰撞分類,其值可為1,2,4,8...直到 2^31,mask 為碰撞集合(category集合)a 和 b碰撞情況:a 的 mask 必須包含 b 的 category,同時 b 的 mask 也必須包含 a 的 category,即
(a.category & b.mask) !== 0 && (b.category & a.mask) !== 0
group 組
通過這個例子就可以直觀的看到到底如何才算是物體碰撞。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Matter-JS</title> <!--matter-js cdnjs地址--> <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.12.0/matter.js"></script> <!--<script src="../js/matter_0.14.2.js"></script>--> <script type="text/javascript"> var stageWidth = 800;//舞臺寬度 var stageHeight = 500;//舞臺高度 var Engine = Matter.Engine;//引擎 var Render = Matter.Render;//渲染器 var World = Matter.World;//世界 var MouseConstraint = Matter.MouseConstraint;//滑鼠控制 var Bodies = Matter.Bodies;//內建常見剛體 var Composites = Matter.Composites;//符合材料 var Composite = Matter.Composite;//混合體 var Common = Matter.Common;//公用模組 var Body = Matter.Body;//剛體 window.onload = function () { matterJS(); } /**Matter-JS*/ function matterJS() { var engine = Engine.create();//建立引擎 var render = Render.create({//建立渲染器 engine: engine,//渲染建立好的引擎 /**渲染頁面的body元素,即會在body標籤自動新建<canvas>畫布,同理如果element的值是某個div元素- * 則會在div下自動新建canvas,canvas的尺寸是options中的width、height * */ element: document.body, options: { width: stageWidth,//畫布的寬度 height: stageHeight,//畫布的高度 wireframes: true,//線框模式,預設false不使用線框模式 showAngleIndicator: true,//是否顯示角度,預設false showVelocity: true,//是否顯示速度,預設false showCollisions: true,//是否顯示碰撞點,預設false showBroadphase: false,//是否顯示寬頻,用於除錯,預設false showMousePosition: false // 滑鼠約束線 } }); Engine.run(engine);//執行引擎 Render.run(render);//執行渲染器 /**設定滑鼠控制*/ var mouseConstraint = MouseConstraint.create(engine, {}); /**Body.nextGroup(isNonColliding):下一個組ip值, * isNonColliding:表示非碰撞,為true時,第一次呼叫 nextGroup 時返回 -1,每呼叫一次則遞減1 * isNonColliding=false時,第一次呼叫 nextGroup 時返回 1,每呼叫一次則遞加1 */ var group = Body.nextGroup(true); console.log("group=" + group); var stack = Composites.stack(20, 20, 12, 4, 0, 0, function (x, y) { switch (Math.round(Common.random(0, 1, 2))) { /**為0時建立矩形*/ case 0: return Bodies.rectangle(x, y, Common.random(20, 50), Common.random(20, 50), { collisionFilter: {group: group} }); /**為1時建立多邊形*/ case 1: return Bodies.polygon(x, y, Math.round(Common.random(3, 8)), Common.random(20, 50), { collisionFilter: {group: group} }); /**為2時建立圓形*/ case 2: return Bodies.circle(x, y, Common.random(10, 20), { collisionFilter: {group: group} }); } }); /**將物體以及滑鼠控制新增到世界中*/ World.add(engine.world, [mouseConstraint, stack]); /**為世界4周新增4面牆*/ World.add(engine.world, create4Wall(Bodies)); } /**建立4面牆-強制物體在牆內運動*/ function create4Wall(Bodies) { var ground_top = Bodies.rectangle(stageWidth / 2, 0, stageWidth, 40, {isStatic: true}); var ground_right = Bodies.rectangle(stageWidth, stageHeight / 2, 40, stageHeight, {isStatic: true}); var ground_bottom = Bodies.rectangle(stageWidth / 2, stageHeight, stageWidth, 40, {isStatic: true}); var ground_left = Bodies.rectangle(0, stageHeight / 2, 40, stageHeight, {isStatic: true}); return [ground_top, ground_right, ground_bottom, ground_left]; } </script> </head> <body> </body> </html>
如上所示 collisionFilter: {group: group},因為 Body.nextGroup(true) 只調用了1次,則所有物體的 group 值為-1,此時物體相互之間是沒有碰撞的。
當 var group = Body.nextGroup(false); 時,因為 Body.nextGroup(false) 只調用了1次,則所有物體的 group 值為 1,此時物體相互之間會發生碰撞。