一、说明

    异步加载就是把消耗程序时间比较大的加载操作放到其他线程中,待加载完毕后通过回调函数的方式通知主线程。
 
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. 电脑开机提示 NTLDR is missing

    电脑开机,黑屏并提示NTLDR is missing Press Ctrl+Alt+Del to restart,并且反复重启都不行,这是怎么回事呢?首先我们来分析下这段英语的含义:NTLDR是指NT ...

  2. 【ExtJs】 ExtJs4.2 基本表单组件的使用

    包含ExtJs 基本的组件radioGroup,ComboBox,File,NumberField... <%-- Created by IntelliJ IDEA. User: Adminis ...

  3. laravel安装 redis 并驱动 session

    1)composer 安装 redis composer require predis/predis 如果感兴趣,可以看一下这里 2)配置 redis 连接(config/database.php 配 ...

  4. Python 入门(五)条件判断和循环

    if语句 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,可以用if语句实现: age = 20 if age > ...

  5. Navicat无法启动,提示无法启动程序,因为计算机中丢失MSVCP140.dll

    .dll是一个动态链接库文件,Dynamic Link Library,是代码的封装,提供某种功能,可以被需要该功能的多个应用调用,提高代码的复用性 解决方法,下载并安装微软VC++2015版运行库 ...

  6. NUC131的系统管理

    系统复位系统复位可以由如下的任何一种中断实现,这些复位中断标志可以通过寄存器RSTSRC读取. 上电复位 nRESET引脚低电平复位 看门狗复位 低压复位 欠压检测器复位 CPU 复位 ...

  7. js正则函数match、exec、test、search、replace、split使用介绍集合,学习正则表达式的朋友可以参考下。

    match 方法 使用正则表达式模式对字符串执行查找,并将包含查找的结果作为数组返回. stringObj.match(rgExp) 参数 stringObj 必选项.对其进行查找的 String 对 ...

  8. [020]Sencha Ext JS 6.0使用教程2

    本节主要以典型例子介绍如何用Sencha Ext JS6.0进行项目开发 入门阶段总是比较难的,掌握了基本操作步骤,使用方法,架构思维,开发起来还是满顺利,开心的,自己又能掌握一门新技术,又能进步,主 ...

  9. Sencha Cmd创建Ext JS示例项目

    Sencha提供了免费的Cmd工具,可以用来创建Ext JS项目并提供了一些便利的功能. Sencha也在官方文档中提供了一个示例来演示如何创建一个Sample Login App. 本文就介绍一下这 ...

  10. 腾讯正式开源高性能超轻量级 PHP 框架 Biny

    概况 Biny是一款高性能的超轻量级PHP框架 遵循 MVC 模式,用于快速开发现代 Web 应用程序 Biny代码简洁优雅,对应用层,数据层,模板渲染层的封装简单易懂,能够快速上手使用 高性能,框架 ...