`
445822357
  • 浏览: 743719 次
文章分类
社区版块
存档分类
最新评论

cococs2d-x 多线程加载plist

 
阅读更多

转自:http://blog.csdn.net/we000636/article/details/8641270


实现多线程加载plist功能,需掌握知识:

1.多线程开启:pthread

2.如何在线程中加载plist


一.多线程开启

当我们想在程序中开多线程中,第一想到的是cocos2d-x有没有自带方法,幸运的是我们找到了CCThread,不幸却发现里面什么都没有。cocos2d-x自带了一个第三方插件--pthread,在cocos2dx\platform\third_party\win32\pthread可以找到。既然是自带的,必须它的理由。想在VS中应用这个插件需要两个步骤:

1.需要右键工程--属性--配置属性--链接器--输入--编缉右侧的附加依赖项--在其中添加pthreadVCE2.lib,如下图所示:


2..需要右键工程--属性--配置属性--C/C++--常规--编缉右侧的附加包含目录--添加新行--找到pthread文件夹所在位置,如下图所示:



然后我们就可以应用这个插件在程序中开启新线程,简单线程开启方法如下代码所示:

头文件:

  1. #ifndef_LOADING_SCENE_H__
  2. #define_LOADING_SCENE_H__
  3. #include"cocos2d.h"
  4. #include"pthread/pthread.h"
  5. classLoadingScene:publiccocos2d::CCScene{
  6. public:
  7. virtualboolinit();
  8. CREATE_FUNC(LoadingScene);
  9. intstart();
  10. voidupdate(floatdt);
  11. private:
  12. pthread_tpid;
  13. staticvoid*updateInfo(void*args);//注意线程函数必须是静态的
  14. };


cpp文件
  1. #include"LoadingScene.h"
  2. #include"pthread/pthread.h"
  3. usingnamespacecocos2d;
  4. boolLoadingScene::init(){
  5. this->scheduleUpdate();
  6. start();
  7. returntrue;
  8. }
  9. voidLoadingScene::update(floatdt){
  10. //可以在这里重绘UI
  11. }
  12. void*LoadingScene::updateInfo(void*args){
  13. //可以在这里加载资源
  14. returnNULL;
  15. }
  16. intLoadingScene::start(){
  17. pthread_create(&pid,NULL,updateInfo,NULL);//开启新线程
  18. return0;
  19. }



二 加载Plist

我们可以在新开的线程中,加载资源,设置一个静态变量bool,在新线程中,当加载完所有资源后,设置bool值为真。在主线程中Update中,检测bool值,为假,可以重绘UI(例如,显示加载图片,或者模拟加载进度),为真,则加载目标场景。相关代码如下:

  1. void*LoadingScene::updateInfo(void*args){
  2. CCSpriteFrameCache*cache=CCSpriteFrameCache::sharedSpriteFrameCache();
  3. cache->addSpriteFramesWithFile("BattleIcons.plist");
  4. cache->addSpriteFramesWithFile("ArcherAnim.plist");
  5. cache->addSpriteFramesWithFile("DeathReaperAnim.plist");
  6. loadComplete=true;//状态值设为真,表示加载完成
  7. returnNULL;
  8. }


成功加载且运行后,你会发现新场景中所有精灵都不显示(类似于黑屏了)。为什么呢?

因为我们在加载plist文件时,addSpriteFramesWithFile方法里会帮我们创建plist对应Png图的Texture2D,并将其加载进缓存中。可是这里就遇到了一个OpenGl规范的问题:不能在新开的线程中,创建texture,texture必须在主线程创建.通俗点,就是所有的openglapi都必须在主线程中调用;其它的操作,比如文件,内存,plist等,可以在新线程中做,这个不是cocos2d不支持,是opengl的标准,不管你是在android,还是windows上使用opengl,都是这个原理。

所以不能在新线程中创建Texture2D,导致纹理都不显示,那么该怎么办?让我们看看CCSpriteFrameCache源码,发现CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist, CCTexture2D *pobTexture)方法,是可以传入Texture2D参数的。是的,我们找到了解决方法:

相关代码如下:

  1. intLoadingScene::start(){
  2. CCTexture2D*texture=CCTextureCache::sharedTextureCache()->addImage("BattleIcons.png");//在这里(主线程中)加载plist对应的Png图片进纹理缓存
  3. CCTexture2D*texture2=CCTextureCache::sharedTextureCache()->addImage("ArcherAnim.png");//以这种方法加载的纹理,其Key值就是文件path值,即例如
  4. texture2的key值就是ArcherAnim.png
  5. CCTexture2D*texture3=CCTextureCache::sharedTextureCache()->addImage("DeathReaperAnim.png");
  6. pthread_create(&pid,NULL,updateInfo,NULL);//开启新线程
  7. return0;
  8. }
  9. void*LoadingScene::updateInfo(void*args){
  10. CCSpriteFrameCache*cache=CCSpriteFrameCache::sharedSpriteFrameCache();
  11. CCTextureCache*teCache=CCTextureCache::sharedTextureCache();
  12. CCTexture2D*texture1=teCache->textureForKey("BattleIcons.png");//从纹理缓存中取出Texure2D,并将其当参数传入addSpriteFramesWithFile方法中
  13. cache->addSpriteFramesWithFile("BattleIcons.plist",texture1);
  14. CCTexture2D*texture2=teCache->textureForKey("ArcherAnim.png");
  15. cache->addSpriteFramesWithFile("ArcherAnim.plist",texture2);
  16. CCTexture2D*texture3=teCache->textureForKey("DeathReaperAnim.png");
  17. cache->addSpriteFramesWithFile("DeathReaperAnim.plist",texture3);
  18. loadComplete=true;
  19. returnNULL;
  20. }


这样解决,就不违背OpenGl规范,没有在新线程中创建Texture2D。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics