1. 程式人生 > >Matter-JS Composites 混合材料 · 上

Matter-JS Composites 混合材料 · 上

 

目錄

Composites

stack 堆疊

chain 鏈

softBody 軟體


Composites

1、多個剛體通過約束組合在一起,稱為複合體。複合體對外當作一個剛體,複合體的物理屬性是通過所包含的剛體的屬性綜合計算出來的。

2、Matter.Composite 模組包含用於建立和處理複合體的方法。

3、Matter.Composites 模組提供了幾種特別的複合材料,如鏈:Composites.chain、牛頓擺:Composites.newtonsCradle、軟體:Composites.softBody、汽車:Composites.car 、堆疊:Composites.stack、網格:mesh、金字塔:pyramid。

4、Matter.Composites 模組提供了幾種特別的複合材料,如鏈:Composites.chain、牛頓擺:Composites.newtonsCradle、軟體:Composites.softBody、汽車:Composites.car 、堆疊:Composites.stack、網格:mesh、金字塔:pyramid

5、本文主要講解 堆疊:Composites.stack、鏈:Composites.chain、軟體:Composites.softBody

stack 堆疊

/**Create a new composite containing bodies created in the callback in a grid arrangement. This function uses the body's bounds to prevent overlaps.(建立一個新的組合,其中包含在網格排列的回撥中建立的實體,此函式使用主體邊界來防止重疊。)

 * @method stack
 * @param {number} xx                 複合體起點(左上角)的x座標
 * @param {number} yy                 複合體起點(左上角)的y座標
 * @param {number} columns       堆疊的列數
 * @param {number} rows             堆疊的行數
 * @param {number} columnGap   相鄰列的距離(px)
 * @param {number} rowGap         相鄰行的距離(px) 
 * @param {function} callback        網格排列的回撥函式,用於建立堆疊的物體
 * @return {composite} A new composite containing objects created in the callback
 */
Composites.stack = function(xx, yy, columns, rows, columnGap, rowGap, callback) 

<!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 type="text/javascript">
        window.onload = function () {
            var Engine = Matter.Engine;//引擎.引擎模組包含建立和操作引擎的方法
            var Render = Matter.Render;//基於HTML5畫布的渲染器
            var World = Matter.World;//演出舞臺. Matter.js 中任何的物體都需要一個舞臺/容器,而存放這些物體的地方,則稱之為World(世界)
            var Bodies = Matter.Bodies;//用於建立各種形狀的物體,物體必須新增到Wolrd中,然後由引擎執行世界
            var Composites = Matter.Composites;//混合體

            var engine = Engine.create();//建立引擎
            var render = Render.create({//建立render(渲染器):渲染上面建立好的物理引擎(engine),渲染物件是html網頁的body
                engine: engine,
                element: document.body,
                options: {//指定舞臺大小
                    width: 800,
                    height: 500,
                    wireframes: true,//是否啟用線框圖,預設啟用
                    showVelocity: true,//是否顯示速度,預設不顯示
                    showAngleIndicator: true//是否顯示角度
                }
            });
            Engine.run(engine);//執行引擎
            Render.run(render);//執行渲染器

            /**新增滑鼠控制:Matter.MouseConstraint.create(engine, options)
             * 第一個引數是引擎 engine,第二個引數是一個json物件,用於設定屬性,
             */
            var mouseConstraint = Matter.MouseConstraint.create(engine, {});

            /**建立複合體,使用 堆疊符合材料 stack(xx, yy, columns, rows, columnGap, rowGap, callback)
             * 複合體啟動座標為(50,100)、5 列、3行、列相隔距離為20px,行相距0px。堆疊的物體在毀掉函式中建立
             * @type {composite}
             */
            var stack_rectangle = Composites.stack(20, 10, 5, 3, 20, 0, function (x, y) {
                //剛體和複合材料結合成複合體,這裡堆疊的是矩形,矩形寬 50,高20,中心位置為(x,y)
                return Bodies.rectangle(x, y, 50, 20);
            });
            //上面堆疊的是矩形,這裡堆疊圓形,同理還可以堆疊其它剛體,如多邊形、梯形等
            var stack_circle = Composites.stack(280, 100, 7, 5, 0, 0, function (x, y) {
                //建立圓形,半徑20,圓心座標為(x,y)
                return Bodies.circle(x, y, 20);
            });
            //將物體新增的世界中,含滑鼠控制
            World.add(engine.world, [stack_rectangle, stack_circle, mouseConstraint]);

            //建立上下左右四面牆(矩形),isStatic:true表示物體靜止,用於保證物體只能在此範圍內移動
            var ground_1 = Bodies.rectangle(400, 0, 800, 50, {isStatic: true});
            var ground_2 = Bodies.rectangle(800, 250, 50, 500, {isStatic: true});
            var ground_3 = Bodies.rectangle(400, 500, 800, 50, {isStatic: true});
            var ground_4 = Bodies.rectangle(0, 250, 50, 800, {isStatic: true});
            //再將四面牆(矩形)新增到世界中
            World.add(engine.world, [ground_1, ground_2, ground_3, ground_4]);
        }
    </script>
</head>
<body>
</body>
</html>

官網demo:http://brm.io/matter-js/demo/#stack

chain 鏈

1、官網API地址:http://brm.io/matter-js/docs/classes/Composites.html#method_chain

/**Chains all bodies in the given composite together using constraints.(使用約束將給定組合中的所有實體連結在一起)
* @method chain
* @param {composite} composite     被連結的複合體
* @param {number} xOffsetA            被連結物體A的x方向偏移量,[-0.5,0.5],0表示中心位置,左右平分0.5
* @param {number} yOffsetA            被連結物體A的y方向偏移量,[-0.5,0.5],0表示中心位置,上下平分0.5
* @param {number} xOffsetB            被連結物體B的x方向偏移量,[-0.5,0.5],0表示中心位置,左右平分0.5  
* @param {number} yOffsetB            被連結物體B的y方向偏移量,[-0.5,0.5],0表示中心位置,上下平分0.5
* @param {object} options
* @return {composite} A new composite containing objects chained together with constraints
*/
Composites.chain = function(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options)

<!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 type="text/javascript">
        var stageWidth = 800;//舞臺寬度
        var stageHeight = 500;//舞臺高度
        window.onload = function () {
            var Engine = Matter.Engine;//引擎
            var Render = Matter.Render;//渲染器
            var World = Matter.World;//世界
            var Constraint = Matter.Constraint;//約束
            var MouseConstraint = Matter.MouseConstraint;//滑鼠控制
            var Composites = Matter.Composites;//複合材料
            var Bodies = Matter.Bodies;//物體

            var engine = Engine.create();//建立引擎
            var render = Render.create({//建立渲染器
                engine: engine,//渲染建立好的引擎
                element: document.body,//渲染頁面的body元素
                options: {
                    width: stageWidth,
                    height: stageHeight,
                    //wireframes: false,//是否顯示邊線框
                    showVelocity: true//是否顯示速度
                }
            });

            Engine.run(engine);//執行引擎
            Render.run(render);//執行渲染器

            /**創造兩個橋墩————固定的兩個豎向矩形代替*/
            var bridge_left = Bodies.rectangle(100, 400, 50, 250, {isStatic: true});
            var bridge_right = Bodies.rectangle(700, 400, 50, 250, {isStatic: true});

            /**橋上的木板————使用堆疊的一排矩形代替
             * stack(xx, yy, columns, rows, columnGap, rowGap, callback)
             * xx,yy 表示堆疊的混合體起點座標;clumns 表示列數;rows 表示行數;columnGap表示列距;rowGap表示行距
             * callback中建立堆疊的物體——矩形
             * 注意:模板建立的位置要與橋墩配合好,否則鐵索會被拉伸到變形
             */
            var stack = Composites.stack(150, 250, 7, 1, 10, 0, function (x, y) {
                return Bodies.rectangle(x, y, 60, 30, {
                    chamfer: 15//chamfer 表示切角,這樣矩形4個角會有15度的圓角
                })
            });

            /**
             * 木板建立好之後,現在需要使用 Composites.chain 連結起來,chain 用於將混合體中的剛體進行連結
             * chain(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options)
             * composite:被連結的混合體,如下所示為上面建立好的木板混合體
             * xOffsetA、yOffsetA 表示A物體連結點的偏移量,注意取值為百分比形式:(0,0)表示在物體中心、(0.5,0)表示表示物體右側的中間位置、(0.5,-0.5)表示物體右上角
             * (-0.5,-0.5)表示物體左上角、(-0.5,0.5)表示物體左下角、其餘以此類推。
             * xOffsetB, yOffsetB 則表示被連結的B物體,連結操作針對的是相鄰物體,依次進行連結
             * 這裡為橋上的木板建立"上、中、下"3條鐵索進行連結。用鐵索將模板連線起來
             */
            Composites.chain(stack, 0.4, -0.3, -0.4, -0.3, {});
            Composites.chain(stack, 0.4, 0, -0.4, 0, {});
            Composites.chain(stack, 0.4, 0.3, -0.4, 0.3, {});

            /**將已經連結好的木板左側固定在左側橋墩上
             * Constraint.create 建立約束———— 將兩個物體通過約束點連線在一起,這個約束點就相當於一個釘子將兩個物體固定在一起
             * 其引數是一個json物件,主要引數有:bodyA,pointA,bodyB,pointB,length,stiffness等
             * bodyA 和 bodyB 分別被連線的兩個物體
             * pointA 和 pointB 表示約束點的位置,其值為向量,預設為{x=0,y:0}在物體中心位置。以物體中心為原點進行量相減(三角形法則)
             * bridge_left 為左側橋墩,pointA: {x: 0, y: -100}表示自身約束點在中心點往上偏移100px的位置
             * stack.bodies[0]:stack為橋面木板混合體,.bodies為獲取混合體中的剛體(陣列),[0]取第一塊木板
             * pointB: {x: -25, y: 0}:第一塊木板上的約束點位置,木板寬度為60,(-25,0)表示中心點往左偏移25px
             */
            var nailLeft = Constraint.create({
                bodyA: bridge_left,
                pointA: {x: 0, y: -100},
                bodyB: stack.bodies[0],
                pointB: {x: -25, y: 0}
            });

            /**使用約束(可以看成一個釘子)將最後一塊木板與右側橋墩連線起來————與上面同理*/
            var nailRight = Constraint.create({
                bodyA: stack.bodies[stack.bodies.length - 1],
                pointA: {x: 25, y: 0},
                bodyB: bridge_right,
                pointB: {x: 0, y: -100}
            });

            /**建立滑鼠控制*/
            var mouseConstraint = MouseConstraint.create(engine, {element: document.body});
            /**建立一個圓形堆疊複合體,用於從上往下掉落,2行8列*/
            var stack_circle = Composites.stack(stageWidth / 4, 10, 8, 2, 0, 0, function (x, y) {
                return Bodies.circle(x, y, 20);
            });

            World.add(engine.world, [stack_circle, mouseConstraint]);//新增掉落的堆疊圓形、滑鼠控制到世界中
            /**新增左右橋墩、左右釘子、以及橋面到世界中*/
            World.add(engine.world, [bridge_left, bridge_right, stack, nailLeft, nailRight]);
            World.add(engine.world, create4Wall(Bodies));//為世界4周新增4面牆
        }
        /**
         *建立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>

softBody 軟體

官網API:http://brm.io/matter-js/docs/classes/Composites.html#method_softBody

softBody 函式原始碼如下,本質是先建一個圓形的堆疊,然後使用網孔連線起來

/**建立一個簡單的類似軟體的物件
* Creates a simple soft body like object.
* @param {number} xx
* @param {number} yy
* @param {number} columns
* @param {number} rows
* @param {number} columnGap
* @param {number} rowGap
* @param {boolean} crossBrace
* @param {number} particleRadius
* @param {} particleOptions
* @param {} constraintOptions
* @return {composite} A new composite softBody
*/

Composites.softBody = function(xx, yy, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) {
     particleOptions = Common.extend({ inertia: Infinity }, particleOptions);
     constraintOptions = Common.extend({ stiffness: 0.2, render: { type: 'line', anchors: false } }, constraintOptions);

     var softBody = Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y) {
         return Bodies.circle(x, y, particleRadius, particleOptions);
     });

     Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions);

     softBody.label = 'Soft Body';

     return softBody;
 };

演示如下:

<!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 type="text/javascript">
        var stageWidth = 800;//舞臺寬度
        var stageHeight = 500;//舞臺高度
        window.onload = function () {
            var Engine = Matter.Engine;//引擎
            var Render = Matter.Render;//渲染器
            var World = Matter.World;//世界
            var Constraint = Matter.Constraint;//約束
            var MouseConstraint = Matter.MouseConstraint;//滑鼠控制
            var Composites = Matter.Composites;//複合材料
            var Bodies = Matter.Bodies;//物體

            var engine = Engine.create();//建立引擎
            var render = Render.create({//建立渲染器
                engine: engine,//渲染建立好的引擎
                element: document.body,//渲染頁面的body元素
                options: {
                    width: stageWidth,
                    height: stageHeight,
                    wireframes: false,//是否顯示邊線框
                    showVelocity: true//是否顯示速度
                }
            });

            Engine.run(engine);//執行引擎
            Render.run(render);//執行渲染器

            /**設定滑鼠控制*/
            var mouseConstraint = MouseConstraint.create(engine, {});

            /**
             * softBody(xx, yy, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions)
             * (xx,yy)為軟體中第一個物體的中心位置;軟體一共 columns 列,rows行;列距 columnGap,行距 rowGap;
             * crossBrace:表示是否十字架支撐,如果為true,則軟體中每個物體中會有十字架進行支撐;
             * particleRadius 表示軟體中的每個圓形的半徑。
             * 軟體原始碼建立的基本流程:
             * 1、現根據引數建立一個圓形堆疊————即裡面是一個個圓形排列而成
             * var softBody = Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y) {
             *      return Bodies.circle(x, y, particleRadius, particleOptions);});
             * 2、然後根據圓形堆疊softBody在建立網孔(mesh)
             * Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions);
             * particleOptions 為圓形設定的選項
             *      friction:摩擦力、collisionFilter:碰撞過濾器,-1表示軟體中的小球不會相互碰撞;render.visible 表示小球不可見
             * constraintOptions 表示約束選項:stiffness 剛度大小
             */
            var particleOptions = {friction: 0.0001, collisionFilter: {group: -1}, render: {visible: true}};
            var constraintOptions = {stiffness: 0.8};
            var columns = 20;//軟體中圓形的列數
            var cloth = Composites.softBody(stageWidth / 5, 10, columns, 15, 0, 0, false, 12, particleOptions, constraintOptions);

            /**將最上方的一排球進行固定*/
            for (var i = 0; i < columns; i++) {
                cloth.bodies[i].isStatic = true;
            }

            /**建立一個活動的球*/
            var circle = Bodies.circle(stageWidth / 2, 20, 50);
            World.add(engine.world, [cloth, circle, mouseConstraint]);//將軟體與滑鼠控制新增到世界中
            World.add(engine.world, create4Wall(Bodies));//為世界4周新增4面牆
        }
        /**
         *建立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>

當將 var particleOptions = {friction: 0.0001, collisionFilter: {group: -1}, render: {visible: true}}; 中的 true 改為 false 時:

官網demo地址:http://brm.io/matter-js/demo/#cloth