cocos2d-x 3.8.1的骨骼动画加载方法addArmatureFileInfo仍然存在问题

简介:

  提出如题所示的问题,心里非常别扭,但的确是事实。因此,Cocos Studio(我目前使用的是 2.3.2)在许多方面还有改进的地方,包括与之相对应的cocos2d-x中的代码操作部分。

   

问题

        目前,我的试验结果发现,使用cocos2d-x 3.8.1中提供的如下方法:

1
ArmatureDataManager::getInstance()->addArmatureFileInfo(filename);

        无法正常加载Cocos Studio 2.3.2导出的骨骼动画资源文件。例如如下代码无法正常通过项目构建

1
ArmatureDataManager::getInstance()->addArmatureFileInfo( "DemoPlayer.csb" );

令人遗憾的例子

 

尽管如此,但是cocos2d-x 3.8.1的cpp-tests实例中的确提供了使用addArmatureFileInfo方法加载.csb骨骼动画文件的例子!!

 

是的,因为.csb文件是二进制格式,目前还找不到其反编译工具,但是,从使用简单的工具分析,cpp-tests实例中提供的示例.csb骨骼动画文件的版本与Cocos Studio 2.3.2导出的骨骼动画资源文件.csb并不一致。

 

下面给出Notepad++观察到的结果图的对照(第1张是Cocos Studio 2.3.2导出骨骼动画文件DemoPlayer.csb查看结果,显然版本号是2.1.0.0,第2张是cpp-tests实例中提供的示例Cowboy.csb骨骼动画文件查看结果,显然版本号是1.0.1):

 

wKioL1ZLIqGBpW75AALR_GQJDyo639.jpg

 

wKiom1ZLIxmC3MHpAAQDiObULoI450.jpg

 

为了进一步分析上述问题,我还专门把cocos2d-x 3.8.1的cpp-tests实例中提供的使用addArmatureFileInfo方法加载其提供的相应.csb骨骼动画文件的代码复制到一个简单示例工程中进行测试,的确OK。相关代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
const   char * HelloWorld::m_binaryFilesNames[4] = {  "bear.csb" "horse.csb" , "Cowboy.csb" , "ccc.csb" };
const   char * HelloWorld::m_armatureNames[4] = {  "bear" "horse" , "Cowboy" , "Skeleton1" };
//......
  // load from binary
  ArmatureDataManager::getInstance()->addArmatureFileInfo(m_binaryFilesNames[3]);
  Armature *m_armature = Armature::create(m_armatureNames[3]);
  m_armature->getAnimation()->playWithIndex(0);
  m_armature->setScale(1.0f);
  Size size = Director::getInstance()->getWinSize();
  m_armature->setPosition(size.width/2, size.height/2);
  addChild(m_armature);

对于数组中相应的前三个.csb文件(应该是老版本的STUDIO导出的骨骼动画csb文件),运行上述代码非常顺利(当然,上述addArmatureFileInfo方法调用更早的ExportJson骨骼动画文件的情况也是能够顺利运行)。事实上,cpp-tests自然也已经在我的机器上顺序调试通过(我的环境是windows 7 64bits Visual Studio 2013)。但是,对于最后那个csb文件(使用当前新版本Cocos Studio 2.3.2导出的骨骼动画文件),则根本不行,执行中断停止在addArmatureFileInfo调用的下一行。

 

在经过部分的源码跟踪后,我尝试着使用碎图技术生成csb文件,尽量使之与cpp-tests提供的文件形式上一致,结果也根本通不过!

 

太遗憾了,我就是想使用Armature及相应的如下技术:

1
    armature->getAnimation()->setMovementEventCallFunc(CC_CALLBACK_0(TestAnimationEvent::animationEvent,  this , std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

但是,很遗憾,只能干瞪眼!没有Armature,我们根本无法使用setMovementEventCallFunc回调函数及其相应技术了。

 

遗憾的是,对于上述问题,官方网站上及DEMO中只字未提!

 

变通办法

 

对于我目前的程序中的上述要求,我只能尝试着其他的变通方法,因为我的要求也并不高。于是我尝试着使用帧事件方法解决了上述问题。

 

在此,我粘贴上我的示例游戏中的相关代码。

第一部分如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  //2load title and mushroom animation
 
  Node* node2 = CSLoader::createNode( "SplashAnimationSkeleton.csb" );
 
  addChild(node2);
 
  node2->setPosition(Vec2(VisibleRect::center().x, VisibleRect::center().y));
 
  //在cocos studio设计器中选择是否循环播放,对于在代码中动画的是否循环播放没有影响!!!//
 
  ActionTimeline* action2 = CSLoader::createTimeline( "SplashAnimationSkeleton.csb" );
 
  node2->runAction(action2);
 
  action2->gotoFrameAndPlay(0, false );
 
  action2->setFrameEventCallFunc(CC_CALLBACK_1(SplashScene::onFrameEvent,  this ));

 

注意,上面的SplashAnimationSkeleton.csb是使用cocos studio 2.3.2创建的简单的骨骼动画文件。

 

我原先设计的使用setMovementEventCallFunc方法结合Armature数据想实现的是目标是:当骨骼动画播放结束,触发另一个既定事件,并在这个事件中完成另外的动画播放任务。

 

对于上述目标,使用帧事件应该是可以的,只是稍微麻烦一些罢了。例如,需要在studio设计器中填写帧事件数据;但是,总算还可以实现。

另外一部分相关代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void  SplashScene::onFrameEvent(Frame* frame)
{
  EventFrame* evnt =  dynamic_cast <EventFrame*>(frame);
  if  (!evnt)
   return ;
  std::string str = evnt->getEvent();
  if  (str ==  "lastFrame" )
  {
   Node* butterfly_01 = CSLoader::createNode( "ButterflyArmature_01.csb" );
   addChild(butterfly_01,100);
   butterfly_01->setPosition(Vec2(VisibleRect::right().x + 100, 0));
   ActionTimeline* action2 = CSLoader::createTimeline( "ButterflyArmature_01.csb" );
   butterfly_01->runAction(action2);
   action2->gotoFrameAndPlay(0,  true );
   Node* p1 = _rootLayer->getChildByName( "Mushroom_Point" );
   auto   action = Sequence::create(
    MoveTo::create(2, p1->getPosition()),
    CallFunc::create(CC_CALLBACK_0(SplashScene::callback0,  this )),
    nullptr);
   butterfly_01->runAction(action);
  }
}

大家看到,我在帧事件回调函数中进行判断,当动画播放到特定帧时(正是我以前要求的第一个动画播放结束时)触发另一个蝴蝶飞入动画的播放。

 

小结一下

 

通过学习与研究部分cocos2d-x 及cocos studio最新版本技术可以学习到更优秀的开发技术的同时,注定我要牺牲许多时间去“踏坑”,也许有得就有失吧。

最后,再提醒一下新手同学,示例工程中的代码部分与资源数据文件部分都有些不太明确的调用,当然,看起来官方是要尽量使用最新的c++代码来使用(或者说保护)早期studio导出的资源。但在同时,却露出了不少急于求成的“马脚”。


















本文转自朱先忠老师51CTO博客,原文链接:http://blog.51cto.com/zhuxianzhong/1713824 ,如需转载请自行联系原作者



相关文章
|
前端开发
Threejs - 加载视频纹理渲染 实现一个3D视频播放器
Threejs - 加载视频纹理渲染 实现一个3D视频播放器
2135 0
Threejs - 加载视频纹理渲染 实现一个3D视频播放器
|
1月前
|
JavaScript
Threejs加载MMD
这篇文章详细介绍了如何在Three.js中加载和使用MMD(MikuMikuDance)模型,包括模型的导入、动画的播放以及与MMD相关的文件格式和操作流程。
56 2
Threejs加载MMD
|
3月前
|
API C# 图形学
Unity3D学习笔记9——加载纹理
Unity3D学习笔记9——加载纹理
41 2
|
图形学
【unity细节】unity物体Model和prefab的区别
【unity细节】unity物体Model和prefab的区别
206 0
|
API 图形学
【unity细节】unity中实例化的物体在Game视图无法显示
【unity细节】unity中实例化的物体在Game视图无法显示
368 0
|
图形学 索引
Cocos2d-x-v3场景切换
Cocos2d-x-v3场景切换
140 0
|
测试技术 图形学 Android开发
|
编解码 测试技术 Android开发