1 游离和静态刚体
一般当我们创建一个刚体并将它添加到空间上后,空间就开始对之进行模拟,包括了对刚体位置、速度、受力以及重力影响等的模拟。没被添加到空间(没有被模拟)的刚体我们把它称之为游离刚体。游离刚体最重要的用途就是用来当作静态刚体,但是你仍然可以使用它们来实现直接控制物体,如移动平台。
静态刚体是游离刚体,但被设置了一个特殊的标志以便让Chipmunk知道它们从不移动除非你要求这么做。静态刚体有两个目的。最初,它们被加入用 来实现休眠功能。因为静态刚体不移动,Chipmunk知道让那些与静态刚体接触或者连接的物体安全的进入休眠。接触或连接常规游离刚体的物体从不允许休 眠。静态刚体的第二个目的就是让Chipmunk知道,关联到静态刚体的碰撞形状是不需要更新碰撞检测数据的。Chipmunk也不需要操心静态物体之间 的碰撞检测。通常所有的关卡几何图形都会被关联到一个静态刚体上除了那些能够移动的东西,例如平台或门等。
每一个空间都有一个专用的静态刚体(staticBody),你可以使用它来添加静态形状。Chipmunk也会自动将形状作为静态形状添加到静态刚体上。
2.属性
Chipmunk为刚体的多个属性提供了getter/setter函数。如果刚体在休眠状态,设置大多数属性会自动唤醒它们。如果你想,你也可以直接在cp.Body
结构体内设置字段。它们都在头文件中有记录。
- body.getMass()
- body.setMass(Float m)
刚体的质量。
- body.getMoment()
- body.setMoment(Float i)
刚体的转动惯量(MoI(译者注:Moment Of Inertia即转动惯量的缩写)或有时只说惯量)。惯量就像刚体的旋转质量。请查阅下面的函数来帮助计算惯量。
- body.getPos()
- body.setPos(cp.Vect pos)
刚体重心的位置。当改变位置的时候如果你要计划对空间进行任何查询,你可能还需要调用cpSpaceReindexShapesForBody()
来更新关联形状的碰撞检测信息。
- body.getVel()
- body.setVel(cp.Vect value)
刚体重心的线速度。
body.f
施加到刚体重心的力。在湖闻樟注:没有在源码是找到对应的getter/setter函数
- body.getAngle()
- body.setAngle(Float a)
刚体的角度,弧度制。当改变角度的时候如果你要计划对空间进行任何查询,你可能还需要调用space.reindexShapesForBody()
来更新关联形状的碰撞检测信息。
- body.etAngVel()
- body.setAngVel(Float value)
刚体的角速度,弧度/秒,
- body.getTorque()
- body.setTorque(Float value)
施加到刚体的扭矩。
body.getRot()
刚体的旋转向量。可通过cpvrotate()
或者cpvunrotate()
进行快速旋转。
- body.getVelLimit()
- body.setVelLimit(Float value)
刚体的速度极限。、默认为INFINITY
(无限大),除非你专门设置它。可以被用来限制下落速度等。
- body.getAngVelLimit()
- body.setAngVelLimit(Float value)
刚体以弧度/秒的角速度限制。默认为INFINITY
,除非你专门设置它。
body.getSpace()
获取body
所添加进去的cpSpace
。
在湖闻樟注:在c的版本中有 cpBodySetUserData()、cpBodySetUserData()这两个用户数据指针的函数,但cocos2d-js中没有。估计是考虑到js的对象的特性,如果需要的话可以声明一个userData成员。
3.转动惯量和面积帮助函数
使用以下函数来近似计算出刚体的转动惯量,如果想得到多个,那就将结果相加在一起。
cpFloat cp.momentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cp.Vect offset) – 计算空心圆的转动惯性,r1和r2是在任何特定顺序下的内径和外径。 (实心圆圈的内径为0)
cpFloat cp.momentForSegment(cpFloat m, cpVect a, cp.Vect b) – 计算线段的转动惯量。端点
a
和b
相对于刚体。cpFloat cp.momentForPoly(cpFloat m, int numVerts, cp.Vect verts, cp.Vect offset) – 计算固定多边形的转动惯量,假设它的中心在质心上。
offset
偏移值被加到每个顶点。cpFloat cp.momentForBox(cpFloat m, cpFloat width, cpFloat height) – 计算居中于刚体的实心矩形的转动惯量。
转动惯量例子
- // 质量为2,半径为5的实心圆的转动惯量
- var circle1 = cp.momentForCircle(2, 0, 5, cp.vzero);
-
- // 质量为1,内径为1,外径为6的空心圆的转动惯量
- var circle2 = cp.momentForCircle(1, 2, 6, cp.vzero);
-
- // 质量为1,半径为3,x轴方向偏离重心量为3的实心圆的转动惯量
- var circle3 = cp.momentForCircle(2, 0, 5, cp.v(3, 0));
-
- // 复合对象。居中于重心的1x4的矩形和y轴偏移重心量为3,半径为1的实心圆
- // 只需将转动惯量相加到一起
- var composite = cp.momentForBox(boxMass, 1, 4) + cpMomentForCircle(circleMass, 0, 1, cp.v(0, 3));
如果你想近似计算诸如质量或密度此类的东西,可以使用下列函数来获取Chipmunk形状区域。
cpFloat cp.areaForCircle(cpFloat r1, cpFloat r2) – 空心圆形状面积
cpFloat cp.areaForSegment(cpVect a, cp.Vect b, cpFloat r) – 斜线段面积。(如果半径为0的话永远为0)
cpFloat cp.areaForPoly(int numVerts, cp.Vect verts) – 多边形形状的面积。多边形为凹多边形时返回一个负值。
4.坐标系转换函数
许多事情被定义在刚体的局部坐标,也就意味着(0,0)是刚体的重心和轴线旋转中心。
cp.Vect body.local2World(cp.Vect v) – 从刚体局部坐标系转换到世界坐标系
cp.Vect body.world2Local(const cpVect v) – 从世界坐标系转换到刚体的局部坐标系
5.施加力和力矩
人们有时候容易混淆力和冲量之间的区别。冲量基本上是一个在非常短的时间内施加的一个非常大的力,就像一个球击中一堵墙或者大炮射击一样。Chipmunk的冲量会在一瞬间直接施加在物体的速度上。无论是力还是冲量都受到物体质量的影响。物体质量翻倍,则效果减半。
body.resetForces() – 对刚体施加0值的力和扭矩
body.applyForce(cp.Vect f, cp.Vect r) – 在离重心相对偏移量为r的位置施加
f
的力于body
上body.applyImpulse(const cp.Vect j, cp.Vect r) – 在离重心相对偏移量为r的位置施加
j
的冲量于body
上。
注: applyForce()
和applyImpulse()
两者都是在绝对坐标系中施加力或者冲量,并在绝对坐标系中产生相对的偏移。(偏移量相对于重心位置,但不随刚体旋转)
参考:https://github.com/ChipmunkCommunityCN/ChipmunkDocsCN/blob/master/Chipmunk2D.md