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();
    }
}

如果有什么错误或者解释不当的地方欢迎指正,我只是因为这个困扰了我的问题得到了解决便写上来,让也被这个问题困扰的人能够得到解答。希望能够帮到你们。

时间: 2024-12-21 05:13:52

cocos2d-x addImageAsync()异步加载资源成功之后的场景跳转问题的相关文章

【Cocos2d-Js基础教学(5)资源打包工具的使用及资源的异步加载处理】

[转载]http://www.cnblogs.com/zisou/p/cocos2dx-js5.html   TexturePacker是纹理资源打包工具,支持Cocos2dx的游戏资源打包. 如果用过的同学可以直接看下面的资源的异步加载处理 首先为什么用TexturePacker? 1,节省图片资源实际大小 2,减少我们游戏中大量资源带来的内存负荷 3,方便游戏对纹理资源的内存管理 游戏开发到后期,我们或许都会遇到的瓶颈就是需要对游戏包进行"瘦身"和内存优化.那么使用TextureP

cocos2d-x lua中实现异步加载纹理

原文地址:  http://www.cnblogs.com/linchaolong/p/4033118.html 前言   问题:最近项目中需要做一个loading个界面,界面中间有一个角色人物走动的动画,在显示这个loading界面的时候加载资源,项目是用cocos2d-x lua实现的,界面做出来后发现在加载资源的时候界面会卡住. 原因: 因为使用的不是异步加载,而且cocos2d-x没有绑定异步加载资源的api到lua中,其实在lua中实现不了异步. 想通过在lua中启动一个线程去加载资源

AssetBundle异步加载被中断的问题

刘 刘泰言创建于 1 年前 在使用异步接口 yield return AssetBundle.ASyncLoad的时候,难免会想到:这个异步处理完之前如何Cancel掉这个任务?也就是一个AssetBundle加载到一半,现在要放弃加载,应该怎么处理? UnityAssetBundle 赞同 0评论 分享 10条回复 曾 曾毅回答于 1 年前 无法CANCEL 赞同 1评论 分享 Walker回答于 1 年前 Unity的接口里没有中断操作,但是可以在自己项目的ABMgr模块给业务逻辑层提供一个

Aery的UE4 C++游戏开发之旅(4)加载资源&创建对象

目录 资源的硬引用 硬指针 FObjectFinder<T> / FClassFinder<T> 资源的软引用 FSoftObjectPaths.FStringAssetReference TSoftObjectPtr<T> 同步加载资源 LoadObject/LoadClass TryLoad/LoadSynchronous 异步加载资源 FStreamableManager.RequestAsyncLoad() 卸载资源 创建对象 创建一般对象 创建Actor派生类

妹子UI-yepnope.js使用详解及示例分享(异步加载数据)

yepnope.js 是一个超高速的按条件异步加载资源的加载器,允许你只加载使用到的资源(css及js). yepnope.js的一个典型实例: ? 1 2 3 4 5 yepnope({ test : Modernizr.geolocation, yep : 'normal.js', nope : ['polyfill.js', 'wrapper.js'] }); 此实例表示如果Modernizr.geolocation为真的时候加载normal.js,为假则加载polyfill.js及wra

Cocos2d-js 开发记录:图片数据资源等的异步加载

这里说的是在需要的使用加载图片,比如游戏中的某个关卡的图片,不用在游戏一开始就加载(万一用户玩不到那关,岂不是很冤,流量费了那么多),否则载入速度也慢.这种方式加载资源要用到cc.loader官方文档上有介绍(http://www.cocos2d-x.org/docs/manual/framework/html5/v3/cc-loader/zh),主要有 loadJs loadJsWithImg loadTxt loadBinary loadImg loadJson 文档给出了一个例子如下: c

自研模块加载器(四) 模块资源定位-异步加载

资源定位-动态加载 通过resolve方法进行异步解析,完整解析如下图所示: 根据上篇文章startUp.js代码,我们继续完善本章动态加载资源的代码. (function(global) { var startUp = global.startUp = { version: '1.0.1' } var data = {}; // 获取当前模块加载器配置信息 var cache = {}; // 缓存 //模块的生命周期 var status = { FETCHED: 1, SAVED: 2,

Unity3D资源异步加载(一)——图片、音视频资源加载

这几天一直做优化的事情,对于资源这一块优化,资源异步加载作为首选,因2018之后版本中弃用了WWW请求,所以今天我们以UnityWebRequest 请求方式介绍,基本上是一个整理. using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; public class ResourceLoad : MonoBehaviour { /// <

异步加载text资源,加载一次、执行一次、链式回调

function getText(time,callback) { setTimeout(function () { callback(time) },time) } var callbackMap={};//记录加载完成的回调 var resMap={};//记录url var loadbackMap={};//记录url 加载完成 var loadedMap={};//记录url 加载完成 var loadedI=-1;//记录url 加载完成位置 var orderI=0;//记录url