cocos2d-x物理引擎介绍

原理介绍

物理引擎是模仿真实世界的物理运行规律,使得精灵做出自由落体、抛物线运动、反弹、碰撞等效果。这些算法引擎都已经实现,不需要我们去写代码,只需要掌握调用方法即可,因此节省了大量的开发时间。

术语

物理世界

物理世界(PhysicsWorld)对象是进行物理模拟时的一个核心部件。物理世界(PhysicsWorld)与场景(Scene)紧密整合在一起。你可以把你想象成上帝,世界(World,Scene)是由你创造的,你需要定义这个世界的规则,比如重力的方向、大小等。

物理刚体

物理刚体(PhyicsBody)是在你定义出来的物理世界中存活的元素。物理刚体通常具有质量、位置自旋度、速度和衰减度等属性,来描述被物理世界影响的程度。

形状

形状是和刚体绑定在一起的,绑定后就定义了刚体的形状,不同形状的刚体在物理世界产生的效果不同,比如滚动和碰撞时对其他刚体的影响。

材质

材质包括材料的以下几种属性:

  • 密度:它被用于计算母体的质量属性。
  • 摩擦:它被用于进行物体间的相对运动。
  • 恢复系数:它被用于使物体反弹。恢复系数一般设为0到1之间。0说明不反弹,1说明完全反弹。
连接/关节

连接(contacts)和关节(joint)对象描述了刚体相互关联的方式。关节可以形象理解为两个弹力球之间连接了一根绳子,这两个弹力球无论怎么运动,距离都不会超过这根绳子,可以认为连接/关节是对两个刚体之间的约束。

碰撞

没错就是你脑子中想象的碰撞,物理引擎根据你定义出来的物理世界和刚体模拟碰撞的发生,这就是物理引擎的精华。

具体实现

创建物理世界

在CBaseScene::initWithPhysics()中对物理世界进行初始化。

  • getPhysicsWorld 获取物理世界对象
  • setGravity(Vec2 ):设置重力加速度(可以是任意方向)
  • setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL):调试接口,设置后可以看到创建的刚体是红色的。
创建刚体
  • PhysicsBody*ballBody= PhysicsBody::create… 创建一个刚体对象,通过create方法的不同可以选择不同的形状。
  • ballBody->setGravityEnable(true); //设置是否受重力影响
  • ballBody->getShape(0)->setFriction(0.0f); //设置摩擦系数
  • ballBody->getShape(0)->setRestitution(0.8f); //设置弹性系数
  • ballBody->getShape(0)->setMass(10); //质量
  • ballBody->setCategoryBitmask(0x1); //分类掩码
  • ballBody->setCollisionBitmask(0x1); //碰撞掩码
  • ballBody->setContactTestBitmask(0x2); //接触测试掩码

然后将刚体绑定(setPhysicsBody(ballBody);)在精灵上,精灵便拥有刚体的属性。

碰撞检测

两个物体是否能碰撞,碰撞后程序是否能检测到,需要使用上面3个掩码,规则是:分类掩码和碰撞掩码按位与操作,是非零值, 则能发生碰撞反应,分类掩码和接触测试掩码按位与操作,是非零值, 则能触发回调函数(onContactBegin)。这2个规则互相是独立的,互相没影响。

auto contactListener = EventListenerPhysicsContact::create(); 
//设置监听器的碰撞开始函数 
contactListener->onContactBegin = CC_CALLBACK_1(TTQPlauyUI::onContactBegin, this); 
//添加到事件分发器中 
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

通过设置刚体的Tag和Name可在onContactBegin中对发生碰撞的刚体进行区分。
除了onContactBegin,cocos2d-x自带的物理引擎是封装的chipmunk,共有四个回调函数。

  • begin() 该步中两个形状刚开始第一次接触。回调返回true则会处理正常碰撞,返回false,Chipmunk会完全忽略碰撞。如果返回false,则preSolve()和postSolve()回调将永远不会被执行,但你仍然会在形状停止重叠的时候接收到一个单独的事件。
  • preSolve() 该步中两个形状相互接触。回调返回false,Chipmunk在这一步会忽略碰撞,返回true来正常处理它。此外,你可以使用cpArbiterSetFriction(),cpArbiterSetElasticity()或cpArbiterSetSurfaceVelocity()来提供自定义的摩擦,弹性,或表面速度值来覆盖碰撞值。
  • postSolve() 两种形状相互接触并且它们的碰撞响应已被处理。如果你想使用它来计算音量或者伤害值,这时你可以检索碰撞冲力或动能。
  • separate() 该步中两个形状刚第一次停止接触。确保begin()/separate()总是被成对调用,当删除接触中的形状时或者析构space时它也会被调用。
    cocos2d-x中对应以下四个:
std::function<bool(PhysicsContact& contact)> onContactBegin;

std::function<bool(PhysicsContact& contact, PhysicsContactPreSolve& solve)> onContactPreSolve;

std::function<void(PhysicsContact& contact, const PhysicsContactPostSolve& solve)> onContactPostSolve;

std::function<void(PhysicsContact& contact)> onContactSeperate;

注意事项

  • 当一个精灵绑定一个刚体之后,如果给这个精灵一个动作,比如moveTo,这个时候刚体也会随着精灵一起移动位置,当移动到和另一个绑定刚体的精灵发生碰撞时,会发生意想不到情况,所以要尽量避免这种情况。
  • 另外刚体可以设置不可旋转,也就是说当设置精灵旋转之后,可能会导致精灵和刚体不重合、错位的情况。(默认情况下,是可随着精灵旋转)
  • 刚体碰撞检测会有穿透问题,就是运动速度太快,没来得及检测,造成响应函数没执行。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值