一、说明

    异步加载就是把消耗程序时间比较大的加载操作放到其他线程中,待加载完毕后通过回调函数的方式通知主线程。
 
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 ( == _asyncRefCount)
{
Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(TextureCache::addImageAsyncCallBack), this, , 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= --当前loaded的图片编号 self:registerScriptHandler(function(tag)
if tag=="enter" then
--设置定时器
self:scheduleUpdateWithPriorityLua(function(dt)
self:loadTexture()
end,)
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", )
label:setPosition(self.size.width/,self.size.height/)
self:addChild(label)
self.label=label
end --初始化图片集
ImageAsync.initTexture=function(self)
self.textures={}
for i=, do
for j=, 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/,self.size.height/))
sprite:setScale()
self:addChild(sprite)
self.curIndex=self.curIndex+
self.label:setString(string.format("Loading...%d%%",math.floor(*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=,#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() == )
{
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 ();
} 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= --当前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(*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+
end --加载Plist图片
local function loadPlist(texture)
frameCache:addSpriteFrames(self._textures[self._curIndex].loc..".plist")
self._label:setString(string.format("Loading...%d%%",math.floor(*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+
end local textureCache=cc.Director:getInstance():getTextureCache()
for i=,#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", )
label:setPosition(self._size.width/,self._size.height/)
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,)
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中
 
 

【Cocos2dx3.x Lua】图片异步加载的更多相关文章

  1. cocos2dx lua中异步加载网络图片,可用于显示微信头像

    最近在做一个棋牌项目,脚本语言用的lua,登录需要使用微信登录,用户头像用微信账户的头像,微信接口返回的头像是一个url,那么遇到的一个问题就是如何在lua中异步加载这个头像,先在引擎源码里找了下可能 ...

  2. Android-Universal-Image-Loader 图片异步加载类库的使用

    在博客中看到一篇利用组件进行图片异步加载的文章在此作记录 原文:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载并缓存的 ...

  3. Android图片异步加载框架Android-Universal-Image-Loader

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个 ...

  4. Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)

    这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚 ...

  5. Android ListView 图片异步加载和图片内存缓存

    开发Android应用经常需要处理图片的加载问题.因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载.为了增加用户体验,给用 ...

  6. Android 图片异步加载的体会,SoftReference已经不再适用

      在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>>  这样软引用的 ...

  7. 【转】Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)

    Android-Universal-Image-Loader 原文地址:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载 ...

  8. Android图片异步加载之Android-Universal-Image-Loader

    将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...

  9. Android图片异步加载之Android-Universal-Image-Loader(转)

    今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决 ...

随机推荐

  1. remove()

    remove() 用于从列表中删除指定的元素 In [35]: l = ['a', 'b', 'c'] In [36]: l.remove('b') In [37]: l Out[37]: ['a', ...

  2. VS添加命令行参数main(int argc, char** argv)

  3. cocos2d-x游戏引擎核心之四——动作调度机制

    一.动作机制的用法 在深入学习动作机制在 Cocos2d-x 里是如何实现的之前,我们先来学习整套动作机制的用法,先知道怎么用,再深入学习它如何实现,是一个很好很重要的学习方法. (1)基本概念 CC ...

  4. 使用NSTimer实现动画

    1.新建empty AppLication,添加HomeViewController页面, iphone.png图片 2.在 HomeViewController.xib中添加Image View,并 ...

  5. android基础组件---->Checkboxe的使用

    由于使用比较简单,这篇博客涵盖Checkboxes和Radio Buttons和Toggle Buttons.好了我们开始今天的学习.我被世俗隐瞒,转身又被自己撞倒.从莫须有的罪名起步,行色简单,心术 ...

  6. PostgreSQL远程代码执行漏洞(CVE-2018-1058)学习笔记

    零.参考文献和绪论: 1.先知社区chybeta大神的--PostgreSQL 远程代码执行漏洞分析及利用—[CVE-2018-1058]--一文 2.博客园hunchill的--Mac 下 Post ...

  7. 【BZOJ4372】烁烁的游戏 动态树分治+线段树

    [BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距 ...

  8. go练习5--生成md5

    import "crypto/md5" import "encoding/hex" //go 生成 md5 func T4_1() { m := md5.New ...

  9. stm32的VCC/VDD/VSS/VEE/VBAT的区别

    先看一下stm32vet6的引脚图吧 电路设计以及PCB制作中,经常碰见电源符号:VCC. VDD.VEE.VSS,他们具有什么样的关系那? 一.解释 VCC:C=circuit 表示电路的意思, 即 ...

  10. Eclipse中将Java项目转换成Web项目的方法(转)

    前言: 用Eclipse开发项目的时候,把一个Web项目导入到Eclipse里会变成了一个java工程,将无法在Tomcat中进行部署运行. 方法: 1.找到.project文件,找到里面的<n ...