最近开始开发一款2D物理游戏,游戏还没上线具体是什么样类型的就不透露了。从去年开始,我全面转用Unity3d开发,开发效率很高。Unity3d开发有完整的集成环境,可视化编辑和工作流,基本是一个很理想的开发工具了。可是,这块2D游戏要求使用cocos2d-x并且用C++开发!和Unity3d相比,cocos2d-x真的很弱,编辑可视化和工作流太鸡肋了,大大影响了开发效率。既然有这样的要求,也只能无奈的开始。
刚开始,我就遇到难点了。Unity3d里面很简单的相机镜头跟踪游戏角色的功能,在cocos2d-x里面就很伤脑筋。逻辑上,跟踪无非就是让游戏每帧都让相机的位置和角色一致。cocos2d-x Sprite在不使用physics的情况下,这个功能倒是可以OK的。但是在使用physics后,就会发现,虽然跟踪了,可总是发现角色会跳动,特别是角色速度特别快的情况下,抖动特别严重。Debug发现后,代码跟踪逻辑是正确的!那问题出在什么地方?
尝试后,只要加入物理效果,就会出现跳动。那问题基本可以锁定在physics部分。好吧,Debug设置断点啃源码吧。看了cocos2d-x的源码,发现引擎逻辑实现是先更新Node注册的scheduler,接着更新physics,在绘制屏幕。而我之前的实现是在scheduler里面让相机和角色的位置一致,而后面还有physics的更新位移,跳动的原因应该就在此了。于是我把跟踪的逻辑转到physics部分。啃了一下physics部分的源码,发现physics的刷新放在update(float dt)上,update已经是virtual的,于是继承PhysicsBody创建子类,改写update函数,在此抓取角色位置然后让相机位置和其相同。可是!!居然还是抖动的!!!
Debug后发现我的逻辑部分没问题,觉得太诡异了。于是我在把重点放在了physics更新Node位置的源码处,设置断点看函数调用堆栈。发现了一个Sprite的物理更新位移居然等到绘制这个Sprite的时候才去同步!!
问题又来了,我同步相机和角色的位置的时候,其实角色的物理发生位移并没有更新到角色的实际位置坐标,而是等到等到绘制的时候采取同步。所以我的抓取角色位置其实还是没有同步。还有一个附加可能性就是,相机的绘制和角色的绘制向后顺序会影响逻辑时候正确!!!!!
我尝试重写相机的绘制部分,把跟踪逻辑放在绘制部分。结果!!!fps下降太快,绘制性能完全不行!!!!
还有一个方法就是在physics更新Sprite位置的地方插入更新跟踪逻辑!!尝试了一下,还是跳动了,而且性能也是损失了!!!!头大了!!Debug+看源码半个小时候,多次尝试后还是不能解决。
怎么办?函数堆栈我发现了一个updateTransformFromPhysics函数,其就是让Sprite和physics同步,而这个同步就是获取Sprite的physicsBody获取位置点然后设置Sprite的位置点一致。突然有灵感了,就是把跟踪逻辑转移到physicsBody的更新部分。进入physicsBody的getPosition函数,发现是根据其_cpBody和_positionOffset来计算位置。通过全局搜索发现_cpBody的更新发生于physicsBody的update函数。看了一下physics部分的源码,发现是模块化的,不会影响cocos2d-x的绘制部分,而且physicsBody的update是virtual的。OK,啃源码到现在基本可以找到思路了。重写physicsBody的update的方法,并且在update后获取physicsBody的位置,这个时候把跟踪逻辑实现在此处后,同步相机和physicsBody的位置。就行了。
实现physicsBody子类,重写update后。功能OK了,没有出现跳动现象 。
虽然实际解决改写代码量很少,但是Debug和看源码理解cocos2d-x底层实现很花时间。
以上。
待续...
网友评论