1、先說說addImageAsync()異步加載圖檔的問題
做遊戲的時候現在資源的比較大,所有我們必然會有一個loading界面,而我在找寫loading界面的方法的時候,發現了2種方法。
一種是自己建立一個線程,再在這個線程裡面加載資源,不過由于openGL的限制,隻能在主線程裡面繪制UI,不過有的人也想出了其他的方法,就是先隻緩存,再在主線程裡面繪制。這裡有這方面的教程。不過這種方法有點繞,反正我是搞得不是很清楚。
另一種,也是TestCpp裡面使用的方法,那就是用
CCTextureCache::sharedTextureCache()->addImageAsync("Texture2D_Test3.png", this, callfuncO_selector(LoadingScene::loadingCallBack));
函數異步加載圖檔,基本應用可以看TestCpp裡面的TextureCacheTest這一個。
2、我遇到的問題
TestCpp裡面當資源都加載好了的時候,它并沒有跳轉場景,而是把先前的畫面顯示的都移除,再添加新的精靈,但是我現在想做是當資源都加載好的時候就從loading界面跳轉到讀取成功界面,而不是簡單的把資源移除與添加新的資源。TextureCacheTest裡面的寫法如下。詳細的請自行去TestCpp裡面檢視。
if (m_nNumberOfLoadedSprites == m_nNumberOfSprites)
{
this->removeChild(m_pLabelLoading, true);
this->removeChild(m_pLabelPercent, true);
addSprite(); //僅僅添加精靈
}
但是我想做的是
if (m_nLoadedResources == m_nAllLoadResources)
{
this->removeAllChildren();
CCScene *loginSuccessScene = LoginSuccessScene::scene();
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.1f, loginSuccessScene));
}
不過當我這麼寫的時候就遇到了問題,那就是場景确實是跳轉了,但是隻是一閃而逝,就又跳回到了loading的場景裡面,而由于我this->removeAllChildren(),是以最後螢幕就黑了。
3、我的解決方法
關于上面那個問題,我的了解是由于我是在 addImageAsync的回調函數LoadingScene::loadingCallBack 裡面寫的跳轉場景,但是當這個線程執行完了之後,主線程會還是在執行的。是以這個裡面的跳轉隻是一閃而逝的。然後我請教他人知道了其實主線程裡面有一個update()函數,它會一直調用。于是我便把上面的那個函數寫在了update裡面,因為update是引擎自帶的函數,是以雖然我顯性沒有調用,但是它會自行調用,你可以直接檢視update()函數的原型 。update()如下
void LoadingScene::update( float delta )
{
if (m_nLoadedResources == m_nAllLoadResources)
{
this->removeAllChildren();
CCScene *loginSuccessScene = LoginSuccessScene::scene();
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.1f, loginSuccessScene));
}
}
但是這樣其實會有一個問題,當資源讀取很快的時候,會跳到loading成功界面,不過之後還是會閃一下,我的了解是當跳轉的時候,可能異步加載資源海沒有完全完成,是以還是會運作那個函數。是以我便加了一個變量m_fWaitTime,在update裡面讓其m_fWaitTime += delta; 并當m_fWaitTime > 5.0f的時候才跳轉頁面,當你想測試一個不等待的時候的效果的時候可以将這個變量相關的東西都注釋掉,當然了,我們運作遊戲的時候加載時間一般都相對較長,是以不用擔心。(不過我還沒有真機測試過=.=,如果真機測試的時候出問題了,我會過來及時更正的)。
4、loading源代碼
下面是loading的主要代碼,其中 addImageAsync()加載的資源都可以用CCTexture2D *texture1 = CCTextureCache::sharedTextureCache()->textureForKey("Test.png");直接取的并使用,就算是在不同的類裡面使用而是同一個類。 LoadingScene.h
#ifndef _LOADING_SCENE_H__
#define _LOADING_SCENE_H__
#include "cocos2d.h"
USING_NS_CC;
class LoadingScene : public CCLayer
{
public:
virtual bool init();
static CCScene *scene();
void loadSuccess();
//讀取的回調函數
void loadingCallBack(CCObject *obj);
void addSprite();
void update(float delta);
void updateProgress(float dt);
CREATE_FUNC(LoadingScene);
private:
//讀取開始時候的進度條
CCSprite *m_pLoadBarStart;
//讀取完成時候的進度條
CCProgressTimer *m_pLoadBarEnd;
//線程相關的函數
//總的加載圖檔數
int m_nAllLoadResources;
//目前加載圖檔數
int m_nLoadedResources;
//讀取進度
float m_fProgressIndex;
CCLabelTTF *m_pLabelLoading;
CCLabelTTF *m_pLabelPercent;
// 當要測試有m_fWaitTime的效果的時候,将下一行與update()和init()裡面初始化的注釋取消掉即可
// float m_fWaitTime;
};
#endif
LoadingScene.cpp
#include "LoadingScene.h"
#include "LoginSuccessScene.h"
#include "Global.h"
CCScene* LoadingScene::scene()
{
CCScene * scene = NULL;
do
{
// 'scene' is an autorelease object
scene = CCScene::create();
CC_BREAK_IF(! scene);
// 'layer' is an autorelease object
LoadingScene *layer = LoadingScene::create();
CC_BREAK_IF(! layer);
// add layer as a child to scene
scene->addChild(layer);
} while (0);
// return the scene
return scene;
}
bool LoadingScene::init()
{
if (!CCLayer::init())
{
return false;
}
scheduleUpdate();
CCSize size = CCDirector::sharedDirector()->getWinSize();
m_nAllLoadResources = 3;
m_nLoadedResources = 0;
m_fProgressIndex = 0.0;
// m_fWaitTime = 0;
m_pLabelLoading = CCLabelTTF::create("loading...", "Arial", 15);
m_pLabelPercent = CCLabelTTF::create("%0", "Arial", 15);
m_pLabelLoading->setPosition(ccp(400, 200));
m_pLabelPercent->setPosition(ccp(450, 200));
this->addChild(m_pLabelLoading, 1);
this->addChild(m_pLabelPercent, 1);
//loading的動畫效果
m_pLoadBarStart = CCSprite::create("loadingStart.jpg");
m_pLoadBarStart->setPosition(ccp(size.width / 2, size.height * 3 / 4));
m_pLoadBarStart->setScale(2.0f);
this->addChild(m_pLoadBarStart);
m_pLoadBarEnd = CCProgressTimer::create(CCSprite::create("loadingEnd.jpg"));
m_pLoadBarEnd->setPercentage(1.0f);
m_pLoadBarEnd->setPosition(ccp(size.width / 2, size.height * 3 / 4));
m_pLoadBarEnd->setType(kCCProgressTimerTypeBar);
m_pLoadBarEnd->setBarChangeRate(ccp(1, 0));
m_pLoadBarEnd->setMidpoint(ccp(0, 0));
m_pLoadBarEnd->setScale(2.0f);
this->addChild(m_pLoadBarEnd);
//讀取資源
CCTextureCache::sharedTextureCache()->addImageAsync("Texture2D_Test1.png", this, callfuncO_selector(LoadingScene::loadingCallBack));
CCTextureCache::sharedTextureCache()->addImageAsync("Texture2D_Test2.png", this, callfuncO_selector(LoadingScene::loadingCallBack));
CCTextureCache::sharedTextureCache()->addImageAsync("Texture2D_Test3.png", this, callfuncO_selector(LoadingScene::loadingCallBack));
//設定一個動作,令進度條2秒内讀取到100%
// CCProgressTo *action = CCProgressTo::create(2, 100);
// m_pLoadBarEnd->runAction(CCSequence::create(action, CCCallFunc::create(this,
// callfunc_selector(LoadingScene::loadSuccess)), NULL));
return true;
}
void LoadingScene::loadSuccess()
{
this->removeAllChildren();
CCScene *loginSuccessScene = LoginSuccessScene::scene();
CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.1f, loginSuccessScene));
// CCDirector::sharedDirector()->pushScene(loginSuccessScene);
}
void LoadingScene::loadingCallBack(CCObject *obj)
{
++m_nLoadedResources;
char tmp[10];
sprintf(tmp,"%%%d", (int)(((float)m_nLoadedResources / m_nAllLoadResources ) * 100));
m_pLabelPercent->setString(tmp);
m_fProgressIndex = (((float)m_nLoadedResources / m_nAllLoadResources ) * 100);
m_pLoadBarEnd->setPercentage(m_fProgressIndex);
}
void LoadingScene::update( float delta )
{
// m_fWaitTime += delta;
if (m_nLoadedResources == m_nAllLoadResources
// && m_fWaitTime > 5.0f
)
{
loadSuccess();
}
}
如果有什麼錯誤或者解釋不當的地方歡迎指正,我隻是因為這個困擾了我的問題得到了解決便寫上來,讓也被這個問題困擾的人能夠得到解答。希望能夠幫到你們。