物理世界的互动之旅:Matter.js入门指南

物理世界的互动之旅:Matter.js入门指南 原文来源于:程序员成长指北;作者:德育处主任 如有侵权,联系删除 本文简介
欢迎来到《物理世界的互动之旅:Matter.

来源:程序员成长指南作者:德育总监

如有侵权,请联系我们删除。

本文简介

欢迎拨打《物理世界的互动之旅: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

(0)
CSDN的头像CSDN
上一篇 2024年7月4日
下一篇 2024年7月4日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注