🔥一个超好用的JS物理引擎库-matterjs
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
matter.js是一个JS的2D的物理引擎,我们可以单独使用它或者用它配合Canvas,来实现一些物理效果,或者一些高级的Canvas动画。
一、安装和使用
1.安装
- 使用
script
标签引入使用 - 使用
npm install matter-js
安装使用
2.初始化
// 起别名方便后面使用
const Engine = Matter.Engine,
Render = Matter.Render,
Runner = Matter.Runner,
Bodies = Matter.Bodies,
Composite = Matter.Composite;
// 创建一个物理引擎
const engine = Engine.create();
engine.gravity.y = 9.8 // 设置重力
// 创建一个渲染器
const render = Render.create({
element: document.body,
engine: engine,
options: {
pixelRatio: 1, // 设置像素比
background: '#fafafa', // 全局渲染模式时背景色
wireframeBackground: '#222', // 线框模式时背景色
hasBounds: false,
wireframes: true, // 线框模式
showSleeping: true, // 刚体睡眠状态
showDebug: false, // Debug 信息
showBroadphase: false, // 粗测阶段
showBounds: false, // 刚体的界限
showVelocity: false, // 移动刚体时速度
showCollisions: false, // 刚体碰撞点
showSeparations: false, // 刚体分离
showAxes: false, // 刚体轴线
showPositions: false, // 刚体位置
showAngleIndicator: false, // 刚体转角指示
showIds: false, // 显示每个刚体的 ID
showVertexNumbers: false, // 刚体顶点数
showConvexHulls: false, // 刚体凸包点
showInternalEdges: false, // 刚体内部边界
showMousePosition: false // 鼠标约束线
}
});
// 创建一个方块和一个地面
var box = Bodies.rectangle(400, 200, 80, 80);
var ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });
// 将他们加入到这个物理引擎中
Composite.add(engine.world, [box, ground]);
// 运行这个渲染器
Render.run(render);
// 创建一个运行环境,类似于U3D的Update函数
var runner = Runner.create();
// 开始渲染运行
Runner.run(runner, engine);
这里注意在创建ground时候,新增了个属性isStatic: true,这句话的意思是当前这个物体是静态的,即:只是一个刚体,拥有碰撞器,但是不会受重力影响,不会收到物理碰撞效果。
engine.timing.timeScale = 0.1 可以设置冻结时间来控制慢放或者快放
二、创建简单的物理几何刚体
1. 创建圆和矩形
const box = Bodies.rectangle(400, 200, 80, 80);
const cir = Bodies.circle(200, 200, 40);
2. 创建一个正多边形
- Bodies.rectangle(x, y, n, r, option):n为正多边形的边数,r为正多边形半径
const pl = Bodies.polygon(200, 100, 8, 80, {
chamfer: { radius: 30 }
})
3. 创建一个梯形
- Bodies.trapezoid(x, y, w, h, slope): slope为斜率,当斜率为1时候,是三角形
const pl = Bodies.trapezoid(200, 100, 80, 100, 0.5)
const pl = Bodies.trapezoid(200, 100, 80, 100, 1)
三、创建组合物理几何刚体
- Body.create({ parts: [shape1, shape2, ...] })
创建一个三角形和矩形的组合体
const t1 = Bodies.trapezoid(200, 100, 80, 100, 1)
const r = Bodies.rectangle(200, 185, 80, 100)
const cp = Body.create({
parts: [t1, r]
})
const ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });
// 将他们加入到这个物理引擎中
Composite.add(engine.world, [cp, ground]);
四、碰撞检测
Events.on(engine, 'collisionStart', function(e) {
const pairs = e.pairs;
pairs.forEach(pair => {
console.log(pair);
})
})
pairs 是一个数组,其中包含所有的碰撞对,遍历这个数组,可以拿到每一对碰撞对象的相关信息。
五、力的施加
- Body.applyForce(shape, shape.position, { x: number, y: number })
shape为被施加力的物体,x、y分别代表受力物体在x、y的受力大小。
const r = Bodies.rectangle(200, 200, 100, 50)
const ground = Bodies.rectangle(0, 300, 80000, 50, { isStatic: true })
// 将他们加入到这个物理引擎中
Composite.add(engine.world, [r, ground]);
setTimeout(() => {
Body.applyForce(r, r.position, {
x: 0.2,
y: 0
})
}, 4000)
六、鼠标操作约束
如果你想使用鼠标进行交互,那么可以使用Matter.MouseConstraint 进行操作。
const mouseConstraint = MouseConstraint.create(engine)
// 将他们加入到这个物理引擎中
Composite.add(engine.world, [r, ground, mouseConstraint]);
七、其它配置和方法
1. 可以为创建的物体设置弹性和密度
const ground = Bodies.rectangle(0, 300, 80000, 50, {
density: 1, // 密度
restitution: 0.8, // 弹性
isStatic: true
})
2. Composites.chain() 创建锁链
const group = Body.nextGroup(true);
const ropeA = Composites.stack(
100,
50,
8,
1,
10,
10,
function (x: number, y: number) {
return Bodies.rectangle(x, y, 50, 20, {
collisionFilter: { group: group },
});
}
);
Composites.chain(ropeA, 0.5, 0, -0.5, 0, {
stiffness: 0.8,
length: 2,
render: { type: "line" },
});
Composite.add(
ropeA,
Constraint.create({
bodyB: ropeA.bodies[0],
pointB: { x: -25, y: 0 },
pointA: { x: ropeA.bodies[0].position.x, y: ropeA.bodies[0].position.y },
stiffness: 0.5,
})
);
const mouseConstraint = MouseConstraint.create(engine)
// 将他们加入到这个物理引擎中
Composite.add(engine.world, [ropeA, mouseConstraint]);
3. 摩擦力
matterjs摩擦力有三种:
- 普通摩擦力 friction
- 空气摩擦力 frictionAir
- 静止摩擦力 frictionStatic
const ground = Bodies.rectangle(0, 300, 80000, 50, {
friction: 1
})
matterJs还可以创建很多其它物理材质的物体,比如说,软球,小汽车,牛顿摆等等,大家可以去官方Demo查看更多的例子,如果你觉得本文帮助了你,请您给我个攒👍🏻。