您的位置:首页 > 其它

addImageAsync异步加载资源和进度条ProgressTimer的实现

2015-12-30 14:00 405 查看
我们要实现的效果图如下:



异步加载:

在进入游戏的时候,玩家都会看到这样的进度条,当翔仔第一次看到这个效果的时候单纯的以为这只是为了游戏的视觉效果而制作的一个进度条。后来才知道开发人员是不得已为之必须制作这个进度条,才能让游戏看起来流畅,顺利的运行。

cocos是一个单线程的引擎,单线程的一个优点就是安全,不用考虑多线程造成的总总困扰。但是在一个游戏场景结束后进入另外一个新的游戏场景我们总会进行加载UI和图片。如果图片资源大并且分辨率高,那么处理器往往不能再第一帧完成所有的图片加载,那么就会造成卡屏现象,导致线程堵塞。如何解决? 当然是在进入新场景前将所有的是的图片预加载到内存中,在新场景的时候直接使用Sprite::createa()便会自动从内存取出使用。便可解决。

cocos提供了addImageAsync()函数来帮助开发人员进行预加载,这种加载是异步加载,addImageAsync函数会申请新的线程来加载图片,主程可以继续运行。*加载完一个图片后addImageAsync可以调用回调函数来通知开发人员,那么可以利用这个回调还是来制作进度条!*

下面来进行实现:

class LoadingScene :public Scene
{
public:

static Scene* createScene(int,int,std::vector<std::string>,char *);
bool init();
void addResource();
void readCallback();
private:
//存放的所有资源
std::vector<std::string> m_vecpics;
//资源数目
int m_numofpic;
//音乐路径
char* m_ptmic;
//loading条的计数器
int m_count;
//显示文字
LabelTTF* m_ptloadingWords;     //显示的文字
//进度条的实现
Sprite *m_ptprogressBarBase;
ProgressTimer *m_ptpro;
Scene* LoadingScene::createScene(int type, int special, std::vector<std::string> pics, char* mic)
{
auto ref = new LoadingScene;
if (ref&&ref->init()){
ref->addResource();
ref->autorelease();
return ref;
}
else{
ref->release();
}
}
bool LoadingScene::init()
{
if (!Scene::init())
{
return false;
}
//移除上一次缓冲区的资源
Director::getInstance()->getTextureCache()->removeAllTextures();
Size size = Director::getInstance()->getVisibleSize();

m_ptloadingWords = LabelTTF::create("Loading..... 0%", "Arial", 40);
m_ptloadingWords->setColor(Color3B(255, 255, 0));
m_ptloadingWords->setPosition(size.width / 2, size.height / 2 + 60);
addChild(m_ptloadingWords);

m_ptprogressBarBase = Sprite::create("loginRect0.png");
m_ptprogressBarBase->setPosition(size.width / 2, size.height / 2 + 20);
addChild(m_ptprogressBarBase);

m_ptpro = ProgressTimer::create(Sprite::create("loginRect1.png"));
m_ptpro->setType(ProgressTimer::Type::BAR);
//设置起点
m_ptpro->setMidpoint(Vec2(0, 1));
//设置方向
m_ptpro->setBarChangeRate(Vec2(1, 0));
m_ptpro->setPosition(m_ptprogressBarBase->getPosition());
m_ptpro->setPercentage(0);
addChild(m_ptpro);

return true;

}
void LoadingScene::addResource()
{

for (auto p : m_vecpics)
Director::getInstance()->getTextureCache()->addImageAsync(p, CC_CALLBACK_0(LoadingScene::readCallback,this));
}

void LoadingScene::readCallback()
{
m_count++;
int a = (float(m_count) / float(m_numofpic)) * 100;
char x[100];
sprintf(x, "Loading..... %d%%", a);
m_ptloadingWords->setString(x);
m_ptpro->setPercentage(a);
log("----------------%d-----%d",m_count,m_numofpic );
if (m_count == m_numofpic)
{
//跳入新场景
Scene* scene = getNewScene();
TransitionScene* tra = getTransition(scene);
Director::getInstance()->replaceScene(tra);
}
}


上述代码都是经过翔仔删减的,所以需要大家看懂后自己重新实现才行。下面给大家详细解释下进度条的部分代码(见代码注释):

//创建一个精灵,给进度条一个背景图片,也就是刚才开始0%的时候的图片
m_ptprogressBarBase = Sprite::create("loginRect0.png");
m_ptprogressBarBase->setPosition(size.width / 2, size.height / 2 + 20);
addChild(m_ptprogressBarBase);
//开始创建进度条
m_ptpro = ProgressTimer::create(Sprite::create("loginRect1.png"));
m_ptpro->setType(ProgressTimer::Type::BAR);
//设置进度条的类型,横向
m_ptpro->setMidpoint(Vec2(0, 1));
//设置进度条的移动方向
m_ptpro->setBarChangeRate(Vec2(1, 0));
//这个翔仔暂时也不清楚,自己百度下··
m_ptpro->setPosition(m_ptprogressBarBase->getPosition());//让精灵和进度条的位置重合
m_ptpro->setPercentage(0);

addChild(m_ptpro);
//每次成功加载一个图片,便会调用回掉函数readCallback,在这里我们实现进度条的移动
void LoadingScene::readCallback()
{
m_count++;
//计算当前进度条的进度,其实这里大家可以自己设置
int a = (float(m_count) / float(m_numofpic)) * 100;
char x[100];
sprintf(x, "Loading..... %d%%", a);
//显示进度
m_ptloadingWords->setString(x);
//设置当前进度条的进度
m_ptpro->setPercentage(a);
log("----------------%d-----%d",m_count,m_numofpic );
if (m_count == m_numofpic)
{
//跳入新场景
Scene* scene = getNewScene();
TransitionScene* tra = getTransition(scene);
Director::getInstance()->replaceScene(tra);
}
}


这里加载的图片loginRect0如下:


图片loginRect1如下:



OK,进度条很简单,轻松完成,有问题请留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: