Cocos Creator 3.x 实战:用BoxCollider和CircleCollider做个简单的2D物理小游戏(附完整源码)
Cocos Creator 3.x 实战:打造2D物理弹球游戏的全流程指南
在游戏开发的世界里,物理引擎就像现实世界的重力法则,为虚拟角色赋予真实的运动规律。Cocos Creator 3.x内置的物理系统让开发者无需从头造轮子,就能实现各种有趣的物理互动效果。今天,我们将通过制作一个完整的2D弹球游戏,带你深入理解BoxCollider和CircleCollider的实际应用。
1. 项目准备与环境搭建
首先确保你已经安装了最新版的Cocos Creator 3.x(建议3.8或更高版本)。启动编辑器后,创建一个新的2D项目,命名为"PhysicsBallGame"。
在项目设置中,我们需要配置物理系统:
- 点击菜单栏的"项目"→"项目设置"
- 选择"物理"选项卡
- 确保"启用物理系统"已勾选
- 重力设置保持默认的Y轴-980(模拟地球重力)
// 也可以在脚本中动态启用物理系统 cc.director.getPhysicsManager().enabled = true; cc.director.getPhysicsManager().gravity = cc.v2(0, -980);提示:对于2D游戏,建议将场景的Canvas组件RenderMode设置为"2D",这样可以避免不必要的3D计算开销。
2. 游戏场景构建与碰撞体配置
我们的弹球游戏将包含以下核心元素:
- 玩家控制的弹球(CircleCollider)
- 静态平台(BoxCollider)
- 可破坏的砖块(BoxCollider)
- 收集物品(CircleCollider)
2.1 创建玩家弹球
- 在层级管理器右键创建新节点,命名为"PlayerBall"
- 添加Sprite组件,选择一个圆形精灵图
- 添加RigidBody2D组件,设置类型为Dynamic
- 添加CircleCollider组件,调整radius匹配精灵大小
// PlayerBall的组件属性参考 rigidBody: { type: cc.RigidBodyType.Dynamic, linearDamping: 0.5, angularDamping: 0.5 }, circleCollider: { radius: 40, offset: cc.v2(0, 0) }2.2 搭建游戏平台
- 创建新节点"Platform"
- 添加Sprite组件,使用长方形精灵图
- 添加RigidBody2D组件,类型设为Static
- 添加BoxCollider组件,调整size匹配平台尺寸
// Platform的碰撞体配置示例 boxCollider: { size: cc.size(600, 30), offset: cc.v2(0, -300) }3. 碰撞分组与交互逻辑
为了让游戏中的不同元素能够正确交互,我们需要设置碰撞分组:
| 分组名称 | 说明 | 与玩家碰撞 |
|---|---|---|
| Player | 玩家球 | - |
| Platform | 平台 | ✓ |
| Brick | 砖块 | ✓ |
| Item | 收集物 | ✓ |
在项目设置的"分组管理"中添加这些分组,并配置碰撞矩阵:
// 初始化碰撞分组 const collisionManager = cc.director.getCollisionManager(); collisionManager.enabled = true; // 设置节点的碰撞分组 this.node.group = 'Player';4. 实现游戏核心逻辑
4.1 玩家控制脚本
为PlayerBall节点创建新脚本"PlayerController.ts":
const {ccclass, property} = cc._decorator; @ccclass export default class PlayerController extends cc.Component { @property(cc.Float) moveForce: number = 500; private rigidBody: cc.RigidBody2D = null; start() { this.rigidBody = this.getComponent(cc.RigidBody2D); } update(dt) { const horizontal = cc.systemEvent.isKeyDown(cc.macro.KEY.left) ? -1 : cc.systemEvent.isKeyDown(cc.macro.KEY.right) ? 1 : 0; this.rigidBody.applyForceToCenter( cc.v2(horizontal * this.moveForce, 0), true ); } onCollisionEnter(other: cc.Collider, self: cc.Collider) { if (other.group === 'Item') { other.node.destroy(); // 增加分数逻辑... } } }4.2 砖块生成系统
创建砖块预制体并实现生成逻辑:
// BrickManager.ts @property(cc.Prefab) brickPrefab: cc.Prefab = null; @property(cc.Integer) rows: number = 5; @property(cc.Integer) columns: number = 8; start() { this.generateBricks(); } generateBricks() { const startX = -300; const startY = 200; const spacing = 80; for (let row = 0; row < this.rows; row++) { for (let col = 0; col < this.columns; col++) { const brick = cc.instantiate(this.brickPrefab); brick.setPosition(startX + col * spacing, startY - row * 40); this.node.addChild(brick); } } }5. 游戏优化与效果增强
5.1 物理材质调整
为不同对象设置不同的物理材质可以显著改善游戏手感:
| 对象 | 弹性 | 摩擦 | 密度 |
|---|---|---|---|
| 玩家球 | 0.8 | 0.2 | 1.0 |
| 平台 | 0.4 | 0.5 | 0.0 |
| 砖块 | 0.6 | 0.3 | 0.5 |
// 设置物理材质 const physicsMaterial = new cc.PhysicsMaterial(); physicsMaterial.restitution = 0.8; // 弹性 physicsMaterial.friction = 0.2; // 摩擦 this.getComponent(cc.CircleCollider).material = physicsMaterial;5.2 视觉效果增强
- 碰撞粒子效果:
onCollisionEnter(other: cc.Collider) { const particle = this.spawnParticle(); particle.setPosition(this.node.position); particle.getComponent(cc.ParticleSystem).resetSystem(); } spawnParticle(): cc.Node { // 返回预加载的粒子节点实例 }- 屏幕震动效果:
shakeScreen(duration: number, intensity: number) { const originalPos = this.node.position; this.schedule(() => { const offset = cc.v2( (Math.random() - 0.5) * intensity, (Math.random() - 0.5) * intensity ); this.node.position = originalPos.add(offset); }, 0.01, duration * 100, 0); }6. 项目构建与发布
完成开发后,我们可以将游戏导出为Web平台:
- 点击菜单栏的"项目"→"构建发布"
- 选择Web Mobile模板
- 设置合适的屏幕方向(建议Landscape)
- 点击"构建"按钮
构建完成后,你可以在build目录中找到完整的游戏文件,可以直接部署到Web服务器或上传到小游戏平台。
注意:发布前建议进行以下优化:
- 压缩纹理资源
- 合并小图集
- 启用引擎的自动图集功能
- 移除未使用的脚本和资源
在开发过程中,我经常遇到的一个坑是忘记为动态物体设置合适的线性阻尼(linearDamping),这会导致球体运动过于敏感或滑动时间过长。经过多次测试,0.3-0.6之间的阻尼值通常能提供最佳的手感体验。
