在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一、说明 异步加载就是把消耗程序时间比较大的加载操作放到其他线程中,待加载完毕后通过回调函数的方式通知主线程。
addImageAsync函数实现(Cocos2dx 3.3)
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
--图片异步加载 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:
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中
|
请发表评论