转自:http://blog.sina.com.cn/s/blog_7608655901017s2b.html
最近在修改一个cocos2d的项目,要把它移植到cocos2d-x,原来的项目中用到了多线程,但是在cocos2d-x中的实现有点不太一样,在CSDN上找了一篇文章,有详细的代码示例:在新的线程中加载资源文件。原文地址:http://blog.csdn.net/we000636/article/details/8641270
原文章是在windows系统下讲解的,在xcode中同样需要导入pThread类库。
简单线程开启方法如下代码所示:
头文件:
.h
- #define
_LOADING_SCENE_H__ -
- #include
"cocos2d.h" - #include
"pthread/pthread.h" - class
LoadingScene : public cocos2d::CCScene{ - public:
-
virtual bool init(); -
CREATE_FUNC(LoadingScene); -
int start(); -
void update(float dt); - private:
-
pthread_t pid; -
static void* updateInfo(void* args); //注意线程函数必须是静态的 - };
cpp文件
#include
- #include
"pthread/pthread.h" -
- using
namespace cocos2d; - bool
LoadingScene::init(){ -
this->scheduleUpdate(); -
start(); -
return true; - }
- void
LoadingScene::update(float dt){ -
//可以在这里重绘UI - }
- void*
LoadingScene::updateInfo(void* args){ -
//可以在这里加载资源 -
return NULL; - }
- int
LoadingScene::start(){ -
pthread_create(&pid,NULL,updateInfo,NULL); //开启新线程 -
return 0; - }
二加载Plist
我们可以在新开的线程中,加载资源,设置一个静态变量bool,在新线程中,当加载完所有资源后,设置bool值为真。在主线程中Update中,检测bool值,为假,可以重绘UI(例如,显示加载图片,或者模拟加载进度),为真,则加载目标场景。相关代码如下:
-
CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache(); -
cache->addSpriteFramesWithFile("BattleIcons.plist"); -
cache->addSpriteFramesWithFile("ArcherAnim.plist"); -
cache->addSpriteFramesWithFile("DeathReaperAnim.plist"); -
loadComplete = true; //状态值设为真,表示加载完成 -
return NULL; - }
成功加载且运行后,你会发现新场景中所有精灵都不显示(类似于黑屏了)。为什么呢?
因为我们在加载plist文件时,addSpriteFramesWithFile方法里会帮我们创建plist对应Png图的Texture2D,并将其加载进缓存中。可是这里就遇到了一个OpenGl规范的问题:不能在新开的线程中,创建texture,texture必须在主线程创建.通俗点,就是所有的opengl
所以不能在新线程中创建Texture2D,导致纹理都不显示,那么该怎么办?让我们看看CCSpriteFrameCache源码,发现CCSpriteFrameCache::addSpriteFramesWithFile(constchar *pszPlist, CCTexture2D*pobTexture)方法,是可以传入Texture2D参数的。是的,我们找到了解决方法:
相关代码如下:
-
CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage("BattleIcons.png"); //在这里(主线程中)加载plist对应的Png图片进纹理缓存 -
CCTexture2D *texture2 = CCTextureCache::sharedTextureCache()->addImage("ArcherAnim.png"); //以这种方法加载的纹理,其Key值就是文件path值,即例如 - texture2的key值就是ArcherAnim.png
-
CCTexture2D *texture3 = CCTextureCache::sharedTextureCache()->addImage("DeathReaperAnim.png"); -
pthread_create(&pid,NULL,updateInfo,NULL); //开启新线程 -
return 0; - }
- void*
LoadingScene::updateInfo(void* args){ -
CCSpriteFrameCache *cache = CCSpriteFrameCache::sharedSpriteFrameCache(); -
CCTextureCache* teCache = CCTextureCache::sharedTextureCache(); -
CCTexture2D* texture1 = teCache->textureForKey("BattleIcons.png"); //从纹理缓存中取出Texure2D,并将其当参数传入addSpriteFramesWithFile方法中 -
cache->addSpriteFramesWithFile("BattleIcons.plist",texture1); -
CCTexture2D* texture2 = teCache->textureForKey("ArcherAnim.png"); -
cache->addSpriteFramesWithFile("ArcherAnim.plist",texture2); -
CCTexture2D* texture3 = teCache->textureForKey("DeathReaperAnim.png"); -
cache->addSpriteFramesWithFile("DeathReaperAnim.plist",texture3); -
loadComplete = true; -
return NULL; - }
这样解决,就不违背OpenGl规范,没有在新线程中创建Texture2D。