这是一个基于 cannon-es 物理引擎和 Three.js 渲染引擎的刚体碰撞仿真 Web 应用。支持多种刚体形状、复合形状、约束系统,以及丰富的预设场景。
- 物理引擎: cannon-es (纯 JavaScript)
- 渲染引擎: Three.js
- 构建工具: Vite
- 测试框架: Puppeteer (E2E)
- ✅ 盒子 (Box)
- ✅ 球体 (Sphere)
- ✅ 圆柱 (Cylinder)
- ✅ 平面 (Plane)
- ✅ 复合形状 - 组合多个基础形状
- ✅ 铰链约束 (Hinge Constraint)
- ✅ 点对点约束 (Point-to-Point)
- ✅ 鼠标拖拽交互
- ✅ 实时物理模拟 (60 FPS)
- ⚖️ 钟摆链 - 5个铰链链接的物理钟摆
- 🔗 铰链盒子 - 4个用铰链连接的彩色盒子
- 🚗 车辆模型 - 带车轮的复合车身
- 📚 堆叠测试 - 24个盒子的稳定堆叠
- 🔺 金字塔 - 15个盒子的金字塔结构
- 🌧️ 球体雨 - 30个随机大小的球体掉落
- Node.js >= 16
- npm 或 yarn
- 克隆或下载项目
cd /Users/williamshakespeare/Desktop/bullet-collision/web-app- 安装依赖
npm install- 启动开发服务器
# 方式1: 使用 Python (推荐)
npm start
# 方式2: 使用 Vite
npm run dev- 访问应用
在浏览器打开:
http://localhost:8080
应用左侧有控制面板,分为三个部分:
- 📦 添加盒子 - 在随机位置创建一个随机大小的盒子
- 🔵 添加球体 - 在随机位置创建一个随机大小的球体
- 🛢️ 添加圆柱 - 在随机位置创建一个随机尺寸的圆柱
- 🧩 添加复合体 - 创建一个组合形状(盒子+球体+小盒子)
- ⚖️ 创建钟摆 - 创建5个铰链链接的钟摆,会自然摆动
- 🔗 铰链盒子 - 创建4个用铰链连接的彩色盒子链
- 🚗 创建车辆 - 创建带车轮的车辆模型(复合车身+4个铰链车轮)
- 📚 堆叠测试 - 创建24个盒子垂直堆叠
- 🔺 金字塔 - 创建15个盒子的金字塔(5+4+3+2+1)
- 🌧️ 球体雨 - 30个随机大小的彩色球体从天而降
- 🔄 重置场景 - 清空所有物体和约束
| 操作 | 功能 |
|---|---|
| 左键拖拽物体 | 点击并拖动物体,可以扔出去 |
| 右键拖拽背景 | 旋转视角,360°观察场景 |
| 滚轮 | 缩放视角,拉近或拉远 |
左下角显示实时信息:
- 物体数量 - 当前场景中的物体总数
- FPS - 实时帧率(应该保持在60左右)
除了预设场景,我们还提供了一个功能强大的可视化编辑器,让你能够:
- ✅ 自由添加各种刚体(盒子、球体、圆柱、复合体)
- ✅ 精确设置物理参数(质量、摩擦力、弹性等)
- ✅ 使用多种约束连接刚体(铰链、点对点、距离、固定)
- ✅ 实时编辑和调整参数
- ✅ 一键运行物理模拟
- ✅ 保存和加载自定义场景
方式1:从主页进入
- 在主页面左下角找到"🎨 打开编辑器"按钮
- 点击按钮进入编辑器
方式2:直接访问
http://localhost:5173/editor.html
在左侧面板点击对应按钮:
- 📦 盒子 - 长方体刚体
- 🔮 球体 - 球形刚体
- 🥫 圆柱 - 圆柱形刚体
- 🧩 复合体 - 复杂组合刚体
选中刚体后,右侧面板可编辑:
- 名称 - 刚体显示名称
- 质量 - 0=静态,>0=动态
- 摩擦力 - 0=光滑,1=高摩擦
- 弹性 - 0=不弹,1=超级弹
- 位置 - X/Y/Z 坐标
- 尺寸 - 根据类型不同而不同
- 在左侧选择约束类型(铰链/点对点/距离/固定)
- 按住
Ctrl键 - 依次点击两个刚体
- 约束自动创建
- ▶ 运行模拟 - 启动物理引擎
- ⏹ 停止 - 暂停模拟,返回编辑模式
- ↺ 重置位置 - 所有物体回到初始状态
- 💾 保存场景 - 保存为JSON文件
- 📂 加载场景 - 从文件加载
- 🗑 清空 - 删除所有内容
1. 添加一个盒子
2. 设置位置为 (0, 5, 0)
3. 按住Ctrl点击盒子,再点击空中的点(会自动创建固定点)
4. 选择"点对点"约束
5. 运行模拟
1. 添加3个盒子作为障碍物
2. 设置弹性为 0.9
3. 添加1个球体,弹性设为 0.95
4. 运行模拟观察弹跳
1. 添加6个盒子,排成一条线
2. 用铰链约束依次连接相邻盒子
3. 运行模拟
4. 用鼠标拖拽一端观察波动
完整的使用指南请参考:EDITOR_GUIDE.md
功能: 演示铰链约束和物理摆动
特点:
- 5个链接通过铰链连接
- 自然重力作用下的真实摆动
- 可以用鼠标推动观察效果
最佳体验:
- 创建钟摆后等待稳定
- 用鼠标轻轻推最下面的球
- 观察波动如何向上传播
功能: 演示多个铰链约束的复杂系统
特点:
- 4个彩色盒子用铰链垂直连接
- 每个盒子可以独立旋转
- 形成灵活的链条结构
最佳体验:
- 拖拽最上面的盒子
- 观察整个链条如何跟随
- 甩动盒子造成波浪运动
功能: 演示复合形状和多个约束
特点:
- 车身是复合形状(主体+车顶)
- 4个车轮用铰链连接到车身
- 真实的物理碰撞和滚动
最佳体验:
- 创建车辆后观察其掉落
- 用鼠标拖拽车身向上提
- 观察车轮如何自然跟随
功能: 测试物理引擎的稳定性
特点:
- 24个盒子垂直堆叠(3列 x 8层)
- 渐变颜色从底到顶
- 微小的随机偏移增加真实感
最佳体验:
- 观察堆叠是否稳定
- 在旁边添加一个球体砸向堆叠
- 观察碰撞和倒塌效果
功能: 演示大规模刚体系统
特点:
- 15个盒子组成金字塔(5+4+3+2+1)
- 暖色调渐变
- 考验碰撞检测性能
最佳体验:
- 观察金字塔的稳定性
- 点击"球体雨"添加球体
- 观察球体如何破坏金字塔
功能: 演示大量物体的碰撞和滚动
特点:
- 30个随机大小的球体
- 从高处随机位置掉落
- 彩虹色随机颜色
最佳体验:
- 先创建"堆叠测试"或"金字塔"
- 再创建"球体雨"
- 观察球体如何破坏现有结构
web-app/
├── index.html # 主页面
├── js/
│ └── main.js # 核心应用逻辑
├── tests/ # 测试套件
│ ├── unit/ # 单元测试
│ ├── e2e/ # 端到端测试
│ └── run-tests.js # 测试运行器
├── package.json # 依赖配置
└── README.md # 本文档
主应用类,负责:
- Three.js 场景初始化
- Cannon-es 物理世界初始化
- 物体和约束创建
- 鼠标交互处理
- 物理到视觉的同步
world.gravity.set(0, -9.82, 0); // 重力
world.broadphase = new CANNON.NaiveBroadphase(); // 碰撞检测
world.solver.iterations = 10; // 求解器迭代次数
world.step(1/60); // 60 FPS 步进- 在
main.js中添加新方法:
addNewShape() {
const position = {
x: Math.random() * 4 - 2,
y: 5 + Math.random() * 5,
z: Math.random() * 4 - 2
};
// Cannon.js 刚体
const shape = new CANNON.YourShape(...);
const body = new CANNON.Body({
mass: 1,
shape: shape,
position: new CANNON.Vec3(position.x, position.y, position.z)
});
this.world.addBody(body);
// Three.js 网格
const geometry = new THREE.YourGeometry(...);
const material = new THREE.MeshPhongMaterial({
color: Math.random() * 0xffffff
});
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(position.x, position.y, position.z);
mesh.castShadow = true;
this.scene.add(mesh);
this.objects.push({ body, mesh });
this.updateObjectCount();
}- 在
index.html中添加按钮:
<button onclick="app.addNewShape()">新形状</button>参考现有场景的方法,如 createStack():
createMyScene() {
// 创建你的场景
for (let i = 0; i < numObjects; i++) {
// 创建刚体和网格
// 添加到 world 和 scene
// 推入 objects 数组
}
this.updateObjectCount();
}npm testnpm run test:unitnpm run test:e2e- ✅ 物理世界初始化
- ✅ 刚体创建
- ✅ 复合形状
- ✅ 铰链约束
- ✅ 点对点约束
- ✅ 物理模拟步进
- ✅ 碰撞检测
- ✅ 页面加载
- ✅ 添加盒子
- ✅ 添加球体
- ✅ 添加复合体
- ✅ 创建钟摆
- ✅ 创建铰链盒子
- ✅ 重置场景
- ✅ FPS 性能
- ✅ 鼠标交互
A: 确保物体质量设置合理,过重的物体可能穿透。可以增加求解器迭代次数:
world.solver.iterations = 20; // 默认是 10A: 减少物体数量,或降低物体网格的面数。
A: 确保点击的是物体而不是背景。左键用于拖拽物体,右键用于旋转视角。
A: 当前版本不支持场景保存。可以手动记录物体的位置和类型,然后在代码中重现。
- 限制物体数量 - 建议不超过 200 个动态物体
- 使用简单形状 - 盒子和球体比复合形状性能更好
- 减少阴影 - 对于大量物体,可以关闭
castShadow - 调整求解器 - 减少迭代次数可以提高性能但降低精度
- v1.0.0 (2026-01-08)
- 初始版本
- 基础形状支持
- 复合形状支持
- 约束系统
- 6个预设场景
- 完整测试套件
ISC
欢迎提交 Issue 和 Pull Request!
开发完成时间: 2026年1月8日 开发者: Claude Code AI Assistant 测试状态: ✅ 所有测试通过