cocos2d-x addImageAsync()异步加载资源成功之后的场景跳转问题
http://blog.csdn.net/w20175357/article/details/23546985
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();
}
}
如果有什么错误或者解释不当的地方欢迎指正,我只是因为这个困扰了我的问题得到了解决便写上来,让也被这个问题困扰的人能够得到解答。希望能够帮到你们。
cocos2d-x addImageAsync()异步加载资源成功之后的场景跳转问题的更多相关文章
- 【Cocos2d-Js基础教学(5)资源打包工具的使用及资源的异步加载处理】
TexturePacker是纹理资源打包工具,支持Cocos2dx的游戏资源打包. 如果用过的同学可以直接看下面的资源的异步加载处理 首先为什么用TexturePacker? 1,节省图片资源实际大小 ...
- cocos2d-x lua中实现异步加载纹理
原文地址: http://www.cnblogs.com/linchaolong/p/4033118.html 前言 问题:最近项目中需要做一个loading个界面,界面中间有一个角色人物走动的 ...
- Unity跳转场景进度条制作教程(异步加载)
Unity跳转场景进度条制作 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- AssetBundle异步加载被中断的问题
刘 刘泰言创建于 1 年前 在使用异步接口 yield return AssetBundle.ASyncLoad的时候,难免会想到:这个异步处理完之前如何Cancel掉这个任务?也就是一个AssetB ...
- Aery的UE4 C++游戏开发之旅(4)加载资源&创建对象
目录 资源的硬引用 硬指针 FObjectFinder<T> / FClassFinder<T> 资源的软引用 FSoftObjectPaths.FStringAssetRef ...
- [Android] Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.LoaderCallbacks)
Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.Lo ...
- android实现异步加载图片类
其中牵涉到的关键知识点 1,回调机制,不过回调接口的实现方式有多种多样,可以是一个类继承该接口,也可以是作为一个方法参数: 可以参照自己的这篇博客: http://www.cnblogs.com/bo ...
- UE4:四种加载资源的方式
转自:https://blog.csdn.net/zhangxsv123/article/details/79707686 第一种: 如果该蓝图有C++类(或者说是从C++类创建的蓝图),直接进行加载 ...
- Unity3D_异步加载场景(进度条)
创建两个场景:现在的场景“NowScene”,要加载的场景“LoadScene”: “NowScene”如图所示,“LoadScene”任意: 创建脚本“AsyncLoadScene”,复制如下代码, ...
随机推荐
- bzoj1178 [Apio2009]CONVENTION会议中心 区间dp+贪心
[Apio2009]CONVENTION会议中心 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 1130 Solved: 444[Submit][S ...
- ClassCastException: org.apache.tomcat.websocket.server.WsServerContainer cannot be cast to javax.websocket.server.ServerContainer
21:09:22.221 [MessageBroker-3] INFO c.t.s.s.impl.StockNewsServiceImpl - [2017-12-16 21:09:22] execut ...
- 【poj3621】最优比率环
题意: 给定n个点,每个点有一个开心度F[i],每个点有m条单向边,每条边有一个长度d,要求一个环,使得它的 开心度的和/长度和 这个比值最大.n<=1000,m<=5000 题解: 最优 ...
- 51nod 1190 最小公倍数之和 V2
给出2个数a, b,求LCM(a,b) + LCM(a+1,b) + .. + LCM(b,b). 例如:a = 1, b = 6,1,2,3,4,5,6 同6的最小公倍数分别为6,6,6,12,30 ...
- parseInt函数
1.概念 解析字符串,返回一个整数 2.说明 接收两个参数:需要转化的字符串.需要解析的数字基数,介于2~36之间(若该值神略或为0,数字将以10为基数解析:若参数大于36或小于2则返回NaN) pa ...
- 关于Linux下s、t、i、a权限
文件权限除了r.w.x外还有s.t.i.a权限: 首先我们利用umask查看系统的权限为四位,首位就是特殊权限位,SetUID为4,SetGID为2,t为1 [root@iz2ze46xi6pjjj6 ...
- 计算机网络课设之基于UDP协议的简易聊天机器人
前言:2017年6月份计算机网络的课设任务,在同学的帮助和自学下基本搞懂了,基于UDP协议的基本聊天的实现方法.实现起来很简单,原理也很简单,主要是由于老师必须要求使用C语言来写,所以特别麻烦,而且C ...
- python基础===多进程
进程线程的区别在进程,线程,协程的区别 linux或者unix有fork()函数,但是不支持win系统. multiprocessing multiprocessing模块是跨平台版本的多进程模块.支 ...
- glob模块的使用
glob模块 功能描述:glob模块可以使用Unix shell风格的通配符匹配符合特定格式的文件和文件夹,跟windows的文件搜索功能差不多.glob模块并非调用一个子shell实现搜索功能,而是 ...
- 图论-最近公共祖先-离线Tarjan算法
有关概念: 最近公共祖先(LCA,Lowest Common Ancestors):对于有根树T的两个结点u.v,最近公共祖先表示u和v的深度最大的共同祖先. Tarjan是求LCA的离线算法(先存储 ...