Cocos Creator物理引擎
物理引擎简介
Cocos Creator 内置的物理引擎是基于 Box2D 的 2D 物理引擎,它可以帮助开发者轻松地在游戏场景中实现物理效果,如碰撞检测、刚体运动、重力、关节等。物理引擎的使用可以大大提升游戏的真实感和互动性,使得游戏更加生动有趣。
物理引擎的主要功能包括:
-
碰撞检测:检测游戏对象之间的碰撞,并触发相应的事件。
-
刚体运动:模拟物体的物理运动,如重力、摩擦力等。
-
关节:模拟物体之间的连接,如弹簧、铰链等。
-
触发器:用于检测对象进入或离开特定区域,但不会产生物理碰撞效果。
在 Cocos Creator 中,物理引擎的使用主要通过 cc.RigidBody
和 cc.Physics Collider
组件来实现。接下来,我们将详细介绍这些组件的使用方法和物理引擎的基本原理。
开启物理引擎
在 Cocos Creator 中使用物理引擎之前,需要先在项目设置中开启物理引擎。具体步骤如下:
-
打开 Cocos Creator 编辑器。
-
选择 项目 -> 项目设置。
-
在项目设置面板中,找到 Physics 选项。
-
勾选 Enable Physics 选项,开启物理引擎。
开启物理引擎后,Cocos Creator 会自动在项目中引入物理引擎相关的模块,并在运行时启用物理模拟。
物理世界
物理世界是物理引擎的核心概念,它包含了所有的物理对象和物理规则。在 Cocos Creator 中,物理世界由 cc.director.getPhysicsManager()
获取,并可以通过设置物理世界的参数来控制物理模拟的效果。
物理世界参数设置
物理世界的主要参数包括重力、调试模式等。以下是一些常用的物理世界参数设置方法:
设置重力
重力是物理世界中最基本的力,通过设置重力可以模拟地球上的物理效果。默认情况下,重力为 (0, -98)
,即向下。
// 获取物理世界管理器
const physicsManager = cc.director.getPhysicsManager();
// 设置重力
physicsManager.gravity = cc.v2(0, -98); // 默认重力
开启调试模式
调试模式可以显示物理引擎中的碰撞体和关节等信息,有助于开发者调试物理效果。
// 开启调试模式
physicsManager.debugDrawFlags = cc.PhysicsManager.DrawBits.e_aabbBit |
cc.PhysicsManager.DrawBits.e_pairBit |
cc.PhysicsManager.DrawBits.e_centerOfMassBit |
cc.PhysicsManager.DrawBits.e_jointBit |
cc.PhysicsManager.DrawBits.e_shapeBit;
物理世界更新
物理世界会根据时间步长(Time Step)进行更新,以模拟物理效果。默认的时间步长是 1/60
秒。可以通过以下代码设置时间步长:
// 设置时间步长
physicsManager.fixedTimeStep = 1 / 60;
刚体(RigidBody)
刚体是物理引擎中的基本单位,它负责模拟对象的物理行为。在 Cocos Creator 中,可以通过添加 cc.RigidBody
组件来将一个节点变成刚体。
刚体类型
刚体有三种类型:
-
静态刚体(Static):不会受到物理引擎的影响,适合用于地面、墙壁等固定物体。
-
动态刚体(Dynamic):会受到物理引擎的影响,适合用于玩家控制的角色、可移动的物体等。
-
** kinematic刚体(Kinematic)**:可以手动控制其运动,但不会受到物理引擎的影响,适合用于 NPC 等。
添加刚体组件
在编辑器中,选择一个节点,然后在 组件 面板中点击 添加组件,选择 刚体 组件。或者在脚本中添加刚体组件:
// 添加刚体组件
const rigidbody = this.node.addComponent(cc.RigidBody);
rigidbody.type = cc.RigidBodyType.Dynamic; // 设置刚体类型为动态
刚体属性
刚体组件包含多种属性,可以控制刚体的行为。以下是一些常用的刚体属性:
-
质量(Mass):刚体的质量,影响其受力大小。
-
摩擦力(Friction):刚体的摩擦力,影响其与其它刚体的摩擦效果。
-
弹性(Bounciness):刚体的弹性,影响其碰撞后的反弹效果。
-
线性阻尼(Linear Damping):刚体的线性阻尼,影响其速度的减缓。
-
角阻尼(Angular Damping):刚体的角阻尼,影响其旋转速度的减缓。
设置刚体属性
在脚本中,可以设置刚体的属性:
// 设置刚体属性
rigidbody.mass = 1; // 质量
rigidbody.friction = 0.5; // 摩擦力
rigidbody.bounciness = 0.7; // 弹性
rigidbody.linearDamping = 0.1; // 线性阻尼
rigidbody.angularDamping = 0.1; // 角阻尼
刚体运动
动态刚体和 kinematic 刚体可以运动,以下是一些控制刚体运动的方法:
应用力(Apply Force)
可以对刚体应用力,使其移动或旋转。力是一个向量,包含力的大小和方向。
// 应用力
rigidbody.applyForce(cc.v2(100, 0), cc.v2(0, 0)); // 在刚体的 (0, 0) 位置应用 (100, 0) 的力
应用冲量(Apply Impulse)
可以对刚体应用冲量,使其瞬间移动或旋转。冲量也是一个向量,包含冲量的大小和方向。
// 应用冲量
rigidbody.applyImpulse(cc.v2(100, 0), cc.v2(0, 0)); // 在刚体的 (0, 0) 位置应用 (100, 0) 的冲量
设置速度(Set Velocity)
可以直接设置刚体的速度。
// 设置速度
rigidbody.linearVelocity = cc.v2(10, 0); // 设置刚体的线速度
rigidbody.angularVelocity = 1; // 设置刚体的角速度
碰撞体(Collider)
碰撞体是刚体上的组件,用于定义刚体的形状和碰撞属性。在 Cocos Creator 中,有多种类型的碰撞体组件,如 cc.PhysicsBoxCollider
、cc.PhysicsCircleCollider
、cc.PhysicsPolygonCollider
等。
添加碰撞体组件
在编辑器中,选择一个节点,然后在 组件 面板中点击 添加组件,选择 碰撞体 组件。或者在脚本中添加碰撞体组件:
// 添加矩形碰撞体组件
const boxCollider = this.node.addComponent(cc.PhysicsBoxCollider);
boxCollider.size = cc.size(100, 100); // 设置碰撞体的大小
碰撞体属性
碰撞体组件包含多种属性,可以控制碰撞体的行为。以下是一些常用的碰撞体属性:
-
材质(Material):碰撞体的材质,影响其摩擦力和弹性。
-
密度(Density):碰撞体的密度,影响刚体的质量。
-
摩擦力(Friction):碰撞体的摩擦力,影响其与其它碰撞体的摩擦效果。
-
弹性(Bounciness):碰撞体的弹性,影响其碰撞后的反弹效果。
-
传感器(Sensor):设置为传感器后,碰撞体不会产生物理效果,但可以触发碰撞事件。
设置碰撞体属性
在脚本中,可以设置碰撞体的属性:
// 设置碰撞体属性
boxCollider.material.friction = 0.5; // 设置摩擦力
boxCollider.material.bounciness = 0.7; // 设置弹性
boxCollider.density = 1; // 设置密度
boxCollider.sensor = true; // 设置为传感器
碰撞事件
物理引擎会检测碰撞事件,并在碰撞发生时触发相应的回调函数。在 Cocos Creator 中,可以通过监听 onBeginContact
和 onEndContact
事件来处理碰撞。
监听碰撞开始事件
在脚本中,可以监听 onBeginContact
事件:
cc.Class({
extends: cc.Component,
properties: {
boxCollider: {
type: cc.PhysicsBoxCollider,
default: null
}
},
onBeginContact: function (contact, selfCollider, otherCollider) {
// 碰撞开始时的处理
console.log("Collision started with", otherCollider.node.name);
},
onEndContact: function (contact, selfCollider, otherCollider) {
// 碰撞结束时的处理
console.log("Collision ended with", otherCollider.node.name);
}
});
碰撞过滤
碰撞过滤可以控制哪些碰撞体之间可以发生碰撞。在 Cocos Creator 中,可以通过设置碰撞组(Collision Group)和碰撞掩码(Collision Mask)来实现碰撞过滤。
设置碰撞组和碰撞掩码
在脚本中,可以设置碰撞体的碰撞组和碰撞掩码:
// 设置碰撞组和碰撞掩码
boxCollider.group = 1; // 设置碰撞组
boxCollider.mask = 2; // 设置碰撞掩码
碰撞体形状
碰撞体的形状决定了其与其它碰撞体的碰撞效果。Cocos Creator 中常见的碰撞体形状包括矩形、圆形、多边形等。
矩形碰撞体
矩形碰撞体是最常见的碰撞体形状,适用于矩形对象。
// 添加矩形碰撞体组件
const boxCollider = this.node.addComponent(cc.PhysicsBoxCollider);
boxCollider.size = cc.size(100, 100); // 设置碰撞体的大小
圆形碰撞体
圆形碰撞体适用于圆形对象。
// 添加圆形碰撞体组件
const circleCollider = this.node.addComponent(cc.PhysicsCircleCollider);
circleCollider.radius = 50; // 设置碰撞体的半径
多边形碰撞体
多边形碰撞体适用于不规则形状的对象。
// 添加多边形碰撞体组件
const polygonCollider = this.node.addComponent(cc.PhysicsPolygonCollider);
polygonCollider.points = [cc.v2(0, 0), cc.v2(100, 0), cc.v2(50, 100)]; // 设置多边形的顶点
关节(Joint)
关节用于连接两个刚体,模拟物理世界的连接效果。在 Cocos Creator 中,有多种类型的关节组件,如 cc.PhysicsJointFixed
、cc.PhysicsJointDistance
、cc.PhysicsJointSpring
等。
添加关节组件
在编辑器中,选择一个节点,然后在 组件 面板中点击 添加组件,选择 关节 组件。或者在脚本中添加关节组件:
// 添加固定关节组件
const fixedJoint = this.node.addComponent(cc.PhysicsJointFixed);
fixedJoint.connectedBody = otherRigidbody; // 设置连接的刚体
fixedJoint.anchor = cc.v2(0, 0); // 设置关节的锚点
关节属性
关节组件包含多种属性,可以控制关节的行为。以下是一些常用的关节属性:
-
连接刚体(Connected Body):关节连接的另一个刚体。
-
锚点(Anchor):关节的锚点位置。
-
刚度(Stiffness):关节的刚度,影响其连接效果。
-
阻尼(Damping):关节的阻尼,影响其连接效果。
设置关节属性
在脚本中,可以设置关节的属性:
// 设置固定关节属性
fixedJoint.connectedBody = otherRigidbody; // 设置连接的刚体
fixedJoint.anchor = cc.v2(0, 0); // 设置关节的锚点
fixedJoint.stiffness = 100; // 设置刚度
fixedJoint.damping = 10; // 设置阻尼
常见的关节类型
以下是一些常见的关节类型及其使用方法:
固定关节(Fixed Joint)
固定关节将两个刚体固定在一起,不发生相对运动。
// 添加固定关节组件
const fixedJoint = this.node.addComponent(cc.PhysicsJointFixed);
fixedJoint.connectedBody = otherRigidbody; // 设置连接的刚体
fixedJoint.anchor = cc.v2(0, 0); // 设置关节的锚点
距离关节(Distance Joint)
距离关节保持两个刚体之间的距离不变。
// 添加距离关节组件
const distanceJoint = this.node.addComponent(cc.PhysicsJointDistance);
distanceJoint.connectedBody = otherRigidbody; // 设置连接的刚体
distanceJoint.anchorA = cc.v2(0, 0); // 设置第一个刚体的锚点
distanceJoint.anchorB = cc.v2(0, 0); // 设置第二个刚体的锚点
distanceJoint.distance = 100; // 设置距离
弹簧关节(Spring Joint)
弹簧关节模拟两个刚体之间的弹簧效果。
// 添加弹簧关节组件
const springJoint = this.node.addComponent(cc.PhysicsJointSpring);
springJoint.connectedBody = otherRigidbody; // 设置连接的刚体
springJoint.anchorA = cc.v2(0, 0); // 设置第一个刚体的锚点
springJoint.anchorB = cc.v2(0, 0); // 设置第二个刚体的锚点
springJoint.stiffness = 100; // 设置刚度
springJoint.damping = 10; // 设置阻尼
springJoint.restLength = 50; // 设置弹簧的自然长度
触发器(Trigger)
触发器是一种特殊的碰撞体,用于检测对象进入或离开特定区域,但不会产生物理碰撞效果。在 Cocos Creator 中,可以通过设置碰撞体的 sensor
属性来将其变成触发器。
添加触发器
在编辑器中,选择一个节点,然后在 组件 面板中点击 添加组件,选择 碰撞体 组件,并将 sensor
属性设置为 true
。或者在脚本中添加触发器:
// 添加矩形触发器组件
const boxCollider = this.node.addComponent(cc.PhysicsBoxCollider);
boxCollider.size = cc.size(100, 100); // 设置碰撞体的大小
boxCollider.sensor = true; // 设置为触发器
触发器事件
触发器事件包括 onEnter
、onStay
和 onExit
事件,分别在对象进入、停留在和离开触发器区域时触发。
监听触发器事件
在脚本中,可以监听触发器事件:
cc.Class({
extends: cc.Component,
properties: {
boxCollider: {
type: cc.PhysicsBoxCollider,
default: null
}
},
onEnter: function (otherCollider) {
// 对象进入触发器区域时的处理
console.log("Object entered trigger area:", otherCollider.node.name);
},
onStay: function (otherCollider) {
// 对象停留在触发器区域时的处理
console.log("Object staying in trigger area:", otherCollider.node.name);
},
onExit: function (otherCollider) {
// 对象离开触发器区域时的处理
console.log("Object left trigger area:", otherCollider.node.name);
}
});
物理引擎示例
简单的物理场景
假设我们有一个简单的物理场景,包含一个动态刚体球和一个静态刚体地面。球会在重力的作用下掉落到地面上并反弹。
场景设置
-
创建一个球节点,添加
cc.RigidBody
组件和cc.PhysicsCircleCollider
组件。 -
创建一个地面节点,添加
cc.RigidBody
组件和cc.PhysicsBoxCollider
组件。
脚本代码
// Ball.js
cc.Class({
extends: cc.Component,
properties: {
rigidbody: {
type: cc.RigidBody,
default: null
},
circleCollider: {
type: cc.PhysicsCircleCollider,
default: null
}
},
onl oad: function () {
// 设置刚体类型为动态
this.rigidbody.type = cc.RigidBodyType.Dynamic;
// 设置碰撞体属性
this.circleCollider.material.friction = 0.5;
this.circleCollider.material.bounciness = 0.7;
this.circleCollider.density = 1;
// 监听碰撞事件
this.node.on(cc.Node.EventType.TOUCH_START, this onTouchStart, this);
},
onTouchStart: function (event) {
// 应用冲量,使球向上弹起
this.rigidbody.applyImpulse(cc.v2(0, 1000), cc.v2(0, 0));
}
});
// Ground.js
cc.Class({
extends: cc.Component,
properties: {
rigidbody: {
type: cc.RigidBody,
default: null
},
boxCollider: {
type: cc.PhysicsBoxCollider,
default: null
}
},
onl oad: function () {
// 设置刚体类型为静态
this.rigidbody.type = cc.RigidBodyType.Static;
// 设置碰撞体属性
this.boxCollider.material.friction = 0.5;
this.boxCollider.material.bounciness = 0.3;
this.boxCollider.density = 0;
}
});
物理关节示例
假设我们有一个物理关节示例,包含两个动态刚体,通过固定关节连接在一起。
场景设置
-
创建两个球节点,分别添加
cc.RigidBody
组件和cc.PhysicsCircleCollider
组件。 -
选择其中一个球节点,添加
cc.PhysicsJointFixed
组件,并设置连接的刚体和锚点。
脚本代码
// Ball1.js
cc.Class({
extends: cc.Component,
properties: {
rigidbody: {
type: cc.RigidBody,
default: null
},
circleCollider: {
type: cc.PhysicsCircleCollider,
default: null
}
},
onl oad: function () {
// 设置刚体类型为动态
this.rigidbody.type = cc.RigidBodyType.Dynamic;
// 设置碰撞体属性
this.circleCollider.material.friction = 0.5;
this.circleCollider.material.bounciness = 0.7;
this.circleCollider.density = 1;
}
});
// Ball2.js
cc.Class({
extends: cc.Component,
properties: {
rigidbody: {
type: cc.RigidBody,
default: null
},
circleCollider: {
type: cc.PhysicsCircleCollider,
default: null
}
},
onl oad: function () {
// 设置刚体类型为动态
this.rigidbody.type = cc.RigidBodyType.Dynamic;
// 设置碰撞体属性
this.circleCollider.material.friction = 0.5;
this.circleCollider.material.bounciness = 0.7;
this.circleCollider.density = 1;
}
});
// JointController.js
cc.Class({
extends: cc.Component,
properties: {
ball1: {
type: cc.Node,
default: null
},
ball2: {
type: cc.Node,
default: null
}
},
onl oad: function () {
// 获取两个球的刚体组件
const rigidbody1 = this.ball1.getComponent(cc.RigidBody);
const rigidbody2 = this.ball2.getComponent(cc.RigidBody);
// 添加固定关节组件
const fixedJoint = this.ball1.addComponent(cc.PhysicsJointFixed);
fixedJoint.connectedBody = rigidbody2; // 设置连接的刚体
fixedJoint.anchor = cc.v2(0, 0); // 设置关节的锚点
fixedJoint.stiffness = 100; // 设置刚度
fixedJoint.damping = 10; // 设置阻尼
}
});
物理关节的其他类型
除了固定关节,Cocos Creator 还提供了其他类型的关节,如距离关节、弹簧关节等。以下是一些常见的关节类型及其使用方法:
距离关节(Distance Joint)
距离关节保持两个刚体之间的距离不变,适合用于模拟绳子或链条等效果。
// DistanceJointController.js
cc.Class({
extends: cc.Component,
properties: {
ball1: {
type: cc.Node,
default: null
},
ball2: {
type: cc.Node,
default: null
}
},
onl oad: function () {
// 获取两个球的刚体组件
const rigidbody1 = this.ball1.getComponent(cc.RigidBody);
const rigidbody2 = this.ball2.getComponent(cc.RigidBody);
// 添加距离关节组件
const distanceJoint = this.ball1.addComponent(cc.PhysicsJointDistance);
distanceJoint.connectedBody = rigidbody2; // 设置连接的刚体
distanceJoint.anchorA = cc.v2(0, 0); // 设置第一个刚体的锚点
distanceJoint.anchorB = cc.v2(0, 0); // 设置第二个刚体的锚点
distanceJoint.distance = 100; // 设置距离
}
});
弹簧关节(Spring Joint)
弹簧关节模拟两个刚体之间的弹簧效果,适合用于模拟弹性连接。
// SpringJointController.js
cc.Class({
extends: cc.Component,
properties: {
ball1: {
type: cc.Node,
default: null
},
ball2: {
type: cc.Node,
default: null
}
},
onl oad: function () {
// 获取两个球的刚体组件
const rigidbody1 = this.ball1.getComponent(cc.RigidBody);
const rigidbody2 = this.ball2.getComponent(cc.RigidBody);
// 添加弹簧关节组件
const springJoint = this.ball1.addComponent(cc.PhysicsJointSpring);
springJoint.connectedBody = rigidbody2; // 设置连接的刚体
springJoint.anchorA = cc.v2(0, 0); // 设置第一个刚体的锚点
springJoint.anchorB = cc.v2(0, 0); // 设置第二个刚体的锚点
springJoint.stiffness = 100; // 设置刚度
springJoint.damping = 10; // 设置阻尼
springJoint.restLength = 50; // 设置弹簧的自然长度
}
});
物理引擎的调试和优化
物理引擎的调试和优化是确保物理效果正确和性能良好的关键步骤。以下是一些调试和优化的建议:
调试模式
开启调试模式后,可以在场景中看到物理引擎的碰撞体和关节等信息,有助于调试物理效果。
// 开启调试模式
const physicsManager = cc.director.getPhysicsManager();
physicsManager.debugDrawFlags = cc.PhysicsManager.DrawBits.e_aabbBit |
cc.PhysicsManager.DrawBits.e_pairBit |
cc.PhysicsManager.DrawBits.e_centerOfMassBit |
cc.PhysicsManager.DrawBits.e_jointBit |
cc.PhysicsManager.DrawBits.e_shapeBit;
性能优化
物理引擎的性能优化可以通过以下几种方式实现:
-
减少物理对象的数量:过多的物理对象会增加物理模拟的计算量,影响性能。尽量减少不必要的物理对象。
-
使用简单的碰撞体形状:复杂的碰撞体形状(如多边形)会增加计算量,使用简单的形状(如矩形、圆形)可以提高性能。
-
调整时间步长:适当调整物理世界的时间步长,可以在保证物理效果的同时优化性能。
-
使用物理层:通过设置物理层和层之间的碰撞规则,可以减少不必要的碰撞检测,提高性能。
// 设置时间步长
const physicsManager = cc.director.getPhysicsManager();
physicsManager.fixedTimeStep = 1 / 60;
总结
Cocos Creator 的物理引擎基于 Box2D,提供了丰富的功能,如碰撞检测、刚体运动、关节等,使得开发者可以轻松地在游戏场景中实现物理效果。通过合理设置物理世界参数、刚体属性、碰撞体属性和关节属性,可以创建出真实感强、互动性高的物理场景。同时,开启调试模式和进行性能优化也是确保物理效果正确和性能良好的重要步骤。
希望本文档能帮助你更好地理解和使用 Cocos Creator 的物理引擎。如果你有任何疑问或需要进一步的帮助,请参考 Cocos Creator 官方文档或社区支持。