欢迎光临Software MyZone,有问题可留言或到站点论坛发帖,争取第一时间帮忙解决 || 站点论坛:火龙论坛 || 淘宝小店:应小心的易淘屋 【欢迎大家提建设性意见】

Box2d 设置物体旋转固定角度(不使用关节)

本文为firedragonpzy原创,转载务必在明显处注明:
转载自【Softeware MyZone】原文链接: 
http://www.firedragonpzy.com.cn/index.php/archives/2604

欢迎热爱编程的朋友们参与到cocos2d-x编程中,为了给大家提供良好的交流环境,网站以开启QQ群
Software MyZone:66202765(群号,欢迎加入,若满,请加1群)
Software MyZone 1群(2dx):286504621
【加群请写:Software MyZone或者是firedragonpzy】
群论坛:火龙论坛正试运营阶段,欢迎大家多提些建设性意见……

之前写了Box2d物体移动的例子,没有分享一下,最近规整了一下代码,与大家分享。。。
最近一直在搞Box2d,不过box2d的资料还真是不多啊。研究物体旋转的时候可是遇到大问题了。现在精灵A,物体B和精灵b,精灵b是物体B的userData,后文中称之为B的皮肤。非物理世界我们均称之为场景,故事就这么展开了……

在场景中有不同的精灵,现在需要将场景中的精灵旋转后移动到物理世界中,物体B的皮肤要和精灵完全吻合。。。如何操作……

在处理b和物体重合的问题郁闷了好久,鉴于是Box2d的新手,可能实现的不好,大家多多见谅。主要是分享出来,大家不会的看看,会的多多指教,共同进步。

首先,首当其冲的问题就是,如果精灵A是多边形,移动到物理世界后与物理世界中的位置不匹配【我们为了使物体B和皮肤同时运动,位置完全吻合,肯定在update方法里面设置同一个position】,精灵A是正方形、长方形、圆形是没有问题的,多边形可就不如你意了。详细分析如下:正方形、圆形、长方形设置位置的时候是以中心点设置,而多边形是以左下角为基点设置。

好,发现问题了好说,解决啊!我在物体世界中通过程序将物体的位置进行了移动:代码如下:


if( this->getTag() == kTagRoundItem || this->getTag() == kTagSquareItem || this->getTag() == kTagRectangleItem )
 {
 myParent->triggerPhysics( this->getPosition() );
 }else
 {
 CCPoint location = ccp( this->getPosition().x - this->getContentSize().width/2, this->getPosition().y - this->getContentSize().height/2 );
 myParent->triggerPhysics( location );
 }

问题解决了,不错。。。

但是一旋转,问题又来了,物体B和皮肤又不能重合了。。。原因是发生角度偏移后,就不能减去 this->getContentSize().width/2,这个需要通过复杂的计算。。。郁闷,,,郁闷、、、当然那些复杂的计算就不说了,主要说下解决方案。

无限次的运行,加上无数的思考后,我觉得通过角度计算太复杂了,是不是可以投机取巧啊。经过观察、分析平移与旋转,我发现物体B和皮肤发生偏移的距离就是锚点为(0,0)和(0.5,0.5)的时候,我通过ccpAdd(位置,ccpSub(位置1,位置2)),这么处理,进行一下精灵b位置的移动不就可以了嘛。于是设置this->setAnchorPoint( ccp( 0,0 ) );取其世界坐标:convertToWorldSpace(this->getAnchorPointInPoints());,郁闷的是结果和(0.5,0.5)的时候一致。。。

在绝望的时候,我抱着侥幸试了试convertToWorldSpaceAR(this->getAnchorPointInPoints());竟然行了,兴奋啊,直接贴出实现代码,共享下:


if( this->getTag() == kTagRoundItem || this->getTag() == kTagSquareItem || this->getTag() == kTagRectangleItem )
 {
 myParent->triggerPhysics( this->getPosition() , this->getRotation());
 }else
 {

CCLog( "angle point x %f",this->getAnchorPointInPoints().x );
 CCLog( "angle point x %f",this->getAnchorPointInPoints().y );
 CCLog( "0 0--%f", this->getPosition().x);
 CCLog( "0 0--%f", this->getPosition().y);
 this->setAnchorPoint( ccp( 0,0 ) );
 //CCPoint location = convertToWorldSpace(this->getAnchorPointInPoints());
 CCPoint locationOld = convertToWorldSpaceAR(this->getAnchorPointInPoints());
 CCLog( "angle point x %f",this->getAnchorPointInPoints().x );
 CCLog( "angle point x %f",this->getAnchorPointInPoints().y );
 CCLog( "0 0--%f", locationOld.x);
 CCLog( "0 0--%f", locationOld.y);
 this->setAnchorPoint( ccp( 0.5,0.5 ) );
 //location = convertToWorldSpace(this->getAnchorPointInPoints());
 locationOld = convertToWorldSpaceAR(this->getAnchorPointInPoints());
 CCLog( "angle point x %f",this->getAnchorPointInPoints().x );
 CCLog( "angle point x %f",this->getAnchorPointInPoints().y );
 CCLog( "0 0--%f", locationOld.x);
 CCLog( "0 0--%f", locationOld.y);

CCPoint location = ccpAdd( this->getPosition(), ccpSub( this->getPosition(), locationOld ) );
 myParent->triggerPhysics( location , this->getRotation());
 }

不过貌似else里面只有一下代码也是ok的:


CCPoint locationOld = convertToWorldSpaceAR(this->getAnchorPointInPoints());
 CCLog( "angle point x %f",this->getAnchorPointInPoints().x );
 CCLog( "angle point x %f",this->getAnchorPointInPoints().y );
 CCLog( "0 0--%f", locationOld.x);
 CCLog( "0 0--%f", locationOld.y);

CCPoint location = ccpAdd( this->getPosition(), ccpSub( this->getPosition(), locationOld ) );
 myParent->triggerPhysics( location , this->getRotation());

其实这里的问题主要在于使用了多边形之后,body的基准点在左下角,这里推荐使用PhsicsEditor,使用这个工具,你可以设置锚点在中心,这样就不必费这么大的劲了……

有关PhysicsEditor的可以参考此文:PhysicsEditor的使用

期间对于一个新手来说遇到的一些小问题如下:

A:物体旋转:

m_groudBody->SetTransform( m_groudBody->GetPosition(), CC_DEGREES_TO_RADIANS(0) );//注意了,box2d中都是弧度,记得转化

B:时间间隔的处理,我用了动作,当然也可以使用时刻表,我试了试,效果不好


CCFiniteTimeAction *action = CCSequence::actions( CCCallFunc::actionWithTarget( this,callfunc_selector(HelloWorld::delayActionCallBackLeft) ),CCDelayTime::create( intervalSpace ),CCCallFunc::actionWithTarget( this,callfunc_selector(HelloWorld::delayActionCallBackMiddle) ),CCDelayTime::create( intervalSpace ),CCCallFunc::actionWithTarget( this,callfunc_selector(HelloWorld::delayActionCallBackRight) ),CCDelayTime::create( intervalSpace ),CCCallFunc::actionWithTarget( this,callfunc_selector(HelloWorld::delayActionCallBackMiddle) ),CCDelayTime::create( intervalSpace ),NULL );
 m_groudSprite->runAction( CCRepeat::actionWithAction( action, shockCounts ) );

C:物体挤压重叠,貌似是隧道效应。解决方案:


bodyDef.bullet = true;//开启子弹,随时监测碰撞,不过很好cpu,具体还没研究,待下回分解,了解的大神指点下

时间紧迫【项目急】,先大体写这些,实现功能,透彻的分析等待下回,如果哪位大神晓得,帮忙解释下,感谢万分……

  1. Pingback: Box2d设置物体旋转固定角度(不使用关节) - 移动端开发 - 无忧网

  2. 刚刚有反馈了,一哥们是这么说的:在吗?刚看了你写的blog,我发现把一个在body里有个方法可以实现旋转SetAngularVelocity(float32 omega);或者在定义里写上bodyDef.angularVelocity = 0.2f;//旋转速度bodyDef.angularDamping = 0.0;

    • 我的右手边是你的左手 17:30:52嗯冲量和角速度但是使用冲量的话不好控制角度 我们要求角度必须一致我的右手边是你的左手 17:32:13角速度的话不好控制最终的位置 只能是<或者是>