JavaScript物理引擎之Matter.js与Box2d性能对比

更新日期: 2019-01-19阅读: 2.8k标签: 引擎

前言

在挑选JavaScript 2D物理引擎的时候,不外乎两种主流的选择:第一种是老牌的Box2D,最开始的版本是C++实现的,后来有了很多种实现,比如flash版本和js版本,具体可看:https://stackoverflow.com/que...;第二种是新潮的matter-js,matter-js比较轻量,API和文档都比较有友好。

这段时间先后折腾了matter-js和Box2D,因为项目需要在微信小游戏端运行,对性能要求比较高,最终还是选择了Box2D。

但凡涉及到这种需要经常看源码才能使用的库中文社区都非常少干货,这段时间折腾之后打算整理一些文章,分享给社区也作为一个知识备忘。

本文简单对两个引擎的性能在不同平台上进行对比,其中Box2D采用的是TypeScript实现的版本:https://github.com/flyover/bo..., 作者仍然在更新,并且我看了下CocosCreator内置的物理引擎也是基于这个进行的封装,社区还是可以得到保证的。matter-js采用的是0.14.2版本(感觉作者已经更新不动这个库了:),大半年都不怎么活跃了)。


测试案例

在屏幕随机位置重复创建相同的矩形刚体,使之自由落体到底部,计算不同刚体数量下,全部刚体落地后每一帧的物理计算平均耗时。下面是测试中的一些截图:



影响性能的因素

  1. 机器本身的配置;
  2. JIT:苹果端微信小游戏没有JIT,性能会大打折扣;
  3. 刚体的随机性:刚体在随机位置生成的过程中,如果与其他刚体重叠,物理引擎需要更多的性能消耗来修正重叠,因此,每次运行测试用例数据上都不可避免会有波动。
  4. 引擎本身的设计:比如Matter.js没有圆形的定义,创建圆形刚体本质上是创建25边形,而Box2d天然就设计了圆形刚体,所以对于圆形刚体,两个引擎会存在不小的差异。


数据采集

因为是测试物理引擎的性能,这里不考虑FPS,只采集物理引擎更新每一帧的时间,因为除开物理引擎,渲染引擎(PixiJS)也会带来性能消耗。

// Box2d数据打点
let positionIterations = 3;
let velocityIterations = 8;
let timeStep           = 1 / 60;
Performance.startPoint('box2dUpdateCost');
world.Step(timeStep, velocityIterations, positionIterations);
Performance.endPoint('box2dUpdateCost');
// Matter.js数据打点
Performance.startPoint('matterUpdateCost');
matter.Engine.update(this.engine, 1e3 / this.fps);
Performance.endPoint('matterUpdateCost');
// 计算平均耗时
function calAverage(list, key) {
    let sum = list.reduce((total, curr) => curr[key] + total, 0);
    console.log(sum / list.length)
}

// 所有数据会收集到一个数组里面
let data = Performance.print();

//calAverage(data, 'matterUpdateCost');
calAverage(data, 'box2dUpdateCost');


Box2D数据

机型10个刚体20个刚体50个刚体100个刚体200个刚体300个刚体
MacBook Pro 20150.2ms0.4ms~0.5ms0.6ms~0.8ms1.3ms~1.6ms4.6ms~5.6ms7ms~8ms
iPhone7 Plus微信小游戏3.3ms~3.5ms4.5ms~5.5ms7.5ms~8.5ms13ms~14ms33ms60ms+
OPPO R11 Plus微信小游戏1.5ms~2.5ms1.8ms~3ms3.6ms6ms~8ms9ms~12ms17ms~19ms

matter-js数据

机型10个刚体20个刚体50个刚体100个刚体200个刚体300个刚体
MacBook Pro 20150.5ms~0.6ms0.6ms~1ms2ms~3ms3.5ms~4ms6ms~8ms12ms~13ms
iPhone7 Plus微信小游戏2.3ms~2.8ms3.0ms~3.5ms6.0ms~6.5ms11.5ms~12ms26ms~28ms45ms
OPPO R11 Plus微信小游戏1.5ms~2.5ms2.5ms5~6ms8ms12ms~14ms30ms

结论

在PC端,Box2d全面战胜了matter-js,在苹果的微信小游戏端,因为没有JIT,Box2d性能反而不如matter-js,而回到安卓的微信小游戏端,因为有JIT,Box2d同样是可以战胜matter-js的。


关于圆形刚体

上面提到了两个引擎对于圆形刚体的设计,因为matter-js没有正统的圆形,我大胆猜测圆形刚体的性能Box2D会大大高于matter-js!

特意去翻了下各自的源码,首先我们来看看matter-js的:

Bodies.circle = function(x, y, radius, options, maxSides) {
    options = options || {};
    var circle = {
        label: 'Circle Body',
        circleRadius: radius
    };
                                
     // approximate circles with polygons until true circles implemented in SAT
    maxSides = maxSides || 25;
    var sides = Math.ceil(Math.max(10, Math.min(maxSides, radius)));

    // optimisation: always use even number of sides (half the number of unique axes)
    if (sides % 2 === 1)
        sides += 1;
        
    return Bodies.polygon(x, y, sides, radius, Common.extend({}, circle, options));
};

从上面的代码可得,matter-js将25边形当成圆,这里在进行碰撞检测的时候,会比纯圆有更多的计算量,不知道matter-js作者是出于什么目的这样设计。

再来看看Box2D版本的实现:

class b2CircleShape extends b2Shape {
      constructor(radius = 0) {
          super(exports.b2ShapeType.e_circleShape, radius);
          this.m_p = new b2Vec2();
      }
      Set(position, radius = this.m_radius) {
          this.m_p.Copy(position);
          this.m_radius = radius;
          return this;
      }
}

与matter-js相比,Box2D的圆与多边形是独立的。

多说无益,我们对比下100个刚体状态下,两个引擎的数据对比,为了凸显差距,我们选择Box2D打不过matter-js的苹果端微信小游戏平台查看数据:

| 引擎 | 耗时 |
| ------------ | ------------ | 
| Box2D | 8ms | 
| matter-js | 25ms!! |

我们可以得出一个有意思的结论:同样是100个刚体,矩形刚体的耗时是13ms~14ms,而圆形刚体的耗时下降到了8ms,这对于一些弹球类的游戏无疑是福音,据我的观察,100个圆形刚体在苹果端微信小游戏下面丝毫不会卡顿。而matter-js的耗时从11.5ms~12ms上升到了25ms,显然就是在越多边形碰撞检测需要的计算量越大!


来自:https://segmentfault.com/a/1190000017946077

链接: https://www.fly63.com/article/detial/1842

V8引擎是如何工作?

V8是google开发的JavaScript引擎, 它是 开源的 ,而且是用C++编写的。它用于客户端(Google Chrome)和服务器端(node.js)JavaScript应用程序。V8最初旨在提高Web浏览器中JavaScript执行的性能。为了提升速度,V8将JavaScript代码转换为更高效的机器代码,而不是使用解释器。

Javascript模版引擎mustache.js简介

最近使用ELK的sentinl进行告警配置,sentinl的邮件通知支持mustache。mustache的核心是标签和logic-less.标签: 定义模板的时候,使用了{{name}}、{{#systems}}{{/systems}}标记. 这就是mustache的标签,只不过用{{}}替代了<>

JavaScript 引擎

编写Web代码有时会让开发人员编写一系列字符并像魔术那样神奇,这些字符会在浏览器中变成具体的图像,文字和动作。了解该技术可以帮助开发人员更好地调整他们作为程序员的技能

JS 引擎 V8 发布 v7.4,性能又大幅提高了

JavaScript 引擎 V8 发布了 7.4 版本,目前处于 beta 阶段,正式版将于几个星期后与 Chrome 74 Stable 一起发布。此版本带来了一些新特性,并极大提升了性能。

精读《V8 引擎 Lazy Parsing》

本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧!这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性能。

JavaScript引擎是如何工作的?从调用栈到Promise你需要知道的一切

你有没有想过浏览器是如何读取和运行 JavaScript 代码的吗?这看起来很神奇,但你可以学到一些发生在幕后的事情。让我们通过介绍 JavaScript 引擎的精彩世界在这种语言中尽情畅游。

从Google V8引擎剖析Promise实现

本文阅读的源码为Google V8 Engine v3.29.45,此版本的promise实现为js版本,在后续版本Google继续对其实现进行了处理。引入了es6语法等,在7.X版本迭代后,逐渐迭代成了C版本实现。

V8引擎-枚举+位运算实现参数配置

基本上从初始化引擎,到Isolate、handleScope、Context一直到编译其实都有记录,但是实在是无从下手。虽说我的博客也没有什么教学意义,但是至少也需要有一个中心和结论。

Node js 视图引擎

Node js 视图引擎就像 Laravel 中的 Blade。其最基本的定义是,视图引擎是帮助我们用比通常更短、更简单的方式编写 HTML 代码并重用的工具。此外,它还可以从服务器端导入数据并渲染最终的 HTML

规则引擎解决方案浅析

用于页面,流程,扩展点实现的选择;输出结果:实现的位置;编排无数的条件积木和行为积木,达到业务逻辑计算,券库存消减的目的;输出结果:商品重计算后的价格;通过订单,售后单,会员等信息编排和判断

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!