来源:程序员成长指南作者:德育总监
如有侵权,请联系我们删除。
本文简介
欢迎拨打《物理世界的互动之旅:Matter.js入门指南》。
本文介绍Matter.js,一个功能强大且易于使用的JavaScript 物理引擎库。
介绍Matter.js的基本概念,包括引擎、世界、对象和约束。
本文还提供了丰富的代码示例,帮助同事更好地理解如何使用Matter.js 创建令人惊叹的物理场景(先画个饼吧~)。
本文是我的学习笔记,对某些概念的解释或理解可能存在差距。如果您发现本文有任何错误或遗漏,请自行调整呼吸频率。换衣服好麻烦啊~
本文的前1000 字是关于一些基本概念的。如果您感到无聊,请先阅读以下内容,然后再回来复习基本概念。
Matter.js是什么?
在现实世界中,物理学无处不在。从行星和恒星的运动到电子的运动,物理定律描述了我们周围几乎所有事物的运动和相互作用。
在计算机科学中,物理引擎是模拟物理现象的软件程序。这些通常用于创建物理游戏、虚拟现实和模拟等应用程序。物理引擎可以模拟重力、碰撞、摩擦等各种现象。物理引擎通常非常复杂,因为它们需要模拟各种现实世界的效果。
事实上,有几个3D 库可以在Web 浏览器中模拟真实世界的物理现象,例如用于2D 的Matter.js [1] 和P2.js [2]。 `Cannon.js`[3]、`ammo.js`[4] 等
由于这篇文章是关于Matter.js 的,所以我在这里只会说Matter.js 的优点。
Matter.js 是一个非常强大的JavaScript2D 物理引擎,可帮助您在Web 应用程序中实现逼真的物理效果。
Matter.js 提供可定制的碰撞检测、重力、机械效果和运动控制功能,可以快速轻松地构建交互式物理模拟。无论是模拟游戏、模型构建还是实验室实验,Matter.js 都能满足您的需求。
Matter.js 官网[5]
基础概念
在学习Matter.js 之前,您需要了解一些基本概念。本文是一篇介绍性文章,仅介绍常用的基本概念。
模块名称说明Engine 引擎Engine 是Matter.js 的核心组件,用于管理物理世界中的所有对象并计算它们的运动和交互。用于模拟真实环境。渲染器渲染器用于可视化物理世界中的对象。这意味着可以将对象渲染到屏幕上。复合体是包含多个刚体和约束的容器,可以将其作为单个物理对象进行操作。刚体表示具有形状、质量和速度等物理属性的实体。刚体有多种形状,包括矩形、圆形和多边形。约束用于限制两个刚体的相对运动,例如保持它们之间的恒定距离或限制它们的旋转。 Loop Module (Runner) Runner用于管理和控制物理引擎的主循环。
我会尝试用自己的话大致概括一下(不过,我觉得我的概括不太准确,如果您理解得更好,请在评论区留言。如果您没有什么特别要说的,” ) 我来这里是为了参观。 )
引擎引擎可以模拟多种现实世界的物理定律。
刚体可以粗略地理解为现实世界的物体,例如球或凳子。
复合体是一个允许您集成和连接多个对象的容器。例如,如果您创建一个球(刚体)并使用复合材料将其连接到引擎,则该球将受到物理规则的影响。
渲染渲染就像一只眼睛,可以帮助您看到由Matter.js 创建的世界。
约束就是约束。例如,跷跷板由长模板和底座组成,板的中心固定在底座上。正是因为这个约束,跷跷板才变成了跷跷板。
循环模块Runner 可以宽松地理解为现实世界的时间。如果没有循环模块,页面上的所有元素都会冻结。你可以看到,当现实世界中的时间耗尽时,整个世界都会停止。
以上是您开始使用Matter.js 时可能需要了解的一些基本概念。
此外,你实际上需要掌握一些基本的物理概念,比如知道什么是碰撞、摩擦、阻力、重力等。这种概念在以下案例中得到解释。
安装Matter.js
在开始使用Matter.js 之前,您需要确保项目中安装了Matter.js。
可以通过npm在命令行安装,也可以通过cdn部署。
CDN
在github上下载并部署到你的项目中,github地址[6]。
具体版本也可以在这里找到[7]。
如果你不想在本地下载Matter.js,也可以在bootcdn[8]上搜索Matter.js并导入。
scriptrc=\’https://cdn.bootcdn.net/ajax/libs/matter-js/0.19.0/matter.js\’/script
复制代码
NPM
Matter.js npm 地址[9]
npminstallmatter-js
复制代码
起步,第一个 Matter.js 应用
此示例是Matter.js[10] 的官方起始案例。通过这个例子,你可以快速理解上面提到的Matter.js的基本概念。
我们先来看看效果。
01.gif
从这个动画中你可以看到:
世界有两个正方形和地面(下面的矩形)。
空中出现一个正方形,然后自由落下。
左边的方块落地时会稍微弹起。
右边的方块在落地前与左边的方块相撞,阻止了左边的方块反弹并向右滚动。
要使用Matter.js实现上述效果,需要执行以下步骤:
创建一个容器。
介绍Matter.js。
创建一个引擎。
创建一个渲染器并将其绑定到画布。
创建一个正方形和地面,并使地面元素静止。
将你创造的元素添加到“世界”中(是的,你就是创世神~)。
最后,添加“时间”属性,以便世界可以运行(Matter.Runner)。
还应该使用与基本概念相对应的表格来理解上述步骤。
转换为代码
!–1.创建容器–
除法=\’c\’/div
!–2.事项介绍–
scriptrc=\’./js/matter.js\’/script
脚本
constEngine=Matter.Engine
constRender=Matter.Render
constBodies=Matter.Bodies
constComposite=Matter.Composite
constRunner=Matter.Runner
//3.创建引擎
letengine=engine.create()
//4. 创建渲染器并将引擎连接到画布。
letrender=Render.create({
element:document.getElementById(\’c\’),//绑定页面元素
Engine:engine,//绑定引擎
})
//5-1. 创建两个正方形。
letboxA=Bodies.矩形(400,200,80,80)
letboxB=body.矩形(450,50,80,80)
//5-2.创建地面并将isStatic设置为true,表示物体是静止的。
letground=Bodies.rectangle(400,610,810,60,{isStatic:true})
//6. 将所有对象添加到世界中。
Composite.add(engine.world,[boxA,boxB,ground])
//7.执行渲染操作
Render.run(渲染)
//8. 创建执行方法。
varrunner=runner.create()
//9. 运行渲染器。
Runner.run(跑步者,引擎)
/剧本
复制代码
使用Engine 创建引擎。 Matter.js 引擎默认帮助您定义世界的基本操作规则。
接下来,使用Render创建一个可以将引擎绑定到页面的渲染器。
主体是指用于创建对象的刚体。在此示例中,创建了两个正方形和一个地面。
复合体是上面提到的复合体,它允许您将对象与世界关联起来。这意味着可以将对象添加到世界中。
最后,由于Render,世界上有了“时间”的概念,物体在时间的操纵下,也按照世界的规律运动。
也许你还不太明白上面代码中各个方法的具体用法,但是结合前面的分析,你已经熟悉了Matter.js中“创建世界”的基本流程了。它的要点(你可能会这样做)。如果你听我的分析你会更困惑))。
渲染器
在前面的示例中,我们使用Matter.Render.create 来绑定画布和页面元素。目前默认的画布大小为800px * 600px。
//省略一些代码
letrender=Matter.Render.create({
element:document.getElementById(\’c\’),//绑定页面元素
Engine:engine,//绑定引擎
})
复制代码
事实上,它还支持其他属性配置,您可以在其中设置画布宽度和高度等内容。
设置画布宽高
使用Matter.Render.create时,还可以传递一个options参数。
//省略一些代码
letrender=Matter.Render.create({
element:document.getElementById(\’c\’),//绑定页面元素
Engine:engine,//绑定引擎
选项:{
宽度:400,
身高:400
}
})
复制代码
关闭线框模式
Matter.js 创建的形状默认处于线框模式。该模式可以手动关闭。 Matter.js 自动用多种颜色填充基本形状。
要关闭线框模式,请将线框设置为false。
02.gif
//省略一些代码
letrender=Matter.Render.create({
element:document.getElementById(\’c\’),//绑定页面元素
Engine:engine,//绑定引擎
选项:{
线框:false
}
})
复制代码
其余代码(包括创建图形的代码)与“第一个Matter.js 应用程序入门”中的代码相同。
该选项还支持其他配置。如果您有兴趣,请参阅文档[11]。
图形元素
Matter.js 支持各种基本形状,包括矩形、圆形、三角形、梯形和多边形。这些图形还支持配置颜色、摩擦力等属性。
基础图形
让我们从基础开始。
在Matter.js文档中,您可以看到Body用于创建对象。这在中文中翻译为“刚体”。
在物理世界中,刚体是指在运动过程中和受力作用后其形状和尺寸不发生改变,内部各点的相对位置也不改变的物体。
在Matter.js 中,刚体是具有质量、位置、速度、加速度和形状等属性的物理对象,可以添加到物理世界并由物理引擎模拟。例如矩形和圆形。
在入门阶段,您可以使用主体来创建基本图形。
矩形 rectangle
我以前用过矩形。本节简要介绍创建矩形所需的一些参数。
矩形是使用Matter.Bodies.rectangle(x, y, width, height) 方法创建的。
参数x和y是矩形中心点的坐标,width和height是矩形的宽度和高度。
如果创建一个80*80 的矩形并希望其左上角位于(0, 0),请将x 和y 分别设置为宽度和高度的一半。
03.png
//省略一些代码
//创建一个矩形
letrect=Matter.Bodies.rectangle(40,40,80,80)
//将矩形添加到世界中
Matter.Composite.add(engine.world,rect)
复制代码
圆形 circle
创建圆的方法是Matter.Bodies.circle(x, y, radius)。
x和y是圆心的坐标,radius是半径。
04.png
//省略一些代码
//创建一个圆
letcircle=Matter.Bodies.circle(40,40,40)
//将矩形添加到世界中
Matter.Composite.add(engine.world,圆)
复制代码
梯形 trapezoid
创建梯形的方法是Matter.Bodies.trapezoid(x, y, width, height,lope)。
x 和y 定义梯形中心点的坐标,width 和height 定义梯形的宽度和高度,slope 定义斜率。
如果斜率大于0 且小于1,则梯形的顶边小于底边。
如果斜率为0,则梯形的顶边和底边相等,看起来像一个矩形。
如果斜率小于0,则顶部边缘大于底部边缘。
如果斜率大于或等于1,则它看起来像一个三角形。
05.png
//省略一些代码
lettrapezoid=Matter.Bodies.trapezoid(200,200,80,80,0.5)
复制代码
三角形 trapezoid
创建三角形与创建梯形相同,只需将斜率设置为大于或等于1 的值即可。
06.png
//省略一些代码
lettriangle=Matter.Bodies.trapezoid(200,200,80,80,1)
复制代码
07.png
//省略一些代码
lettriangle=Matter.Bodies.trapezoid(200,200,80,80,2)
复制代码
正多边形 polygon
Matter.js 使用Matter.Bodies.polygon(x, y, Sides, radius) 创建规则多边形。
请注意,它是正多边形。
参数x和y是多边形中心点的坐标,sides可以设置多边形的边数,radius设置多边形的半径。
08.png
//省略一些代码
letpolygon=Matter.Bodies.polygon(200,200,7,40)
复制代码
自定义多边形
要使用Matter.js 创建自定义多边形,您可以使用Matter.Bodies.fromVertices(x, y, vertexSets) 方法。
x 和y 定义多边形中心的坐标,vertexSet 定义多边形顶点的集合。
//省略一些代码
//定义顶点
构造顶点=[
{x:0,y:0},
{x:50,y:0},
{x:50,y:50},
{x:25,y:75},
{x:0,y:50}
]
//自定义多边形
consttrapezoid=Matter.Bodies.fromVertices(100,100,顶点)
//将自定义多边形添加到世界中
Matter.Composite.add(engine.world,梯形)
复制代码
图形状态和属性配置
当使用之前使用Matter.bodies 创建的图形时,您可以在末尾添加额外的对象参数来配置图形的状态和属性。
填充色 render.fillStyle
如果要为Matter.js 中的形状添加填充颜色,可以配置render 属性的fillStyle 属性的值。例如,要将圆的填充颜色设置为橙色,请使用以下代码:
09.png
//省略一些代码
//创建渲染器
letrender=Matter.Render.create({
element:document.getElementById(\’c\’),//绑定页面元素
Engine:engine,//绑定引擎
选项:{
宽度:400,
高度:400,
Wireframes:false,//关闭线框模式
}
})
//省略一些代码
//创建一个矩形
letrect=Matter.Bodies.rectangle(200,200,80,80,{
渲染:{
fillStyle:\’橙色\’
}
})
复制代码
请注意,如果使用填充颜色功能,则必须在渲染器中关闭线框模式。
边框颜色和线宽 render.strokeStyle render.lineWidth
使用render.drawingStyle 设置边框颜色,使用render.lineWidth 设置边框宽度。
10.png
//省略一些代码
//创建渲染器
letrender=Matter.Render.create({
element:document.getElementById(\’c\’),//绑定页面元素
Engine:engine,//绑定引擎
选项:{
宽度:400,
高度:400,
Wireframes:false,//关闭线框模式
}
})
//省略一些代码
//创建一个矩形
letrect=Matter.Bodies.rectangle(200,200,80,80,{
渲染:{
Stroke Style:\’#3490de\’, //设置边框颜色
lineWidth:20//设置边框宽度
}
})
复制代码
render.fillStyle 和render.strokingStyle 都支持颜色关键字、以# 开头的十六进制数字、rgb、rgba 和其他颜色值。
但是,不支持以0x 开头的十六进制颜色。
贴图 render.sprite
一个好的前端应该知道如何映射,Matter.js 也提供了映射功能。
只需设置render.sprite即可。
我们以矩形为例。
11.png
//省略一些代码
//创建一个矩形
letrect=Matter.Bodies.rectangle(200,200,200,200,{
渲染:{
sprite:{//使用精灵
texture:\’./monkey.jpg\’//图像纹理位置
}
}
})
//将所有对象添加到世界中
Matter.Composite.add(engine.world,rect)
复制代码
缩放贴图 scale
如果需要设置纹理的宽度和高度,还可以更改xScale 和yScale 属性。
然而,这两个属性只影响纹理的大小,而不影响图形的实际大小。
12.png
//省略一些代码
letrect=Matter.Bodies.rectangle(200,200,200,200,{
渲染:{
精灵:{
纹理:\’./monkey.jpg\’,
xScale:0.5,
y 比例:1.5
}
}
})
复制代码
贴图偏移 offset
您可以设置精灵贴图的xOffset和yOffset。
//省略一些代码
letrect=Matter.Bodies.rectangle(200,200,200,200,{
渲染:{
精灵:{
纹理:\’./monkey.jpg\’,
x偏移:0.5,
y 偏移:1
}
}
})
复制代码
不透明度 render.opacity
不透明度值范围从0到1。
//省略一些代码
letrect=Matter.Bodies.rectangle(80,100,80,80,{
渲染:{
不透明度:0.5
}
})
复制代码
元素可见性 render.visible
如果render.visible 为false,则该元素将被隐藏。否则,该元素是可见的。 render.visible 的默认值为true。
//省略一些代码
letrect=Matter.Bodies.rectangle(80,100,80,80,{
渲染:{
visible:false//隐藏元素
}
})
复制代码
旋转 angle
angle 属性允许您设置元素的旋转弧度。
为了便于理解,我习惯使用“角度”这个单位。
要将角度转换为弧度,可以使用以下公式:
数学.PI/180*角度
复制代码
13.png
//省略一些代码
//长方形
letrect=Matter.Bodies.rectangle(80,100,80,80,{
角度:数学.PI/180*45
})
复制代码
上面的代码创建了一个矩形并将其旋转45 度。我想如果和上面的公式结合起来会更容易理解。
空气阻力 frictionAir
我们已经向您简要介绍了如何用颜色填充基本图形和使用纹理,但这只是开胃菜。
Matter.js 的真正亮点是它的物理引擎。
如前所述,要使物理引擎正常工作,您需要使用以下代码:
//省略一些代码
//创建运行方法
让跑步者
= Runner.create()
// 运行渲染器
Runner.run(runner, engine)
复制代码
如果忘了,可以看看前面的 “起步,第一个 Matter.js 应用” 这章节。
先介绍一下空气阻力。
我们知道,在地球上,当一个物体做自由落体运动时,会受到空气阻力的影响。
Matter.js 提供了 frictionAir 这个属性可以让我们给指定物体配置具体的空气阻力。
14.gif
// 省略部分代码
let rectA = Matter.Bodies.rectangle(80, 100, 80, 80, {
frictionAir: 0.1 // 设置空气阻力
})
let rectB = Matter.Bodies.rectangle(200, 100, 80, 80, {
frictionAir: 0.5 // 设置空气阻力
})
let rectC = Matter.Bodies.rectangle(320, 100, 80, 80, {
frictionAir: 1 // 设置空气阻力
})
// 地面
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
// 6. 将所有物体添加到世界中
Matter.Composite.add(engine.world, [rectA, rectB, rectC, ground])
复制代码
从左往右的立方体中,我分别给它们配置的空气阻力时 0.1、0.5 和 1 ,数值越大,空气阻力就越大,自由落体的速度也就越慢。
回弹力 restitution
前面的例子中创建的物体都是没有弹力的,它们掉到地面时不会回弹。
如果希望物体有弹性,可以配置它的 restitution 。
15.gif
// 省略部分代码
let rectA = Matter.Bodies.rectangle(80, 100, 80, 80, {
restitution: 0 // 设置弹力
})
let rectB = Matter.Bodies.rectangle(200, 100, 80, 80, {
restitution: 1 // 设置弹力
})
let rectC = Matter.Bodies.rectangle(320, 100, 80, 80, {
restitution: 1.2 // 设置弹力
})
// 地面
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
// 6. 将所有物体添加到世界中
Matter.Composite.add(engine.world, [rectA, rectB, rectC, ground])
复制代码
在 Matter.js 中,物体的回弹力正常取值范围是 0 ~ 1。其中0表示碰撞后不反弹,1表示碰撞后完全反弹。
如果反弹系数大于1,就意味着碰撞后物体的能量增加,这是不符合物理规律的。
但如果你在做游戏,在处理游戏角色的某些技能时也可以让回弹力超出1。毕竟这是你的世界。
质量 mass
在初中物理课上我们知道,质量越大,惯性越大。也就是说物体更难改变它的状态(静止或运动状态)。当施加力或者撞击物体时,质量越大的物体会更难加速或者减速,需要更长的时间来达到相同的速度或者停止。而质量越小的物体则更容易改变它的状态,可以更快地加速或减速。
在 Matter.js 中,碰撞响应的计算是基于物体的质量和速度等参数的。比如,当两个物体相撞时,质量越大的物体会对速度的改变产生更小的影响,而质量越小的物体会对速度的改变产生更大的影响。
举个例子,我在画布中创建3个质量不同的矩形,左边的矩形的质量最小,右边的最大。在回弹力相同的情况下,质量越小,回弹的程度就越大。
16.gif
// 省略部分代码
// 矩形A
let rectA = Matter.Bodies.rectangle(80, 100, 80, 80, {
restitution: 1,
mass: 0.1
})
// 矩形B
let rectB = Matter.Bodies.rectangle(200, 100, 80, 80, {
restitution: 1,
mass: 5
})
// 矩形C
let rectC = Matter.Bodies.rectangle(320, 100, 80, 80, {
restitution: 1,
mass: 10
})
// 地面
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
Matter.Composite.add(engine.world, [rectA, rectB, rectC, ground])
复制代码
静止 isStatic
前面几个例子中,空中的几个矩形都会往下掉,但地面却不会。
这是因为地面元素将 isStatic 设置为 true 了,所以元素就不会动了。
// 省略部分代码
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
复制代码
关于基础元素的其他属性配置,可以看看 『Matter.js官方文档的 Body 内容』[12]。
堆 stack
在 Matter.js 中允许你将多个物体组合在一起,以便更方便地管理和操作它们。这个方法叫做“堆 stack”。
你可以将多个矩形放在一个 stack 中,然后一起移动它们,或者一起旋转它们,而不需要分别操作每个矩形。这可以大大简化代码,并提高代码的可维护性。
要创建一个 stack,可以使用 Matter.Composites.stack 方法。
用法:Matter.Composites.stack(xx, yy, columns, rows, columnGap, rowGap, callback)
其中的参数作用:
xx 和 yy: stack 的起始位置。
columns 和 rows: stack 的列数和行数。
columnGap: 相邻两个物体之间的列间隔。
rowGap: 相邻两个物体之间的行间隔。
callback: 回调函数,通常用于生成 stack 中的每个物体。
举个完整例子
17.gif
<div id=\”c\”></div>
<script src=\”../js/matter.js\”></script>
<script>
let engine = Matter.Engine.create()
let render = Matter.Render.create({
element: document.getElementById(\’c\’), // 绑定页面元素
engine: engine, // 绑定引擎
options: {
width: 400,
height: 400,
wireframes: false,
}
})
// 堆
// 起始位置是 (20, 20),一共6列3行,列间距10,行间距20
let stack = Matter.Composites.stack(20, 20, 6, 3, 10, 20, function (x, y) {
return Matter.Bodies.rectangle(x, y, 30, 30)
})
// 地面
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
// 将堆和地面添加到世界里
Matter.Composite.add(engine.world, [stack, ground])
Matter.Render.run(render)
let runner = Matter.Runner.create()
Matter.Runner.run(runner, engine)
</script>
复制代码
这个例子我只给堆和地面添加了注释,方便工友们寻找这段主要的代码。
在使用 stack 时,最后的用来创建物体的回调函数有 x 和 y 参数,这两个参数是 Matter.js 提供的,它会根据前面几个参数 (xx, yy, columns, rows, columnGap, rowGap) 来计算每次 x 和 y 的值是多少,而这个 x 和 y 通常用来定义图形元素的位置。
stack 更大的意义是方便我们集中管理堆中的元素,比如在上面这个例子中,要让所有立方体自身旋转30度,可以直接在回调函数里写上。
18.gif
// 省略部分代码
let stack = Matter.Composites.stack(20, 20, 6, 3, 10, 20, function (x, y) {
return Matter.Bodies.rectangle(x, y, 30, 30, {
angle: Math.PI / 180 * 30, // 旋转30度
restitution: 0.5 // 添加一点回弹力
})
})
复制代码
在这个例子中,我还给每个矩形增加了一点回弹力,让矩形在落地散开后的动画看上去更符合真实世界的逻辑。
除了能够方便地给每个矩形都添加属性外,你还可以给整个堆进行调整。
比如整体旋转30度(这个效果和上面的例子不一样!)。
19.gif
// 省略部分代码
let stack = Matter.Composites.stack(20, 20, 6, 3, 10, 20, function (x, y) {
return Matter.Bodies.rectangle(x, y, 30, 30, {
restitution: 0.5 // 添加一点回弹力
})
})
// 整个堆旋转30度
Matter.Composite.rotate(stack, Math.PI / 180 * 30, { x: 0, y: 200 })
复制代码
约束 Constraint
在 Matter.js 里,约束 Constraint 可以理解为将2个物体绑在一起。
生活中常见的例子跷跷板。
20.jpg
不好意思,放错图了,下面这张才对
21.jpg
一个简单的跷跷板分为2部分:横着的板和底座。
把这两部分绑定在一起就形成跷跷板。
在 Matter.js 中要实现这个功能,用到的就是约束 Constraint。
先简单体验一下再说用法。
22.gif
<div id=\”c\”></div>
<script src=\”../js/matter.js\”></script>
<script>
let engine = Matter.Engine.create()
let render = Matter.Render.create({
element: document.getElementById(\’c\’), // 绑定页面元素
engine: engine, // 绑定引擎
options: {
width: 400,
height: 400,
wireframes: false,
}
})
// 板子A(红色)
let rectA = Matter.Bodies.rectangle(200, 330, 20, 100, {
isStatic: true,
render: {
fillStyle: \’#f00\’
},
collisionFilter: {
group: -1
}
})
// 板子B(蓝色)
let rectB = Matter.Bodies.rectangle(200, 330, 200, 20, {
render: {
fillStyle: \’#00f\’
},
collisionFilter: {
group: -1
}
})
// 创建旋转约束
let rotateConstraint = Matter.Constraint.create({
bodyA: rectA,
bodyB: rectB,
length: 0
})
// 矩形的堆
let stack = Matter.Composites.stack(20, 30, 4, 3, 10, 20, function (x, y) {
return Matter.Bodies.rectangle(x, y, 40, 20)
})
// 圆形的堆
let stack_circle = Matter.Composites.stack(220, 60, 3, 4, 10, 20, function (x, y) {
return Matter.Bodies.circle(x, y, 16)
})
// 地面
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
// 将 蓝色和红色矩形、约束、矩形堆、圆形堆、地面 都添加到世界里
Matter.Composite.add(engine.world, [rectA, rectB, rotateConstraint, stack, stack_circle, ground])
Matter.Render.run(render)
let runner = Matter.Runner.create()
Matter.Runner.run(runner, engine)
</script>
复制代码
在上面的例子中,我创建了1个跷跷板(由红色和蓝色矩形组合而成),1堆小矩形,1堆小圆形,1个地面。
小矩形堆和小圆形堆都做自由落体。
跷跷板使用了 Matter.Constraint.create 做约束处理,其中的参数 bodyA 和 bodyB 用来指定要约束的两个物体。length 表示约束的长度,设置为0的话,他们之间的约束点就没有任何挪动的空间,这就和跷跷板的原理一样了。
Matter.Constraint.create(options) 的配置对象包含以下属性:
options:约束的选项。
options.bodyA:类型为 Matter.Body,约束连接的第一个物体。
options.pointA:类型为 Matter.Vector,约束连接的第一个物体上的点。
options.bodyB:类型为 Matter.Body,约束连接的第二个物体。
options.pointB:类型为 Matter.Vector,约束连接的第二个物体上的点。
options.length:类型为 number,约束的初始长度。
options.stiffness:类型为 number,约束的刚度系数。
options.damping:类型为 number,约束的阻尼系数。
options.render:约束的渲染选项。
options.render.visible:类型为 boolean,表示约束是否可见,默认为 true。
options.render.lineWidth:类型为 number,表示约束线条的宽度。
options.render.strokeStyle:类型为 string,表示约束线条的颜色。
鼠标约束
这里所指的耗子约束是指给鼠标添加操作物体的功能。
要实现拖拽物体的功能,需要以下几个步骤:
创建鼠标实例 Matter.Mouse.create。
给鼠标添加约束 Matter.MouseConstraint.create。
将鼠标约束添加到物理引擎中。
23.gif
<div id=\”c\”></div>
<script src=\”../js/matter.js\”></script>
<script>
let engine = Matter.Engine.create()
let render = Matter.Render.create({
element: document.getElementById(\’c\’), // 绑定页面元素
engine: engine, // 绑定引擎
options: {
width: 400,
height: 400,
wireframes: false,
}
})
let box = Matter.Bodies.rectangle(80, 100, 80, 80, {
restitution: 0.3,
mass: 0.1
})
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
// 创建鼠标实例
let mouse = Matter.Mouse.create(render.canvas)
// 给鼠标添加约束
let mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse: mouse,
constraint: {
stiffness: 0.2,
render: {
visible: false // 默认为 true,会显示鼠标拖拽轨迹
}
}
})
// 将鼠标约束添加到物理引擎中
Matter.Composite.add(engine.world, [box, ground, mouseConstraint]);
Matter.Render.run(render)
let runner = Matter.Runner.create()
Matter.Runner.run(runner, engine)
</script>
复制代码
事件监听
在 Matter.js 中,可以使用 Events.on 方法来监听各种事件,包括鼠标事件、碰撞事件等等。
常用鼠标事件
例如这样监听鼠标的各种事件(随便举点例子)
// 省略部分代码
// 创建一个 Mouse 实例
let mouse = Matter.Mouse.create(render.canvas)
let mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse: mouse
})
// 监听鼠标事件
// 监听鼠标按下事件
Matter.Events.on(mouseConstraint, \’mousedown\’, function(event) {
console.log(\’按下\’)
})
// 监听鼠标移动事件
Matter.Events.on(mouseConstraint, \”mousemove\”, function(event) {
console.log(\’移动\’)
})
// 监听鼠标抬起事件
Matter.Events.on(mouseConstraint, \”mouseup\”, function(event) {
console.log(\’抬起\’)
})
// 监听鼠标拖拽刚体 – 开始拖拽
Matter.Events.on(mouseConstraint, \’startdrag\’, function(event) {
console.log(\’开始拖拽\’)
})
// 监听鼠标拖拽刚体 – 结束拖拽
Matter.Events.on(mouseConstraint, \’enddrag\’, function(event) {
console.log(\’结束拖拽\’)
})
Matter.Composite.add(engine.world, mouseConstraint)
复制代码
监听碰撞
在 Matter.js 中,用 Matter.Events.on 去监听 collisionStart 事件就能知道物体的碰撞。
除了 collisionStart 外,还有其他监听周期。
collisionStart:当两个物体开始碰撞时触发。
collisionActive:当两个物体持续碰撞时触发。
collisionEnd:当两个物体停止碰撞时触发。
我用 collisionStart 举例:
24.gif
// 省略部分代码
// 创建一个矩形
var box = Matter.Bodies.rectangle(200, 100, 80, 80, {
restitution: 1
})
// 地面
let ground = Matter.Bodies.rectangle(200, 390, 400, 20, {
isStatic: true,
render: {
fillStyle: \’#cccccc\’
}
})
// 添加刚体到引擎中
Matter.Composite.add(engine.world, [box, ground]);
// 监听碰撞事件
Matter.Events.on(engine, \’collisionStart\’, function(event) {
const pairs = event.pairs
pairs.forEach(pair => {
console.log(pair)
})
})
复制代码
上面这个例子中,我给 box 设置了回弹力,它首次落地后回弹了2次,首次落地加2次回弹一共就触发了3次碰撞,所以在控制台输出了3次碰撞的结果。
其中,pairs 是指一对正在碰撞的物体。当两个物体相互碰撞时,它们就被组成为一个 pair 对象。
我们可以通过 event.pairs 属性来访问有关碰撞的更多信息。
#以上关于物理世界的互动之旅:Matter.js入门指南的相关内容来源网络仅供参考,相关信息请以官方公告为准!
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92914.html