使用Matter.js的方法指南

914 阅读7分钟

在本系列的上一篇教程中,你了解了Matter.js中的World和Engine模块。这两个模块中的方法是为了一次控制多个主体或整个世界的行为。然而,在某些时候,有必要对你的世界中的单个体的属性进行控制。

例如,你可能想在一个特定的物体上施加一些力或改变其摩擦系数。在这种情况下,Matter.js中的Body模块会有很大的帮助。这个模块包含很多方法和属性,让你为各种物理属性指定数值,从质量到恢复系数。在本教程中,你将了解所有这些方法和属性以及如何正确使用它们。

缩放、旋转和平移一个体

你可以通过使用rotate(body, rotation) 方法来旋转Matter.js世界中的任何刚性体。旋转是相对于体的当前角度而言的,它不会给它带来任何角速度。旋转角度是以弧度为单位的。

你也可以通过使用scale(body, scaleX, scaleY, [point]) 方法来缩放一个体。参数scaleXscaleY 分别指定水平和垂直方向上的缩放量。请记住,任何这样的缩放也会更新体的物理属性,比如它的质量、面积和惯性。第四个参数指定了发生缩放的周围点。当没有指定时,缩放点的默认值被认为是体的中心。

可以使用translate(body, translation) 方法,通过给定的矢量相对于当前位置移动一个体。平移参数指定了物体相对于其当前位置的新位置。下面是演示中的代码部分,用于缩放、旋转和移动盒子。

设置速度和施加力

你也可以使用setVelocity(body, velocity) 方法给一个对象施加线性速度。以这种方式施加速度并不改变相关物体的角度、施加的力或位置。物体的位置或角度可能会发生变化,但库中并没有特别将它们设置为任何数值。它们的值是由作用在物体上的其他力决定的,比如摩擦力。

就像线速度一样,你也可以用setAngularVelocity(body, velocity) 方法改变物体的角速度。在这种情况下,位置、角度和施加在物体上的力也保持不变。

你应该记住的一点是,速度在setVelocity() 中是一个矢量,在setAngularVelocity() 中是一个数字:

document.querySelector('#linear').addEventListener('click', function () {
    Body.setVelocity( box, {x: 10, y: -10});
});
document.querySelector('#angular').addEventListener('click', function () {
    Body.setAngularVelocity( box, Math.PI/6);
});

除了给物体赋予速度之外,你还可以给它们施加一个力矢量。applyForce(body, position, force) 方法可以用来对一个物体施加一个force 向量,从一个给定的position 。这个力可能会也可能不会导致对给定体施加扭矩。

下面的代码在体的中心位置施加了一个力。力的矢量是{x: 0, y: -0.05} 。这意味着施加的力将是纯垂直的,并且是向上的方向。你应该记住,在Matter.js中,向上方向的垂直力有一个负号。另一件值得注意的事情是,指定垂直力的数字是多么小。在Matter.js中,引力本身的数值只有1。

只要球不与任何墙壁或地板相撞,施加力后的球的运动似乎很自然。通常情况下,当事物与某些东西相撞时,我们希望它们会反弹回来。一个物体反弹的能量是由恢复系数决定的。

在Matter.js中,它的值默认被设置为零。这意味着,任何被设置为恢复系数的物体与其他物体相撞时,根本不会反弹回来。数值为1意味着物体将以与碰撞前相同的动能反弹回来。像0.5这样的值意味着物体反弹时的动能只有它之前动能的50%。一个物体的恢复值可以用restitution 键来控制。

在某些模拟中,你可能需要改变不同物体之间的摩擦力。这可以通过friction,frictionAir, 和frictionStatic 键来实现:

  • friction 键指定了一个体的运动摩擦力的值。它的数值可以在0和1之间。数值为0意味着一个物体一旦被设定为运动状态,就可以无限期地保持运动。阻止它的唯一方法是施加一些其他的外力。两个物体之间的摩擦力的最终值是通过公式Math.min(bodyA.friction, bodyB.friction) 来确定的。
  • frictionStatic 键指定身体处于静止状态时的摩擦力值。静态摩擦力的默认值是0.5。较高的值意味着需要较大的力来使物体运动。
  • frictionAir 键用于指定身体与周围空气之间的摩擦力值。一个较高的值意味着身体在空气中运动时将很快减速。空气摩擦的影响是非线性的。
document.querySelector('#force').addEventListener('click', function () {
    Body.applyForce( ball, {x: ball.position.x, y: ball.position.y}, {x: 0.04, y: 0});
});


document.querySelector('#vforce').addEventListener('click', function () {
    Body.applyForce( ball, {x: ball.position.x, y: ball.position.y}, {x: 0, y: -0.04});
});

document.querySelector('#red-friction').addEventListener('click', function () {
  ball.friction = 0.05;
  ball.frictionAir = 0.0005;
  ball.restitution = 0.9;
});

document.querySelector('#res-friction').addEventListener('click', function () {
  ball.friction = 0.1;
  ball.frictionAir = 0.001;
  ball.restitution = 0;
});

控制身体的渲染

到目前为止,我们还没有指定渲染车身时要使用的颜色、轮廓宽度或笔画样式。所有这些属性都嵌套在render 键中。fillStyle 属性接受一个字符串来指定渲染主体的填充样式。lineWidth 属性接受一个数字,该数字定义了创建主体轮廓时要使用的线宽。

值为零意味着根本不会呈现任何线条。strokeStyle 属性可用于指定渲染车身轮廓时要使用的笔画样式。你可以通过将visible 键设置为false ,来防止车身完全被渲染。你想要渲染的车身的不透明度可以通过opacity 键来控制。

你也可以使用图像而不是简单的颜色和轮廓来渲染一个身体。使用精灵渲染身体的参数是用一组不同的属性来指定的。texture 属性定义了应该被用作精灵纹理的图像路径。

xOffsetyOffset 属性可用于定义精灵在各自轴上的偏移。同样地,你可以使用xScaleyScale 属性来定义精灵的X轴和Y轴的缩放。下面是一些代码,它将我们的球的浅蓝色背景替换为来自开放游戏艺术网站的足球精灵

const ball = Bodies.circle(90, 280, 20, {
  render: {
    sprite: {
      texture: "path/to/soccer_ball.png",
      xScale: 0.4,
      yScale: 0.4
    }
  }
});

改变物理属性

你已经看到了如何在Matter.js中为一个物体指定摩擦力或恢复系数。还有很多其他的属性,其值可以用同样的方式指定。另一方面,有些属性是只读的,不能由你改变。

你可以通过使用position 键来设置一个物体在世界中的位置,该键接受一个矢量作为其值。你也可以使用mass 属性来指定一个物体的质量,但这样你也必须为inverseMass 属性设置一个值,这个值是用1/mass 计算的。控制一个物体的质量的一个更好的方法是借助于density 属性。

一旦你改变了一个物体的密度,它的质量将根据其面积自动计算。这样,你也可以根据不同物体的密度来区分它们。例如,一个使用岩石作为精灵的物体应该比一个使用足球作为精灵的相同大小的物体有更高的密度。

一些属性如speed,velocity, 和angularVelocity 是只读的,但它们的值可以通过适当的方法如setAngularVelocity()setVelocity() 来设置。你可以在文档中阅读更多关于Body模块的不同属性。

总结

在本教程中,你已经了解了Matter.js库中Body模块的所有重要方法和属性。了解这些不同的属性以及它们的作用,可以帮助你创建更真实的现实生活中的物理学模拟。在本系列的下一个也是最后一个教程中,你将学习Matter.js中的复合模块。