技术标签: 移动开发 H5 物理引擎 matter
物理引擎是一个计算机程序,使用质量、速度、摩擦力和空气阻力等变量,模拟了一个近似真实的物理系统,为刚性物体赋予真实的物理效果,比如重力、旋转和碰撞等效果,让物体的行为表现的更加趋向真实,例如,守望先锋的英雄在跳起时,系统所设置的重力参数就决定了他能跳多高,下落时的速度有多快,子弹的飞行轨迹等等。
四个例子不同的效果,模拟物体落入斜坡的表现
物理引擎通常有两种常见类型:实时物理引擎和高精度物理引擎。高精度物理引擎需要更多的处理能力来计算非常精确的物理,通常使用在科学研究(计算物理学)和动画电影制作。实时物理引擎常用于电子游戏并且简化了算法,降低精确度以减少处理时间,使得在游戏中有更好的处理速度。
CS1.5 应用的是真实度比较差的物理引擎,人物死亡后倒地动作是固定的,即使有障碍物也会执行这个动作,所以人物穿过了门。
而 CS:GO 因为采用了 Source Engine 开发,模拟较为精细,所以人物死亡之后的姿势可以根据物理学自动计算,所以可以躺在杆上,使游戏更加真实。
Matter.js 是一个用于 Web 的 JavaScript 2D 物理引擎库,该项目诞生于 2014 年 2 月 28 号(0.5.0-alpha 版本),目前已更新迭代了 11 个版本(最新为 0.12.0 版本),它相较于老牌的 Box2D 引擎库,Matter.js 更为轻量级(压缩版仅有 84 KB),并且在性能和功能方面也不逊色。
在没有 Matter.js 前,你想去制作一个物理游戏不仅需要扎实数学知识和物理知识,并且需要通过编程语言表示出来让机器读懂。而有 Matter.js 就不一样了,它为开发者提供了许多的功能模块,通过简单易用的 API 就可以实现例如弹跳、碰撞、重力、滚动等物理效果。
首先,需要下载开发版本或者稳定版定,并将脚本加入到页面中,即可开启旅程。
1 |
<script src="matter.js" type="text/javascript"></script> |
你也可以使用包管理工具 Bower 或 NPM
1 |
$ bower install matter-js |
1 |
$ npm install matter-js |
刚体 | 复合体 | 复合材料 |
凹面和凸面 | 物理特性(质量、面积、密度等) | 弹性(弹性和非弹性碰撞) |
碰撞(粗略阶段、中间阶段、精细阶段) | 稳定的堆叠和静止 | 动量守恒 |
摩擦力和阻力 | 事件监听 | 约束 |
重力 | 睡眠和静态物体 | 圆角(倒角) |
视图(平移、缩放) | 碰撞查询(射线追踪、区域测试) | 时间缩放(减速、加速) |
Canvas 渲染器(支持向量和纹理) | MatterTools 工具(创建、测试和调试) | 世界状态序列化,需要 resurrect.js |
跨浏览器(Chrome、Firefox、Safari、IE8+) | 兼容移动端(触摸、响应) | 原生 JS 实现 |
大多数的物理引擎对于物理模拟的要素都有着相近的概念,不同的引擎差别在于使用的方式,功能的全面性,模拟的精细度等层面,下面就先从物理世界的基础概念讲起。
Engine(引擎)和 World(世界)
Matter.Engine
模块包含了创建和处理引擎的方法,引擎是负责管理和更新模拟世界的控制器,引擎可以控制时间的缩放,可以检测所有的碰撞事件,并且拿到所有碰撞的物体对(pairs)。
在 Matter.js 中任何的物体都需要一个容身处,而存放这些物体的地方,我们称之为世界,物体必须添加到世界里,然后由引擎运行这个世界。而创建世界需要使用到 Matter.World
模块,该模块包含了用于创建和操作世界的方法,一个 Matter.World
相当于一个复合物体,物体、约束、复合物体的聚合体,其次世界还有额外的一些属性,比如重力、边界。
Render(渲染)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 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 精灵和视窗功能。
Body(刚体)
物体或者叫刚体,在物理引擎里特指坚硬的物体,具有固定的形状,不能形变。刚体可以用于表示一个箱子、一个球或是一块木头,每个物体都有自己的物理属性,质量、速度、摩擦力、角度等,还可以设置刚体的标记。Matter.Bodies
模块中内置了几种刚体,矩形 Matter.rectangle
、多边形 Matter.polygon
、圆形 Matter.circle
、梯形 Matter.trapezoid
等等。
1 2 3 4 5 6 7 8 |
// 创建刚体 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]); |
Composite(复合体)
由刚体和复合材料通过约束组合在一起的就叫做复合体。复合体对外当作一个刚体,复合体的物理属性是通过所包含的刚体的属性综合计算出来的。Matter.Composite
模块包含用于创建和处理复合体的方法,另外还有一个 Matter.Composites
模块,提供了几种特别的复合材料,例如 链 Composites.chain
、牛顿摆球 Composites.newtonsCradle
、软体 Composites.softBody
、汽车 Composites.car
、堆叠 Composites.stack
等等。
桥梁
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 使用堆叠创建桥梁 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 }); |
布
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 } }); |
牛顿摆球
1 2 |
// 创建牛顿摆球 var newtonsCradle = Composites.newtonsCradle(300, 320, 5, 25, 150); |
Constraint(约束)
约束可理解为通过一条线,将刚体 A 和刚体 B 两个刚体连接起来,被约束的两个刚体由于被连接在了一起,移动就相互受到了限制。Matter.Constraint
模块包含了用于创建和处理约束的方法,这个约束可以很宽松,也可以很紧绷,还可以定义约束的距离,约束具有弹性,可以用来当作橡皮筋。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// 创建一个矩形和圆形 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 }) ]); |
MouseConstraint(鼠标约束)
如果你想让刚体与用户之间有交互,那就要在鼠标和刚体之间建立连接,也就是鼠标和刚体间的约束,Matter.MouseConstraint
模块包含用于创建鼠标约束的方法,提供通过鼠标或触摸(移动端时)移动刚体的能力,可以设置什么标记的物体才能被鼠标操纵,创建鼠标约束后,可以捕获到鼠标的各类事件。
1 2 3 4 5 6 |
// 全局鼠标约束 var mouseConstraint = MouseConstraint.create({ element: render.canvas }); World.add(engine.world, mouseConstraint); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 设置某个标记的物体才能被鼠标操纵 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); |
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.Body.applyForce(body, position, force)
方法可以给刚体施加一个力,传入 X 和 Y 轴需要的力度值,通过这个方法你可以去模拟踢一个足球、投一个篮球的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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(); |
重力
可以设置 X、Y 轴的重力值,默认都为 1,参数在 0、1、-1 中选择使用。
1 2 3 4 5 |
// 实现反重力效果 engine.world.gravity.y = -1; // 无重力效果 engine.world.gravity.y = 0; |
睡眠状态
通过 enableSleeping: true
开启睡眠模式后,当刚体处于不受作用状态时,会进入睡眠状态,这样可以有效的提高引擎的性能,当物体被其他物体碰撞或者对刚体施加力时,刚体会被叫醒,引擎会继续对其进行计算模拟。
1 2 3 4 5 6 7 8 9 |
// 开启睡眠状态 var engine = Engine.create({ enableSleeping: true }); // 还可以针对进入睡眠状态的刚体进行监听,比如将刚体移出世界 Event.on(ball, "sleepStart", function() { World.remove(engine.world, ball); }); |
摩擦力
摩擦力在 Matter.js 中分别提供了三种:摩擦力 friction
、空气摩擦力 frictionAir
以及静止摩擦力 frictionStatic
。friction
默认值是 0.1,取值范围在 0 - 1,当值为 0 意味着刚体可以摩擦力的无限滑动,1 意味着对刚体施加力后会立刻停止,frictionAir
默认值是 0.01,取值范围 0 - 1,当值为 0 意味着刚体在空间中移动时速度永远不会减慢,值越高时刚体在空间的移动速度越慢,frictionStatic
默认值 0.5,当值为 0 时意味着刚体几乎是静止的,值越高时意味着需要移动刚体所需的力就越大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 摩擦力 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 时给出加速效果。
1 |
engine.timing.timeScale = 0.1; |
这里就简单提及到几个属性,当然还有更多的属性比如:视图(View)、弹性(Restitution)等等,更详细的 API 可到官网查看。
除了前面讲 Matter.Render
模块的时候提到的线框模式 wireframes
便于调试外,Matter.Render
模块其实还为我们提供了以下几种方法,便于我们自定义调试选项:
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
用于运行和测试 DEMOMatterTools.Gui
改变引擎的属性MatterTools.Inspector
检查世界下载
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数