目录
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