Cax + Matter-js 物理引擎结合使用

简介:

最初试过 box2dweb 与 cax框架 结合使用,发现 box2dweb 的代码会导致 webpack 编译出的 cax 包模块执行顺序乱套。 box2dweb 貌似也没有官方文档和维护地址,所以弃坑转战 Matter-js。

Matter-js 是 Github 上最流行的 Web 2D 物理引擎,主要有如下特性:

  • 支持刚体、混合体、复合体
  • 支持凹凸多边形刚体
  • 支持刚体间约束条件
  • 内置睡眠与静止身体
  • 物理模拟时间加快变慢
  • 移动兼容(触摸事件和PC鼠标事件响应)
  • 物理性质(质量、面积、密度、动量守恒、摩擦阻力、重力、弹性或非碰撞检测以及恢复等)

开始结合 Cax 和 Matter-js

引入 js

先在 HTML 引入 matter-js 和 cax, 你可以通过 npm 或 cdn 获取 js:

准备工作

页面添加 Canvas

<canvas id="myCanvas" width="800" height="600"></canvas>
复制代码

提前声明好变量:

var Engine = Matter.Engine,
            Render = Matter.Render,
            World = Matter.World,
            Bodies = Matter.Bodies,
            Composites = Matter.Composites,
            Body = Matter.Body,
            Constraint = Matter.Constraint,
            MouseConstraint = Matter.MouseConstraint,
            Common = Matter.Common,
            Events = Matter.Events,
            Composite = Matter.Composite
复制代码

创建刚体

Bodies.rectangle(100, 49, 800, 44, { isStatic: true })
复制代码
  • 前四个参数分别代表 x y width height。需要注意的是 x 和 y 是矩形中心的坐标
  • isStatic 为 true 的话代表是静止刚体,不传或者传 false 为可运动刚体。

创建四面墙并添加到世界

// 创建引擎
var engine = Engine.create();

// 创建四面墙壁墙壁并添加到世界
var offset = 10;
World.add(engine.world, [
    Bodies.rectangle(400, 600 - offset, 800, offset * 2, { isStatic: true }),
    Bodies.rectangle(400, offset, 800, offset * 2, { isStatic: true }),
    Bodies.rectangle(offset, 300, offset * 2, 600, { isStatic: true }),
    Bodies.rectangle(800 - offset, 300, offset * 2, 600, { isStatic: true }),
]);
复制代码

创建物体并添加到世界

var stack = Composites.stack(20, 20, 6, 4, 0, 0, function (x, y) {
    if (Common.random() > 0.5) {
        return Bodies.rectangle(x, y, 64, 64, {
            bitmap: new cax.Bitmap("img/box.jpg")
        });
    } else {
        return Bodies.circle(x, y, 46, {
            desity: 0.0005,
            frictionAir: 0.06,
            friction: 0.01,
            bitmap: new cax.Bitmap("img/basketball.png"),

        });
    }
});

World.add(engine.world, stack);
复制代码

通过Composites.stack(xx, yy, columns, rows, columnGap, rowGap, callback)可以用来创建物体堆。 参数xx,yy分别为物体堆中第一个物体的x和y坐标,columns和 rows分别为所要创建的物体堆的列数和行数,columnGap和rowGap分别为物体与物体之间的列间隙和行间隙,最后,由var body = callback(x, y, column, row, lastBody, i); 可以看出callback为生成的具体物体的方法。

看以看到,创建的时候挂在 bitmap 上去用户后续的渲染。

发动引擎

Engine.run(engine)
复制代码

初始化渲染墙壁和物体

var bodies = Composite.allBodies(engine.world);

for (var i = 0; i < bodies.length; i += 1) {
    var obj = bodies[i]
    if (obj.bitmap) {
        obj.bitmap.x = obj.position.x
        obj.bitmap.y = obj.position.y
        if (obj.label === 'Circle Body') {
            obj.bitmap.scaleX = obj.bitmap.scaleY = 92 / 128
            obj.bitmap.originX = 64
            obj.bitmap.originY = 64
            obj.bitmap.rotation = obj.angle * 180 / Math.PI
        } else {
            obj.bitmap.scaleX = obj.bitmap.scaleY = 64 / 200
            obj.bitmap.originX = 100
            obj.bitmap.originY = 100
            obj.bitmap.rotation = obj.angle * 180 / Math.PI
        }
        stage.add(obj.bitmap)
    }
}

//墙壁
var topRect = new cax.Rect(800, 20, { fillStyle: '#2CB044' })
stage.add(topRect)
var bottomRect = new cax.Rect(800, 20, { fillStyle: '#2CB044' })
bottomRect.y = 600 - 20
stage.add(bottomRect)
var leftTop = new cax.Rect(20, 600, { fillStyle: '#2CB044' })
stage.add(leftTop)
var rightRect = new cax.Rect(20, 600, { fillStyle: '#2CB044' })
rightRect.x = 800 - 20
stage.add(rightRect)
复制代码
  • 通过 Composite.allBodies 可以拿到所以刚体
  • 通过设置 bitmap 的 scaleX 和 scaleY 可以使 刚体大小和纹理大小对应起来

更新渲染舞台

cax.setInterval(function () {
    var bodies = Composite.allBodies(engine.world);
    for (var i = 0; i < bodies.length; i += 1) {
        var obj = bodies[i]
        if (obj.bitmap) {
            obj.bitmap.x = obj.position.x
            obj.bitmap.y = obj.position.y
            obj.bitmap.rotation = obj.angle * 180 / Math.PI
        }
    }

    stage.update()
}, 16)
复制代码

添加 Matter-js 内置 Debug Canvas

var render = Render.create({
    element: document.body,
    engine: engine,
    options: {
        wireframes: false
    }
});
var renderOptions = render.options;

renderOptions.wireframes = true;
Render.run(render);
复制代码

最终效果:



原文发布时间为:2018年06月26日
原文作者:当耐特
本文来源掘金如需转载请联系原作者
相关文章
|
5月前
|
JavaScript 前端开发 算法
Box2D(现在通常称为Box2D.js或者其WebAssembly版本,Emscripten Box2D)是一个流行的2D物理引擎,用于模拟刚体动力学、碰撞检测与响应以及关节约束等物理现象
【6月更文挑战第16天】Box2D.js,基于C++的2D物理引擎,经Emscripten编译为WebAssembly,用于JavaScript游戏中的真实物理模拟,包含碰撞检测和关节约束。它提供高效的碰撞检测,易于扩展和定制物理属性。使用步骤涉及初始化世界、创建刚体、添加碰撞形状、模拟物理及处理碰撞事件。物理引擎虽提升逼真度,但也增加复杂性和性能需求。其他选项如p2.js、matter.js和ammo.js也可供选择。
150 8
|
6月前
|
JavaScript 前端开发 算法
在JS小游戏中使用Box2D或其他物理引擎
【5月更文挑战第14天】Box2D(现在通常称为Box2D.js或者其WebAssembly版本,Emscripten Box2D)是一个流行的2D物理引擎,用于模拟刚体动力学、碰撞检测与响应以及关节约束等物理现象。虽然Box2D本身是用C++编写的,但它可以通过Emscripten等技术被编译为WebAssembly,从而在JavaScript环境中高效运行。
88 4
|
移动开发 JavaScript 前端开发
PhysicsJS:基于JavaScript的强大的物理引擎
PhysicsJS是一个基于JavaScript、模块化、可扩展、易于使用的物理引擎。
733 0
PhysicsJS:基于JavaScript的强大的物理引擎
|
Web App开发 JavaScript 前端开发
|
JavaScript 前端开发 HTML5
Matter.js – 你不能错过的 2D 物理引擎
  Matter.js 是一个 JavaScript 2D 刚体物理引擎的网页。Matter.Engine 模块包含用于创建和操作引擎的方法。这个引擎是一个管理更新和渲染世界的模拟控制器。 Matter.js 目前是测试版本,这意味着 API 仍在开发中,可能偶尔会发生变化。
1903 0
|
JavaScript 前端开发 数据可视化
Verlet-js:超炫的开源 JavaScript 物理引擎
  Verlet-js 是一个简单的集成 Verlet 的物理引擎,基于 JavaScript 编写,作者是 Sub Protocol。粒子系统、距离限制、角度限制等,Verlet-js 都能支持,基于这些基础,它可以帮助你构建几乎任何你能想象到的任何东西。
1053 0
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
97 2
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
130 4
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
82 4