zoukankan      html  css  js  c++  java
  • 【Cocos2dx3.x Lua】图片异步加载

    一、说明

        异步加载就是把消耗程序时间比较大的加载操作放到其他线程中,待加载完毕后通过回调函数的方式通知主线程。
     
    addImageAsync函数实现(Cocos2dx 3.3)

    Link: http://codepad.org/UuNcXMqq    [ raw code | fork ]  
     
    void TextureCache::addImageAsync(const std::string &path, const std::function<void(Texture2D*)>& callback)
    {
        Texture2D *texture = nullptr;
    
        std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);
    
        auto it = _textures.find(fullpath);
        if( it != _textures.end() )
            texture = it->second;
    
        if (texture != nullptr)
        {
            callback(texture);
            return;
        }
    
        // lazy init
        if (_asyncStructQueue == nullptr)
        {             
            _asyncStructQueue = new queue<AsyncStruct*>();
            _imageInfoQueue   = new deque<ImageInfo*>();        
    
            // create a new thread to load images
            _loadingThread = new std::thread(&TextureCache::loadImage, this);
    
            _needQuit = false;
        }
    
        if (0 == _asyncRefCount)
        {
            Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(TextureCache::addImageAsyncCallBack), this, 0, false);
        }
    
        ++_asyncRefCount;
    
        // generate async struct
        AsyncStruct *data = new (std::nothrow) AsyncStruct(fullpath, callback);
    
        // add async struct into queue
        _asyncStructQueueMutex.lock();
        _asyncStructQueue->push(data);
        _asyncStructQueueMutex.unlock();
    
        _sleepCondition.notify_one();
    }
    异步加载实例:
        ImageAsync.lua
        

    Link: http://codepad.org/ydr3m4bK    [ raw code | fork ]  
    --图片异步加载
    ImageAsync=class("ImageAsync",function()
        return cc.Layer:create()
    end)
    
    ImageAsync.ctor=function(self)
        self.size=cc.Director:getInstance():getWinSize()
        self:initTexture()
        self:loadingLabel()
        self.curIndex=0 --当前loaded的图片编号
    
        self:registerScriptHandler(function(tag)
            if tag=="enter" then
                --设置定时器
                self:scheduleUpdateWithPriorityLua(function(dt)
                    self:loadTexture()
                end,0)
            elseif tag=="exit" then
                cclog("exit")
                self:unscheduleUpdate()
                cc.Director:getInstance():getTextureCache():removeAllTextures()
            end
        end)
    end
    
    --初始化loadding label
    ImageAsync.loadingLabel=function(self)
        local label=cc.Label:createWithTTF("Loading...0%", "res/fonts/arial.ttf", 32)
        label:setPosition(self.size.width/2,self.size.height/4)
        self:addChild(label)
        self.label=label
    end
    
    --初始化图片集
    ImageAsync.initTexture=function(self)
        self.textures={}
        for i=0,7 do
            for j=0,7 do
                local image=string.format("Images/sprites_test/sprite-%d-%d.png",i,j)
                table.insert(self.textures,image)
            end
        end
    end
    
    --异步加载图片
    ImageAsync.loadTexture=function(self)
        local function loadedImage(texture)
            local sprite=cc.Sprite:createWithTexture(texture)
            sprite:setPosition(cc.p(self.size.width/2,self.size.height/2))
            sprite:setScale(2)
            self:addChild(sprite)
            self.curIndex=self.curIndex+1
            self.label:setString(string.format("Loading...%d%%",math.floor(100*self.curIndex/#self.textures)))
            cclog(string.format("loaded self.textures[%d]:%s",self.curIndex,self.textures[self.curIndex]))
        end
    
        local textureCache=cc.Director:getInstance():getTextureCache()
        for i=1,#self.textures do
            textureCache:addImageAsync(self.textures[i],loadedImage)
        end
    
        self:unscheduleUpdate()
    end
    
    ImageAsync.create=function()
        local layer=ImageAsync.new()
        return layer
    end
    
    return ImageAsync
    执行效果:
        
     
    补充说明:
        Cocos2dx TextureCache会加载图片到内存中,创建Sprite  initWithFile时如果内存中已经有该texture直接使用该texture,这样就达到了减少切换界面时出现的卡顿(直接从内存中取资源,而非IO操作),具体实现如下:
        
     
    TextureCache的addImage实现如下:
    Texture2D * TextureCache::addImage(const std::string &path)
    {
        Texture2D * texture = nullptr;
        Image* image = nullptr;
        // Split up directory and filename
        // MUTEX:
        // Needed since addImageAsync calls this method from a different thread
    
        std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);
        if (fullpath.size() == 0)
        {
            return nullptr;
        }
        auto it = _textures.find(fullpath);
        if( it != _textures.end() )
            texture = it->second;
    
        if (! texture)
        {
            // all images are handled by UIImage except PVR extension that is handled by our own handler
            do 
            {
                image = new (std::nothrow) Image();
                CC_BREAK_IF(nullptr == image);
    
                bool bRet = image->initWithImageFile(fullpath);
                CC_BREAK_IF(!bRet);
    
                texture = new (std::nothrow) Texture2D();
    
                if( texture && texture->initWithImage(image) )
                {
    #if CC_ENABLE_CACHE_TEXTURE_DATA
                    // cache the texture file name
                    VolatileTextureMgr::addImageTexture(texture, fullpath);
    #endif
                    // texture already retained, no need to re-retain it
                    _textures.insert( std::make_pair(fullpath, texture) );
                }
                else
                {
                    CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache", path.c_str());
                }
            } while (0);
        }
    
        CC_SAFE_RELEASE(image);
    
        return texture;
    }
     
    补充说明:
        异步加载plist和png图片——方法是在异步加载png图片的回调函数中,加载plist文件
        Link: http://codepad.org/BuWR4Hdl    [ raw code | fork ]
     
    local BaseLoading=class("BaseLoading",function()
        return cc.Layer:create()
    end)
    
    BaseLoading.init=function(self)
        self._size=cc.Director:getInstance():getWinSize()
        self._textures={}
        self._curIndex=1 --当前loaded的图片编号
    
        self:initTexture()
        self:loadingUI()
    end
    
    --需要加载的所有资源文件
    BaseLoading.initTexture=function(self)
    
    end
    
    --异步加载图片
    BaseLoading.loadTexture=function(self)
        local frameCache=cc.SpriteFrameCache:getInstance()
        --加载图片
        local function loadPng(texture)
            self._label:setString(string.format("Loading...%d%%",math.floor(100*self._curIndex/#self._textures)))
            cclog(string.format("loaded self.textures[%d]:%s",self._curIndex,self._textures[self._curIndex].loc..".png"))
            if self._curIndex==#self._textures then
                self:finishLoading()
            end
            self._curIndex=self._curIndex+1
        end
    
    
        --加载Plist图片
        local function loadPlist(texture)
            frameCache:addSpriteFrames(self._textures[self._curIndex].loc..".plist")
            self._label:setString(string.format("Loading...%d%%",math.floor(100*self._curIndex/#self._textures)))
            cclog(string.format("loaded self.textures[%d]:%s",self._curIndex,self._textures[self._curIndex].loc..".png"))
            if self._curIndex==#self._textures then
                self:finishLoading()
            end
            self._curIndex=self._curIndex+1
        end
    
        local textureCache=cc.Director:getInstance():getTextureCache()
        for i=1,#self._textures do
            local rtype=self._textures[i].rtype
            if rtype=="png" then
                textureCache:addImageAsync(self._textures[i].loc..".png",loadPng)
            elseif rtype=="plist" then
                textureCache:addImageAsync(self._textures[i].loc..".png",loadPlist)
            end
        end
        self:unscheduleUpdate()
    end
    
    --loading UI
    BaseLoading.loadingUI=function(self)
        local label=cc.Label:createWithTTF("Loading...0%", "res/fonts/Marker Felt.ttf", 32)
        label:setPosition(self._size.width/2,self._size.height/4)
        self:addChild(label)
        self._label=label
    end
    
    
    BaseLoading.startLoading=function(self)
        self:registerScriptHandler(function(tag)
            if tag=="enter" then
                --设置定时器
                self:scheduleUpdateWithPriorityLua(function(dt)
                    self:loadTexture()
                end,0)
            elseif tag=="exit" then
                self:unscheduleUpdate()
            end
        end)
    end
    
    --完成异步加载图片回调函数
    BaseLoading.finishLoading=function(self)
    
    end
    
    return BaseLoading
    补充说明:
        异步加载plist纹理和png图片
        加载plist时,先加载plist对应的png图片,加载plist对应的png图片之后,在异步回调函数中,将plist载入textureCache中
     
     
  • 相关阅读:
    Unknown type '246 in column 3 of 5 in binary-encoded result set
    IOS开发常用的linux命令
    苹果开发中常用英语单词
    ios 中的UI控件学习总结(1)
    Srping MVC+mybatis mapping 多映射 配置
    IIS程序POST请求被触发两次的灵异事件
    文件服务器共享专用端口留档记录
    windows环境配置showdoc在线文档教程
    WindowsSever2008 R2 Standard 共享打印机手顺
    高效计算_七月算法5月深度学习班第2次课程笔记
  • 原文地址:https://www.cnblogs.com/luosongchao/p/4337933.html
Copyright © 2011-2022 走看看