Matter.js 快速上手:创建第一个 2D 物理世界
本文系统讲解如何使用 Matter.js 从零搭建第一个 2D 物理世界,涵盖核心模块架构、画布初始化、刚体碰撞、物理属性调优及常见踩坑指南。
一、认识 Matter.js 的核心协作模块
Matter.js 是一个轻量级、开源且功能完备的 JavaScript 2D 刚体物理引擎。在开始写代码前,首先需要理清其模块设计。初学者常误以为“只要调用一个函数就能在屏幕上画出小球”,但实际上 Matter.js 将数学计算与视觉渲染严格拆分成了不同的角色。
构建物理世界涉及的五个关键子模块如下:
- Matter.Engine:物理引擎的心脏。负责维护时间流逝,并在每个时刻计算所有刚体的重力下坠、速度变化与碰撞反馈。
- Matter.Render:内置的简易 Canvas 渲染器。它只负责“看”引擎里的数据并在画布上画出来。如果开发复杂大型游戏,可以用 PixiJS 或 Three.js 替换该模块。
- Matter.Runner:循环协调器。利用浏览器的
requestAnimationFrame确保物理世界的计算节奏与屏幕刷新率相一致。 - Matter.Bodies:刚体工厂。提供快速生成矩形、圆形、梯形等基础几何刚体的方法。
- Matter.Composite:物理对象容器。在 Matter.js 现代版本中,所有的物体、地面、弹簧约束都统一存放在
engine.world(一个根复合容器)中。
二、从零搭建物理世界的完整操作步骤
搭建第一个物理世界通常遵循固定的五个环节:引入库、解构命名空间、初始化引擎与画布、配置物理刚体,最后启动运行循环。
步骤 1:新建 HTML 并引入 Matter.js
创建一个基础的 index.html 文件,在页面中通过 CDN 脚本标签载入 Matter.js:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>My First Matter.js World</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #2c302e;
}
</style>
</head>
<body>
<!-- 引入官方 CDN 构建包 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
<script>
// 后续 JS 代码将写在这里
</script>
</body>
</html>
步骤 2:解构模块并初始化引擎与渲染器
在 <script> 中解构所需子模块,并创建 engine 与 render 实例:
// 1. 提取 Matter.js 常用类
const { Engine, Render, Runner, Bodies, Composite, Mouse, MouseConstraint } = Matter;
// 2. 创建物理计算引擎
const engine = Engine.create();
// 3. 创建画布渲染器
const render = Render.create({
element: document.body, // 画布挂载的目标父容器
engine: engine, // 关联的物理引擎
options: {
width: 800,
height: 600,
wireframes: false, // 设为 false 才能渲染实心填充色,否则仅显示线框
background: '#FAF8F3' // 画布背景底色
}
});
步骤 3:定义刚体(物体与静态边界)
注意:在 Matter.js 中,Bodies.rectangle(x, y, width, height) 传入的 x, y 是刚体的中心点坐标,而不是左上角坐标。
// 创建一个下落的方块:中心位于 (400, 100),宽 60,高 60
const box = Bodies.rectangle(400, 100, 60, 60, {
render: {
fillStyle: '#8A9478' // 自定义外观颜色
}
});
// 创建一个下落的圆形小球:中心位于 (420, 40),半径 30
const ball = Bodies.circle(420, 40, 30, {
restitution: 0.8, // 弹性恢复系数:0.8 代表具有明显的反弹效果
render: {
fillStyle: '#D97A53'
}
});
// 创建固定的静态地面:中心在 (400, 580),宽 800,高 40
// 必须设置 isStatic: true,否则地面也会受重力掉出屏幕!
const ground = Bodies.rectangle(400, 580, 800, 40, {
isStatic: true,
render: {
fillStyle: '#464B48'
}
});
// 创建一块左倾斜的静态滑梯挡板
const ramp = Bodies.rectangle(300, 350, 320, 20, {
isStatic: true,
angle: Math.PI * 0.12, // 倾斜约 21 度
render: {
fillStyle: '#464B48'
}
});
步骤 4:装配物体并启动世界
使用 Composite.add 将上述刚体一次性放入物理世界,随后运行渲染器与主循环调度器:
// 将刚体批量注册到物理世界容器中
Composite.add(engine.world, [box, ball, ground, ramp]);
// 启动渲染管线
Render.run(render);
// 创建并运行主循环调度器
const runner = Runner.create();
Runner.run(runner, engine);
步骤 5:增加鼠标交互(可选但强烈推荐)
为了让物理世界生动可玩,可以通过 MouseConstraint 允许用户通过鼠标光标随意抓取刚体并拖拽抛掷:
// 绑定鼠标事件到渲染画布上
const mouse = Mouse.create(render.canvas);
const mouseConstraint = MouseConstraint.create(engine, {
mouse: mouse,
constraint: {
stiffness: 0.2, // 拖拽弹簧硬度
render: {
visible: false // 隐藏拖拽时连向鼠标的弹性辅助线
}
}
});
// 装载鼠标约束,并将事件同步给渲染器
Composite.add(engine.world, mouseConstraint);
render.mouse = mouse;
三、刚体核心属性与力学行为解析
刚体的运动质感取决于其属性参数配置。下表梳理了调整物理手感时最常改动的四个属性:
| 属性名称 | 默认值 | 作用与影响 | 典型取值示例 |
|---|---|---|---|
isStatic |
false |
是否为不动刚体。设为 true 时不可位移,充当地面或障碍物。 | 墙壁、柱子设为 true |
restitution |
0 |
恢复弹性系数(0 到 1)。数值越高,碰撞反弹保留的速度越多。 | 金属块 0.1,橡胶球 0.85 |
friction |
0.1 |
表面滑动摩擦力。数值越大,与其它刚体接触时减速越剧烈。 | 冰面滑块 0.005,粗糙砂纸 0.8 |
density |
0.001 |
刚体密度。Matter.js 会根据面积和密度自动推算刚体质量 mass。 |
木块 0.001,重铁球 0.05 |
四、初学者常见认知误区与规避建议
在实际编写代码时,初次接触物理引擎的开发者往往容易在以下几个概念上产生混淆:
误区 1:“Matter.Render 只能用来开发简易玩具,做不成完整产品”
修正辨析:这种说法有其事实依据,但推导并不严谨。Matter.Render 本身确实只是官方提供的一个调试用渲染器,它的重点是准确地描绘碰撞凸包、轴对齐包围盒与物理锚点,而非追求炫丽的粒子光效或贴图序列帧。
但这并不代表 Matter.js 不能用于生产。在商业游戏或互动应用中,业界通行的标准做法是完全废弃 Matter.Render,仅利用 Matter.Engine 纯在内存中计算每个物理刚体的 position.x、position.y 与 angle,然后将这些数值直接同步赋值给 Pixi.js 的精灵(Sprite)或 Three.js 的网格(Mesh)。架构解耦正是 Matter.js 最具生命力的特性之一。
误区 2:“添加物体要用 World.add(...)”
修正辨析:许多网上的旧版教程中遍布 World.add(engine.world, body) 的写法。虽然在较旧的 Matter.js 0.14~0.17 中它能正常运行,但在现代新版本中官方已将其标为废弃,统一推荐使用 Composite.add(engine.world, body)。World 本质上就是一个顶级的 Composite 容器,使用现代统一 API 可以避免未来大版本升级带来的废弃警告。
误区 3:“为什么给刚体设置了颜色,界面上仍然全是灰色空心线框?”
修正辨析:这是 90% 的初学者都会遭遇的陷阱。Matter.js 的 Render 默认配置项中,wireframes 属性缺省为 true。在该模式下,所有刚体都会以透明内部、灰色描边的方式绘制以方便观察碰撞边缘。如果希望自定的 fillStyle 生效,必须在 Render.create 的 options 中显式声明 wireframes: false。
五、总结与极简上手清单
创建 2D 物理世界并不是一项深奥的技术。只要掌握“模块解构 → 引擎与画布创建 → 刚体注入容器 → 启动主循环”这一主线逻辑,就能迅速搭建出生动有趣的力学模拟场景。
AOS.js 动画不触发怎么办?排查 DOM 加载与移动端兼容问题
2026-11-05 17:02:26
sigma.js 怎么实现节点点击、拖拽与悬停提示交互
2026-11-05 15:03:27
Matter.js 与 PixiJS/Three.js 集成:分离物理计算与渲染
2026-11-05 13:43:48
主流JS弹幕库选型指南:Danmaku.js等库的功能与体积对比
2026-11-05 09:28:19
JavaScript点击事件监听与交互效果实例
2026-11-05 09:10:19








