🔥一个超好用的JS物理引擎库-matterjs

6,244 阅读4分钟

🔥一个超好用的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);

captured.gif 这里注意在创建ground时候,新增了个属性isStatic: true,这句话的意思是当前这个物体是静态的,即:只是一个刚体,拥有碰撞器,但是不会受重力影响,不会收到物理碰撞效果。

engine.timing.timeScale = 0.1 可以设置冻结时间来控制慢放或者快放

二、创建简单的物理几何刚体

1. 创建圆和矩形

const box = Bodies.rectangle(400, 200, 80, 80);
const cir = Bodies.circle(200, 200, 40);

captured (1).gif

2. 创建一个正多边形

  • Bodies.rectangle(x, y, n, r, option):n为正多边形的边数,r为正多边形半径
const pl = Bodies.polygon(200, 100, 8, 80, { 
  chamfer: { radius: 30 }
})

image.png

3. 创建一个梯形

  • Bodies.trapezoid(x, y, w, h, slope): slope为斜率,当斜率为1时候,是三角形
const pl = Bodies.trapezoid(200, 100, 80, 100, 0.5)

image.png

const pl = Bodies.trapezoid(200, 100, 80, 100, 1)

image.png

三、创建组合物理几何刚体

  • 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]);

captured (2).gif

四、碰撞检测

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)

captured (3).gif

六、鼠标操作约束

如果你想使用鼠标进行交互,那么可以使用Matter.MouseConstraint 进行操作。

const mouseConstraint = MouseConstraint.create(engine)
// 将他们加入到这个物理引擎中
Composite.add(engine.world, [r, ground, mouseConstraint]);

captured (4).gif

七、其它配置和方法

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]);

image.png

3. 摩擦力

matterjs摩擦力有三种:

  • 普通摩擦力 friction
  • 空气摩擦力 frictionAir
  • 静止摩擦力 frictionStatic
const ground = Bodies.rectangle(0, 300, 80000, 50, { 
  friction: 1
})

matterJs还可以创建很多其它物理材质的物体,比如说,软球,小汽车,牛顿摆等等,大家可以去官方Demo查看更多的例子,如果你觉得本文帮助了你,请您给我个攒👍🏻。