这些都是github上比较火的
可以用原生的写。。。 但是会比较麻烦, 常用的物理引擎,图像渲染效果和图形学知识等都要从头自己去写,出东西的速度就大大下降了。 建议用引擎会简单些,大大加快开发速度。
就在不久前,创建和部署 游戏 的唯一方法是选择像 Unity 或 Unreal 这样的 游戏 引擎,学习语言,然后打包 游戏 并将其部署到你选择的平台上。
试图通过浏览器向用户提供 游戏 的想法似乎是一项不可能完成的任务。
幸运的是,由于浏览器技术的进步和硬件加速在所有流行的浏览器中都可用,JavaScript 性能的改进以及可用处理能力的稳步提高,为浏览器创建交互式 游戏 体验变得越来越普遍。
在本文中,我们将了解如何使用 Three.js 创建 游戏 。但首先,让我们回顾一下 Three.js 是什么以及为什么它是 游戏 开发的好选择。
Three.js 在 GitHub 上的项目描述恰当地将 Three.js 描述为“......一个易于使用、轻量级、跨浏览器的通用 3D 库”。
Three.js 让我们作为开发人员可以相对简单地在屏幕上绘制 3D 对象和模型。如果没有它,我们将需要直接与 WebGL 交互,虽然这并非不可能,但即使是最小的 游戏 开发项目也会花费大量时间。
传统上,“ 游戏 引擎”由多个部分组成。例如,Unity 和 Unreal 提供了一种将对象渲染到屏幕上的方法,但也提供了大量其他功能,如网络、物理等等。
然而,Three.js 的方法更受限制,不包括物理或网络之类的东西。但是,这种更简单的方法意味着它更容易学习和更优化以做它最擅长的事情:将对象绘制到屏幕上。
它还有一组很棒的示例,我们可以使用它们来了解如何在屏幕上绘制各种对象。最后,它提供了一种简单且原生的方式将我们的模型加载到我们的场景中。
如果不希望用户需要通过应用商店下载应用或进行任何设置来玩你的 游戏 ,那么Three.js 作为 游戏 开发引擎可能是一个有吸引力的选择。如果你的 游戏 在浏览器中运行,那么进入门槛最低,这只能是一件好事。
今天,我们将通过制作一个使用着色器、模型、动画和 游戏 逻辑的 游戏 来浏览 Three.js。我们将创建的内容如下所示:
这个概念很简单。我们控制着一艘火箭飞船,穿越一个星球,我们的目标是拾取能量晶体。我们还需要通过增加护盾来管理飞船的 健康 状况,并尽量不要因为撞击场景中的岩石而严重损坏我们的船。
在我们的运行结束时,火箭飞船返回天空中的母舰,如果用户点击 NEXT LEVEL ,他们会再次尝试,这一次火箭要经过更长的路径。
随着用户玩 游戏 ,火箭飞船的速度会增加,因此他们必须更快地躲避岩石并收集能量晶体。
要创建这样的 游戏 ,我们必须回答以下问题:
到我们制作这款 游戏 时,我们将克服这些挑战。
不过,在我们开始编码之前,我们必须回顾一些简短的理论,特别是与我们将如何在 游戏 中创造运动感有关。
想象一下,你在现实生活中控制着一架直升机,并且正在跟踪地面上的一个物体。物体以逐渐增加的速度继续前进。为了跟上,你必须逐渐提高你所在直升机的速度。
如果对直升机或地面上的物体的速度没有限制,只要你想跟上地面上的物体,这种情况就会持续下去。
当创建一个跟随对象的 游戏 时,正如我们在本例中所做的那样,应用相同的逻辑可能很诱人。也就是说,在世界空间中随着物体的加速移动物体,并更新后面跟随的相机的速度。然而,这提出了一个直接的问题。
基本上,每个玩这个 游戏 的人都会在他们的手机或台式电脑上玩它。这些设备资源有限。如果我们尝试在相机移动时生成可能无限数量的对象,然后移动该相机,最终我们将耗尽所有可用资源,并且浏览器选项卡将变得无响应或崩溃。
我们还需要创建一个代表海洋的平面(一个平面 2D 对象)。当我们这样做时,我们必须给出海洋的尺寸。
然而,我们不能创建一个无限大的平面,我们也不能创建一个巨大的平面,只是希望用户永远不会在我们的关卡中前进到足以让他们离开平面的程度。
那是糟糕的设计,并且希望人们玩我们的 游戏 不足以体验错误似乎违反直觉。
我们不是在一个方向上无限期地移动我们的相机,而是让相机保持静止并移动它周围的环境。这有几个好处。
一是我们总是知道火箭飞船在哪里,因为火箭的位置不会移到远处;它只会左右移动。这让我们很容易判断物体是否在相机后面,并且可以从场景中移除以释放资源。
另一个好处是我们可以选择远处的一个点来创建对象。这意味着当物体接近玩家时,新的物品或物体将不断地在玩家视野之外的距离创建。
当它们从视野中消失时,无论是玩家与它们发生碰撞还是从玩家身后消失,这些物品都会从场景中移除,以降低内存使用量。
要创建这种效果,我们需要做两件事:首先,我们需要在程序上沿深度轴移动每个项目,以将对象移向相机。其次,我们必须为我们的水面提供一个可以抵消的值,并随着时间的推移增加这个偏移量。
这将产生水面移动越来越快的效果。
现在我们已经解决了如何在场景中向前移动火箭,让我们继续设置我们的项目。
让我们开始制作 游戏 吧!我们需要做的第一件事是设置构建环境。对于这个例子,我选择使用 Typescript 和 Webpack。这篇文章不是要讨论这些技术的有点,所以除了快速总结之外,我不会在这里详细介绍它们。
使用 Webpack 意味着当我们开发项目并保存文件时,Webpack 将看到我们的文件已更改,并使用保存的更改自动重新加载浏览器。
这意味着我们无需在每次进行更改时手动刷新浏览器,从而节省大量时间。这也意味着我们可以使用像three-minifier这样的插件,它可以在我们部署它时减小我们的包的大小。
在我们的示例中使用 TypeScript 意味着我们的项目将具有类型安全性。我发现这在使用 Three.js 的一些内部类型时特别有用,比如Vector3s 和Quaternions. 知道我将正确类型的值分配给变量是非常有价值的。
我们还将在 UI 中使用Materialize CSS。对于我们将用作 UI 的几个按钮和卡片,这个 CSS 框架将有很大帮助。
要开始我们的项目,请创建一个新文件夹。在文件夹中,创建一个package.json并粘贴以下内容:
然后,在命令窗口中,键入npm i以将包安装到新项目中。
我们现在需要创建三个文件,一个基本的 Webpack 配置文件,然后是我们项目的开发和生产配置文件。
在项目文件夹中创建一个webpack.common.js文件并粘贴以下配置:
然后,创建一个webpack.dev.js文件并粘贴这些详细信息。这配置了 Webpack 开发服务器的热重载功能:
最后,创建一个webpack.production.js文件并粘贴这些详细信息:
我们需要做的下一件事是配置 TypeScript 环境以允许我们使用来自 JavaScript 文件的导入。为此,请创建一个tsconfig.json文件并粘贴以下详细信息:
我们的构建环境现在已经配置好了。现在是时候开始为我们的玩家创造一个美丽而可信的场景了。
我们的场景包含以下元素:
我们将在一个名为 game.ts的文件中完成大部分工作,但我们也会将部分 游戏 拆分为单独的文件,这样我们就不会得到一个非常长的文件。我们现在可以继续创建文件game.ts。
因为我们正在处理一个非常复杂的主题,所以我还将包含指向此代码在 GitHub 上的项目中的位置的链接。这应该有望帮助你保持自己的方向,而不是在更大的项目中迷失方向。
我们需要做的第一件事是创建一个Scene,以便 Three.js 有一些东西可以渲染。在我们的game.ts中,我们将添加以下行来构建我们的并将 一个ScenePerspectiveCamera放置在场景中,这样我们就可以看到发生了什么。
最后,我们将为稍后分配的渲染器创建一个引用:
为了设置我们的场景,我们需要执行一些任务,比如创建一个新的WebGLRenderer和设置我们想要绘制的画布的大小。
为此,让我们创建一个init函数并将其也放入我们的game.ts中。此init函数将为我们的场景执行初始设置,并且只运行一次(当 游戏 首次加载时):
我们还需要为场景利用渲染和动画循环。我们需要动画循环来根据需要在屏幕上移动对象,并且我们需要渲染循环来将新帧绘制到屏幕上。
让我们继续在game.ts中创建render函数。 一开始,这个函数看起来很简单,因为它只是请求一个动画帧然后渲染场景。
我们请求动画帧的原因有很多,但其中一个主要原因是如果用户更改选项卡,我们的 游戏 将暂停,这将提高性能并减少设备上可能浪费的资源:
好了,现在我们有了一个空的场景,里面有一个相机,但没有别的了。让我们在场景中添加一些水。
幸运的是,Three.js 包含一个我们可以在场景中使用的水对象示例。它包括实时反射,看起来相当不错;你可以在这里查看。
对我们来说幸运的是,这种水将完成我们在场景中想要做的大部分事情。我们唯一需要做的就是稍微改变水的着色器,这样我们就可以在渲染循环中更新它。
我们这样做是因为如果随着时间的推移,我们越来越多地抵消我们的水纹理,那么它会给我们带来速度的感觉。
作为演示,下面就是我们 游戏 的开场场景,但我每帧都增加了偏移量。随着偏移量的增加,感觉就像我们下方海洋的速度正在增加(即使火箭实际上是静止的)。
水对象可以在 Three.js GitHub 上找到。我们唯一需要做的就是做一个小的改变,使这个偏移量可以从我们的渲染循环中控制(所以我们可以随着时间的推移更新它)。
我们要做的第一件事是在 Three.js 存储库中获取 Water.js 示例的副本。我们将把这个文件objects/water.js放在我们的项目中。如果我们打开water.js文件,大约一半,我们将开始看到如下所示的内容:
这是海洋材质的着色器。着色器本身的介绍超出了本文的范围,但基本上,它们是我们的 游戏 将向用户的计算机提供的关于如何绘制此特定对象的说明。
这里还有我们的着色器代码,它是用 OpenGraph 着色器语言 (GLSL) 编写的,并合并到一个原本是 JavaScript 的文件中。
这没有什么问题,但是如果我们将这个着色器代码单独移动到一个文件中,那么我们可以将 GLSL 支持安装到我们选择的 IDE 中,我们将获得语法着色和验证之类的东西,这有助于我们自定义 GLSL .
要将 GLSL 分解为单独的文件,让我们在当前objects目录中创建一个shader目录,选择 我们的vertexShader和 fragmentShader 的内容, 并将它们分别移动到waterFragmentShader.glsl和waterVertexShader.glsl文件中。
在我们waterFragmentShader.glsl文件的顶部,我们有一个getNoise函数。默认情况下,它看起来像这样:
为了使这个偏移量可以从我们的 游戏 代码中调整,我们想在我们的 GLSL 文件中添加一个参数,允许我们在执行期间对其进行修改。为此,我们必须将此函数替换为以下函数:
你会注意到我们在这个 GLSL 文件中包含了一个新变量:speed变量。这是我们将更新以提供速度感的变量。
在我们的game.ts中,现在需要配置水的设置。在我们文件的顶部,添加以下变量:
然后,在我们的init函数中,必须配置水平面的旋转和位置,如下所示:
这将为海洋提供正确的旋转。
Three.js 带有一个相当令人信服的天空,我们可以在项目中免费使用它。你可以在此处的 Three.js 示例页面中查看此示例。
在我们的项目中添加天空非常容易;只需要将天空添加到场景中,设置天空盒的大小,然后设置一些参数来控制天空的外观。
我们需要对初始场景初始化做的最后一件事是添加一些光照并添加我们的火箭模型和母舰模型:
现在我们有了一些漂亮的水和火箭的场景。但是,我们缺乏任何可以真正使它成为 游戏 的东西。为了解决这个问题,我们需要构建一些基本参数来控制 游戏 并允许玩家朝着某些目标前进。
在我们game.ts文件的顶部,我们将添加以下sceneConfiguration变量,这有助于我们跟踪场景中的对象:
现在,我们必须为玩家所在的当前关卡执行初始化。这个场景设置函数很重要,因为每次用户开始一个新的关卡时都会调用它。
因此,我们需要将火箭的位置设置回起点并清理所有正在使用的旧资产。我在代码行内添加了一些注释,以便你可以看到每一行在做什么:
我们预计有两种类型的设备可以玩我们的 游戏 :台式电脑和手机。为此,我们需要适应两种类型的输入选项:
现在让我们配置这些。
在我们game.ts的开始,我们将添加以下变量来跟踪键盘上是否按下了左键或右键:
然后,在我们的init函数中,我们将注册keydownandkeyup事件来分别调用onKeyDownandonKeyUp函数:
最后,对于键盘输入,我们将记录按下这些键时要执行的操作:
我们的移动用户没有键盘可以输入,因此,我们将使用nippleJS在屏幕上创建一个操纵杆,并使用操纵杆的输出来影响火箭在屏幕上的位置。
在我们的init函数中,我们将通过检查它在屏幕上是否有非零数量的触摸点来检查设备是否是触摸设备。如果是,我们将创建操纵杆,但一旦玩家释放操纵杆的控制,我们还将将火箭的运动设置回零:
在我们的animate函数中,我们会跟踪此时按下左键或右键或操纵杆是否正在使用中的操作。我们还将火箭的位置夹在可接受的左右位置,这样火箭就不能完全移出屏幕:
正如我们已经讨论过的,火箭飞船在我们的场景中保持静止,并且物体朝它移动。这些物体移动的速度随着用户继续玩而逐渐增加,随着时间的推移增加了关卡的难度。
仍然在我们的动画循环中,我们希望逐步将这些对象移向玩家。当对象离开玩家的视野时,我们希望将它们从场景中移除,这样我们就不会占用玩家计算机上不必要的资源。
在我们的渲染循环中,我们可以像这样设置这个功能:
我们可以看到有几个函数是这个调用的一部分:
让我们 探索 一下这些函数在我们的 游戏 中完成了什么。
碰撞检测是我们 游戏 的重要途径。没有它,我们将不知道我们的火箭飞船是否达到了任何目标,或者它是否撞到了岩石并应该减速。这就是我们想要在 游戏 中使用碰撞检测的原因。
通常,我们可以使用物理引擎来检测场景中对象之间的碰撞,但是 Three.js 没有包含物理引擎。
不过,这并不是说 Three.js 不存在物理引擎。他们当然可以,但是为了我们的需要,我们不需要添加物理引擎来检查我们的火箭是否击中了另一个物体。
本质上,我们想回答这个问题,“我的火箭模型目前是否与屏幕上的任何其他模型相交?” 我们还需要根据受到的打击以某些方式做出反应。
例如,如果我们的玩家不断将火箭撞到岩石上,我们需要在受到一定程度的伤害后结束关卡。
为了实现这一点,让我们创建一个函数来检查我们的火箭和场景中的对象的交集。根据玩家击中的内容,我们会做出相应的反应。
我们将把这段代码放在我们的game目录中的一个collisionDetection.ts文件中:
对于碰撞检测,我们唯一需要做的另一件事是添加一个短动画,当用户与对象碰撞时播放该动画。此函数将获取发生碰撞的位置并从该原点生成一些框。
完成的结果将如下所示。
为了实现这一点,我们必须在碰撞发生的地方创建一个圆圈中的盒子,并将它们向外设置动画,这样看起来它们就像从碰撞中爆炸一样。为此,让我们在collisionDetection.ts文件中添加此功能:
这就是我们整理出来的碰撞检测,当物体被破坏时会有一个漂亮的动画。
随着场景的进行,我们希望在玩家的两侧添加一些悬崖,这样感觉就像他们的运动在某个空间内得到了适当的限制。我们使用模运算符在程序上将岩石添加到用户的右侧或左侧:
随着场景的进行,我们还希望将“挑战行”添加到场景中。这些是包含岩石、水晶或盾牌物品的物体。每次创建这些新行中的一个时,我们都会为每一行随机分配岩石、水晶和盾牌。
因此,在上面的示例中,单元格 1、2 和 4 没有添加任何内容,而单元格 3 和 5 分别添加了水晶和盾牌项目。
为了实现这一点,我们将这些挑战行分为五个不同的单元格。我们根据随机函数的输出在每个单元格中生成某个项目,如下所示:
可以在这些链接中的任何一个查看岩石、水晶和盾牌创建功能。
我们需要在渲染循环中完成的最后一件事是:
在我们的渲染函数结束时,我们可以添加以下代码来适应这个功能:
这就是我们的渲染循环完成了。
当人们加载我们的 游戏 时,他们会看到一些让他们能够开始玩的按钮。
这些只是简单的 HTML 元素,我们根据 游戏 中发生的情况以编程方式显示或隐藏它们。问题图标让玩家对 游戏 的内容有所了解,并包含有关如何玩 游戏 的说明。它还包括我们模型的(非常重要的!)许可证。
并且,按下红色按钮开始 游戏 。请注意,当我们点击红色的“播放”按钮时,摄像机会移动并旋转到火箭后面,让玩家准备好开始场景。
在我们的场景init函数中,我们将要执行此操作的事件注册到此按钮的onClick处理程序。要创建旋转和移动功能,我们需要执行以下操作:
为此,我们将在init函数中添加以下代码,如下所示:
当我们的关卡结束时,我们还必须连接我们的逻辑,并且可以在此处查看执行此操作的代码。
在 Three.js 中创建 游戏 可以让你接触到数量惊人的潜在客户。由于人们可以在浏览器中玩 游戏 而无需下载或安装到他们的设备上,因此它成为开发和分发 游戏 的一种非常有吸引力的方式。
正如我们所见,为广泛的用户创造一种引人入胜且有趣的体验是非常有可能的。所以,唯一需要解决的是,你将在 Three.js 中创建什么?
原文链接:http://www.bimant.com/blog/threejs-game-dev-tutorial/
Matter.js 中基础的概念
大多数的物理引擎对于物理模拟的要素都有着相近的概念,不同的引擎差别在于使用的方式,功能的全面性,模拟的精细度等层面,下面就先从物理世界的基础概念讲起。
Engine(引擎)和 World(世界)
Matter.Engine 模块包含了创建和处理引擎的方法,引擎是负责管理和更新模拟世界的控制器,引擎可以控制时间的缩放,可以检测所有的碰撞事件,并且拿到所有碰撞的物体对(pairs)。
在 Matter.js 中任何的物体都需要一个容身处,而存放这些物体的地方,我们称之为世界,物体必须添加到世界里,然后由引擎运行这个世界。而创建世界需要使用到 Matter.World模块,该模块包含了用于创建和操作世界的方法,一个 Matter.World 相当于一个复合物体,物体、约束、复合物体的聚合体,其次世界还有额外的一些属性,比如重力、边界。
Render(渲染)
JavaScript
1
2
3
4
5
6
7
8
9
10
// Matter.Render 用法
var engine = Engine.create()
// ... 将物体加入到世界中
var render = Render.create({
element: document.body,
engine: engine,
options: options
})
Engine.run(engine)
Render.run(render)
element 是一个容器元素,使用时指定要渲染的节点
engine 指定为 Matter.Engine 实例
options 指定一些渲染的参数
Matter.Render 是将实例渲染到 Canvas 中的渲染器,控制视图层的样式,它的主要作用是用于开发和调试,默认情况下 Matter.Render 将只显示物体的线框(轮廓),这对于开发和调试很有帮助,但如果需要使用到全局实体渲染则需要将线框模式关闭 render.options.wireframes = false,另外它同样也适合制作一些简单的游戏,因为它包括了一些绘图选项、线框、向量、Sprite 精灵和视窗功能。
DEMO 戳这里
Body(刚体)
物体或者叫刚体,在物理引擎里特指坚硬的物体,具有固定的形状,不能形变。刚体可以用于表示一个箱子、一个球或是一块木头,每个物体都有自己的物理属性,质量、速度、摩擦力、角度等,还可以设置刚体的标记。Matter.Bodies 模块中内置了几种刚体,矩形 Matter.rectangle、多边形 Matter.polygon、圆形 Matter.circle 、梯形 Matter.trapezoid 等等。
JavaScript
1
2
3
4
5
6
7
// 创建刚体
var rect = Bodies.rectangle(200, 100, 50, 50), // 矩形
circle = Bodies.circle(300, 100, 25), // 圆
polygon = Bodies.polygon(450, 100, 5, 25), // 多边形
trapezoid = Bodies.trapezoid(590, 100, 50, 50, 3)// 梯形
// 将刚体添加到世界中
World.add(engine.world, [rect, circle, polygon, trapezoid])
DEMO 戳这里
Composite(复合体)
由刚体和复合材料通过约束组合在一起的就叫做复合体。复合体对外当作一个刚体,复合体的物理属性是通过所包含的刚体的属性综合计算出来的。Matter.Composite 模块包含用于创建和处理复合体的方法,另外还有一个 Matter.Composites 模块,提供了几种特别的复合材料,例如 链 Composites.chain、牛顿摆球 Composites.newtonsCradle、软体 Composites.softBody、汽车 Composites.car 、堆叠 Composites.stack 等等。
桥梁
JavaScript
1
2
3
4
5
6
7
8
9
10
11
// 使用堆叠创建桥梁
var group = Body.nextGroup(true)
var bridge = Composites.stack(150, 300, 9, 1, 10, 10, function(x, y) {
return Bodies.rectangle(x, y, 50, 20, {
collisionFilter: { // 过滤碰撞
group: group
}
})
})
// 创建链约束
Composites.chain(bridge, 0.5, 0, -0.5, 0, { stiffness: 0.9 })
DEMO 戳这里
布
JavaScript
1
2
3
4
5
6
7
8
9
10
// 软体
var cloth = Composites.softBody(200, 200, 20, 12, 5, 5, false, 8, {
friction: 0.00001, // 摩擦力
collisionFilter: {
group: Body.nextGroup(true)
},
render: {
visible: false
}
})
DEMO 戳这里
牛顿摆球
JavaScript
1
2
// 创建牛顿摆球
var newtonsCradle = Composites.newtonsCradle(300, 320, 5, 25, 150)
DEMO 戳这里
Constraint(约束)
约束可理解为通过一条线,将刚体 A 和刚体 B 两个刚体连接起来,被约束的两个刚体由于被连接在了一起,移动就相互受到了限制。Matter.Constraint 模块包含了用于创建和处理约束的方法,这个约束可以很宽松,也可以很紧绷,还可以定义约束的距离,约束具有弹性,可以用来当作橡皮筋。
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 创建一个矩形和圆形
var rect = Bodies.rectangle(400, 100, 50, 50, {
isStatic: true
}),
ball = Bodies.circle(400, 400, 50)
World.add(engine.world, [
rect,
ball,
Constraint.create({
bodyA: rect, // 约束刚体 A
pointA : { // 约束点 A
x: 0,
y: 0
},
bodyB: ball, // 约束刚体 B
pointB: { // 约束点 B
x: 0,
y: -50
},
stiffness: 0.6
})
])
DEMO 戳这里
MouseConstraint(鼠标约束)
如果你想让刚体与用户之间有交互,那就要在鼠标和刚体之间建立连接,也就是鼠标和刚体间的约束,Matter.MouseConstraint 模块包含用于创建鼠标约束的方法,提供通过鼠标或触摸(移动端时)移动刚体的能力,可以设置什么标记的物体才能被鼠标操纵,创建鼠标约束后,可以捕获到鼠标的各类事件。
JavaScript
1
2
3
4
5
// 全局鼠标约束
var mouseConstraint = MouseConstraint.create({
element: render.canvas
})
World.add(engine.world, mouseConstraint)
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 设置某个标记的物体才能被鼠标操纵
var categoryBall = 0x0001// 分类
var ball = Matter.Bodies.circle(300, 350, 32, {
density: 0.68, // 密度
restitution: 1, // 弹性
collisionFilter: {
category: categoryBall
}
})
var mouseConstraint = MouseConstraint.create({
element: render.canvas,
collisionFilter: {
mask: categoryBall
}
})
World.add(engine.world, mouseConstraint)
DEMO 戳这里
Vector(向量)
Matter.Vector 模块包含用于创建和操纵向量的方法,向量是引擎有关几何操作行为的基础,修改物体的运动状态基本都是使用向量来控制,例如赋予物体一个力,或者设置物体的速度、旋转角度,并且内置了多个向量的求解函数:向量积、标量积、格式化、垂直向量等等。
Events(事件)
Matter.Events 模块包含了绑定、移除和触发对象的方法。
绑定事件 Matter.Events.on(object, eventNames, callback)
移除事件 Matter.Events.off(object, eventNames, callback)
触发事件 Matter.Events.trigger(object, eventNames, event)
Matter.js 中的一些属性
施加力
Matter.Body.applyForce(body, position, force) 方法可以给刚体施加一个力,传入 X 和 Y 轴需要的力度值,通过这个方法你可以去模拟踢一个足球、投一个篮球的效果。
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
var ball = Bodies.circle(300, 100, 25, {
density: 0.68, // 密度
restitution: 0.8 // 弹性
})
World.add(engine.world, ball)
function addForce() {
var forceMagnitude = 0.02 * ball.mass
Body.applyForce(ball, ball.position, {
x : (forceMagnitude + Common.random() * forceMagnitude) * Common.choose([1, -1]),
y : -forceMagnitude + Common.random() * -forceMagnitude
})
}
addForce()
DEMO 戳这里
重力
可以设置 X、Y 轴的重力值,默认都为 1,参数在 0、1、-1 中选择使用。
JavaScript
1
2
3
4
// 实现反重力效果
engine.world.gravity.y = -1
// 无重力效果
engine.world.gravity.y = 0
DEMO 戳这里
睡眠状态
通过 enableSleeping: true 开启睡眠模式后,当刚体处于不受作用状态时,会进入睡眠状态,这样可以有效的提高引擎的性能,当物体被其他物体碰撞或者对刚体施加力时,刚体会被叫醒,引擎会继续对其进行计算模拟。
JavaScript
1
2
3
4
5
6
7
8
// 开启睡眠状态
var engine = Engine.create({
enableSleeping: true
})
// 还可以针对进入睡眠状态的刚体进行监听,比如将刚体移出世界
Event.on(ball, "sleepStart", function() {
World.remove(engine.world, ball)
})
DEMO 戳这里
摩擦力
摩擦力在 Matter.js 中分别提供了三种:摩擦力 friction、空气摩擦力 frictionAir 以及静止摩擦力 frictionStatic。friction 默认值是 0.1,取值范围在 0 – 1,当值为 0 意味着刚体可以摩擦力的无限滑动,1 意味着对刚体施加力后会立刻停止,frictionAir 默认值是 0.01,取值范围 0 – 1,当值为 0 意味着刚体在空间中移动时速度永远不会减慢,值越高时刚体在空间的移动速度越慢,frictionStatic 默认值 0.5,当值为 0 时意味着刚体几乎是静止的,值越高时意味着需要移动刚体所需的力就越大。
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
// 摩擦力
Bodies.rectangle(300, 70, 40, 40, {
friction: 0.01
})
// 空气摩擦力
Bodies.rectangle(300, 70, 40, 40, {
frictionAir: 0.05
})
// 静止摩擦力
Bodies.rectangle(300, 70, 40, 40, {
frictionStatic: 1
})
时间缩放
可以控制全局的时间,当值为 0 时为冻结模拟,值为 0.1 给出慢动作效果,值为 1.2 时给出加速效果。
JavaScript
1
engine.timing.timeScale = 0.1
这里就简单提及到几个属性,当然还有更多的属性比如:视图(View)、弹性(Restitution)等等,更详细的 API 可到官网查看。
Matter.js 调试
除了前面讲 Matter.Render 模块的时候提到的线框模式 wireframes 便于调试外,Matter.Render 模块其实还为我们提供了以下几种方法,便于我们自定义调试选项:
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
pixelRatio: 1, // 设置像素比
background: '#fafafa', // 全局渲染模式时背景色
wireframeBackground: '#222', // 线框模式时背景色
hasBounds: false,
enabled: true,
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 // 鼠标约束线
}
})
另外官方提供了三个调试工具,可单独使用或一起使用,如下:
工具:
MatterTools.Demo 用于运行和测试 DEMO
MatterTools.Gui 改变引擎的属性
MatterTools.Inspector 检查世界