多-threaded负荷plist特征。获取知识的必要性:
1.多线程开启:pthread
2.怎样在线程中载入plist
一.多线程开启
当我们想在程序中开多线程中。第一想到的是cocos2d-x有没有自带方法。幸运的是我们找到了CCThread,不幸却发现里面什么都没有。
cocos2d-x自带了一个第三方插件--pthread,在cocos2dx\platform\third_party\win32\pthread能够找到。既然是自带的,必须它的理由。想在VS中应用这个插件须要两个步骤:
1.须要右键project--属性--配置属性--链接器--输入--编缉右側的附加依赖项--在当中加入pthreadVCE2.lib,例如以下图所看到的:
2..须要右键project--属性--配置属性--C/C++--常规--编缉右側的附加包括文件夹--加入新行--找到pthread文件夹所在位置。例如以下图所看到的:
然后我们就能够应用这个插件在程序中开启新线程。简单线程开启方法例如以下代码所看到的:
头文件:
-
#ifndef _LOADING_SCENE_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 "LoadingScene.h"
-
#include "pthread/pthread.h"
-
-
using namespace cocos2d;
-
bool LoadingScene::init(){
-
this->scheduleUpdate();
-
start();
-
return true;
-
}
-
void LoadingScene::update(float dt){
-
-
}
-
void* LoadingScene::updateInfo(void* args){
-
-
return NULL;
-
}
-
int LoadingScene::start(){
-
pthread_create(&pid,NULL,updateInfo,NULL);
-
return 0;
-
}
二 载入Plist
我们能够在新开的线程中。载入资源,设置一个静态变量bool,在新线程中。当载入全然部资源后,设置bool值为真。在主线程中Update中,检測bool值,为假,能够重绘UI(比如,显示载入图片,或者模拟载入进度),为真,则载入目标场景。相关代码例如以下:
-
void* LoadingScene::updateInfo(void* args){
-
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 api都必须在主线程中调用;其他的操作,比方文件,内存。plist等,能够在新线程中做,这个不是cocos2d不支持,是opengl的标准,无论你是在android,还是windows上使用opengl,都是这个原理。
所以不能在新线程中创建Texture2D,导致纹理都不显示。那么该怎么办?让我们看看CCSpriteFrameCache源代码。发现CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist, CCTexture2D *pobTexture)方法,是能够传入Texture2D參数的。
是的。我们找到了解决方法:
相关代码例如以下:
-
int LoadingScene::start(){
-
CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage("BattleIcons.png");
-
CCTexture2D *texture2 = CCTextureCache::sharedTextureCache()->addImage("ArcherAnim.png");
-
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");
-
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。