一、说明

    异步加载就是把消耗程序时间比较大的加载操作放到其他线程中,待加载完毕后通过回调函数的方式通知主线程。
 
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. OpenCV学习:播放avi视频文件

    #if 0 //播放avi视频文件(IplImage) #include <opencv2/opencv.hpp> using namespace std; #pragma comment ...

  2. mysqlbinlog工具的作用是什么呢,如何将binary log转换为文本格式?

    需求描述: 今天在看mysqlbinlog这个工具,就在想这个工具到底是干嘛的呢,在mysql数据库中, binary log中记录了数据库内容的变化或者说修改,这些修改是以二进制的方式存储到 bin ...

  3. 编译ros程序包--4

    编译程序包(原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/) 1.编译程序包: 一旦安装了所需的系统依赖项,我们就可以开始编译刚才创建的程序包了 ...

  4. quick-cocos2d-x游戏开发【10】——触摸捕获事件 cc.NODE_TOUCH_CAPTURE_EVENT

    假设看过sample中touch的代码,你会发现演示样例中有一个cc.NODE_TOUCH_CAPTURE_EVENT事件.它和cc.NODE_TOUCH_EVENT触摸事件一样,是引擎级别的事件,我 ...

  5. laravel 强大的关联模型

    内容比较多,不总结了,直接看学院君的译文吧,已经写得很详细了 传送门:http://laravelacademy.org/post/6191.html PS1: laravel的关联模型并不是遍历一次 ...

  6. 【python】一次执行多个linux命令

    方法:多个命令之间用“;”进行连接即可:

  7. 《C++ Primer Plus》12.7 队列模拟 学习笔记

    Heather银行打算在Food Heap超市开设一个自动柜员机(ATM).Food Heap超市的管理者担心排队使用ATM的人流会干扰超市的交通,希望限制排队等待的人数.Heather银行希望对顾客 ...

  8. 百度地图api添加自定义控件

    官网栗子:http://lbsyun.baidu.com/jsdemo.htm#b0_6 <!DOCTYPE html><html><head> <meta ...

  9. 【git】------git的基本命令------【巷子】

    001.初始化仓库,创建git仓库 git init 002.配置个人信息 git config --global user.name <名字> --------->:配置用户名 g ...

  10. Redis的简单了解以及主从复制

    1.Redis的简单了解 Redis是一种高性能的分布式NoSql数据库,持久存储,高并发,数据类型丰富,通过现场申请内存空间,同时可以配置虚拟内存.五种数据类型:string(字符串,这种格式和me ...