Quick-Cocos2d-x v3.3 异步加载Spine方案 转
Quick-Cocos2d-x v3.3 异步加载Spine方案
浩月难求也与2015-03-25 15:06:3441 次阅读
背景
项目中使用了Quick-Cocos2d-x 3.3,由于Spine各个功能相当强大,所以使用了Spine作为骨骼动画,由于Spine并非cocos官方支持,所以在一些问题上支持性不是那么好,其中如何异步加载Spine就是一个问题。
比如游戏中经常遇到这么一个问题:在主战斗场景中,需要加载大量的图片、声音、Spine动画等,如果我们等到需要用到的时候再去加载,由于文件I/O是比较耗时的,有可能就会在游戏过程造成卡顿的现象,尤其在低端配置手机中体现尤为明显,这就会造成游戏体验不佳。
对于这个问题呢,一种比较常用的解决方案:在进入主战斗之前,就会预加载所有战斗中需要用到的资源,并且缓存起来,等到真到需要用到游戏资源的时候,直接去读取缓存中的数据,那就是我们经常看到的Loading条。
难点
1、异步加载
Cocos本身已经支持了一些资源的异步加载回调,使用多线程做的,每加载完一个资源,都可以有异步回调作相应的处理(比如显示加载进度)。但是 对于一些cocos官方不支持的资源,比如Spine等,就需要自己实现异步加载回调。
自己实现我知道有两种方法:
一种就是和cocos官方的一样,也用多线程做,这个没什么好说的。
一种就是叫做”同步异步化“,开启一个每帧都update函数,在update()里加载一次资源,用同步的方式实现异步加载的资源。
“同步异步化”在Lua中还有另一种方法可以实现,就是用Lua的协程,更加的方便。
我自己使用的是使用的update这种方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
function LoadingLayer:update(ts) - --- 每帧加载一次资源 local pngNum = table.nums(ResMng._pngList) local plistNum = table.nums(ResMng._plistList) local soundNum = table.nums(ResMng._soundList) local spineNum = table.nums(ResMng._spineList) local curLoadNum = ResMng._curLoadNum -- 加载资源顺序 -- 1、加载PNG if 0 <= curLoadNum and curLoadNum < pngNum then ResMng.loadPng() -- 2、加载PLIST elseif pngNum <= curLoadNum and curLoadNum < pngNum + plistNum then ResMng.loadPlist() -- 3、加载SOUND elseif pngNum + plistNum <= curLoadNum and curLoadNum < pngNum + plistNum + soundNum then ResMng.loadSound() -- 4、加载Spine elseif pngNum + plistNum + soundNum <= curLoadNum and curLoadNum < pngNum + plistNum + soundNum + spineNum then ResMng.loadSpine() else print( "所有资源预加载完成" ) ResMng.resortSpine() self:replaceScene() end end |
2、Spine缓存
Cocos官方都对一些常用的资源支持了缓存,如TextureCache、AnimationCache、SpirteFrameCache、AudioCache,但是由于Spine并非官方支持,所以对于Spine的缓存需要自己实现,对于Spine缓存实现方式,也有两种方法可以参考:
1、在C++层,实现一个和官方类似的缓存方案,叫做SpineCache,然后增加tolu层代码,这种方式优雅、自然,但是代价比较大。
2、在Lua层手动实现一个简易的缓存方案。
这里我当然是使用的第二种方案了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
-- 加载一次Spine图 function ResMng.loadSpine() local spineInfo = self._spineList[self._curLoadIndex] assert (spineInfo, "加载Spine索引出错" .. self._curLoadIndex) local spineAnimation = require( "app.common.factory.sp_animation" ). new () spineInfo.animation = spineAnimation:createWithID(spineInfo.id) spineInfo.animation:getNode():retain() self._curLoadNum = self._curLoadNum + 1 if self._curLoadIndex == #self._spineList then self._curLoadIndex = 1 else self._curLoadIndex = self._curLoadIndex + 1 end end -- 从缓存中获取Spine function ResMng.getSpineByID(spineID) -- 如果不存在此资源,先加载到缓存 if not self._spineList[spineID] then print( "缓存文件:" , spineID) local spineAnimation = require( "app.common.factory.sp_animation" ): new () self._spineList[spineID] = spineAnimation:createWithID(spineID) self._spineList[spineID]:getNode():retain() end local newSpine = require( "app.common.factory.sp_animation" ): new () return newSpine:createWithData(self._spineList[spineID]) end |
3、导出createWithData到Lua层调用
Spine Runtime,加载Spine有两种方式:
一个是createWithFile, 使用的是文件IO方式,这个相当耗时
一个是createWithData,使用的是已经加载好的Spine的骨骼数据,这种方法速度比较快。
但是Quick默认两个方法都不自动导出,都是用的手写代码导出,且只手动导出createWithFile, 如果我们需要使用createWithData,这时就需要手动导出了,导出代码如下:
LuaSkeletonAnimation.h
1
2
3
4
5
6
7
8
|
class LuaSkeletonAnimation: public spine::SkeletonAnimation { public : static LuaSkeletonAnimation* createWithFile ( const char * skeletonDataFile, const char * atlasFile, float scale = 1); static LuaSkeletonAnimation* createWithData(SkeletonAnimation* spineData); LuaSkeletonAnimation ( const char * skeletonDataFile, const char * atlasFile, float scale = 1); LuaSkeletonAnimation(SkeletonAnimation* spineData); virtual ~LuaSkeletonAnimation(); }; |
LuaSkeletonAnimation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
LuaSkeletonAnimation::LuaSkeletonAnimation ( const char * skeletonDataFile, const char * atlasFile, float scale) : spine::SkeletonAnimation(skeletonDataFile, atlasFile, scale) { } LuaSkeletonAnimation::LuaSkeletonAnimation(SkeletonAnimation* spineData) : spine::SkeletonAnimation(spineData) { } LuaSkeletonAnimation* LuaSkeletonAnimation::createWithFile ( const char * skeletonDataFile, const char * atlasFile, float scale) { LuaSkeletonAnimation* node = new (std:: nothrow ) LuaSkeletonAnimation(skeletonDataFile, atlasFile, scale); node->autorelease(); return node; } LuaSkeletonAnimation* LuaSkeletonAnimation::createWithData(SkeletonAnimation* spineData) { LuaSkeletonAnimation* node = new (std:: nothrow ) LuaSkeletonAnimation(spineData); node->autorelease(); return node; } |
lua_cocos2dx_spine_manual.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//add by chenhao on 2015/03/24 //手动添加Spine tolua代码,解决Spine缓存问题 static int lua_cocos2dx_CCSkeletonAnimation_createWithData(lua_State* L) { if (nullptr == L) return 0; int argc = 0; # if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; if (!tolua_isusertable(L, 1, "sp.SkeletonAnimation" , 0, &tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(L) - 1; if (1 == argc) { # if COCOS2D_DEBUG >= 1 if (!tolua_isusertable(L, 1, "sp.SkeletonAnimation" , 0, &tolua_err)) { goto tolua_lerror; } #endif SkeletonAnimation* spineData = (SkeletonAnimation*)tolua_tousertype(L, 2, 0); auto tolua_ret = LuaSkeletonAnimation::createWithData(spineData); int nID = (tolua_ret) ? ( int )tolua_ret->_ID : -1; int * pLuaID = (tolua_ret) ? &tolua_ret->_luaID : NULL; toluafix_pushusertype_ccobject(L, nID, pLuaID, ( void *)tolua_ret, "sp.SkeletonAnimation" ); return 1; } luaL_error(L, "'createWithFile' function of SkeletonAnimation has wrong number of arguments: %d, was expecting %d\n" , argc, 2); # if COCOS2D_DEBUG >= 1 tolua_lerror: tolua_error(L, "#ferror in function 'createWithData'." , &tolua_err); #endif return 0; } |
并且在extendCCSkeletonAnimation()中,添加下面这行代码。
1
|
tolua_function(L, "createWithData" , lua_cocos2dx_CCSkeletonAnimation_createWithData); |
为了减少导出自定义类, 我对C++层createWithData的参数类型作了一些修改,但是不影响。改为了:
1
|
static SkeletonAnimation* createWithData(SkeletonAnimation* spineData); |
以上都是本人自己实现摸索过程中, 探索出来的一些方法,有什么问题大家可以提出来,我好修改
Quick-Cocos2d-x v3.3 异步加载Spine方案 转的更多相关文章
- 请给出异步加载js方案
请给出异步加载js方案,不少于两种 默认情况javascript是同步加载的,也就是javascript的加载时阻塞的,后面的元素要等待javascript加载完毕后才能进行再加载,对于一些意义不是很 ...
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->新增“行政区域管理”,同时大批量树采用异步加载
行政区划:简称政区,是国家为了进行分级管理而实行的区域划分.中国现行的行政区划实行如下原则:1.全国分为省.自治区.直辖市:2.省.自治区分为自治州.县.自治县.市:3.自治州分为县.自治县.市:4. ...
- 【Cocos2d-Js基础教学(5)资源打包工具的使用及资源的异步加载处理】
TexturePacker是纹理资源打包工具,支持Cocos2dx的游戏资源打包. 如果用过的同学可以直接看下面的资源的异步加载处理 首先为什么用TexturePacker? 1,节省图片资源实际大小 ...
- python(4) 小程序-异步加载
注:处理异步加载需要模拟浏览器登陆,然后用import json,用loads解析 例如:
- Jquery zTree结合Asp.net实现异步加载数据
zTree结合Asp.net实现异步加载数据 实现简单操作 zTree 下载 api 访问 :http://www.ztree.me/v3/main.php 例子中用到json数据转化 newtons ...
- 【转】【玩转cocos2d-x之二十三】多线程和同步03-图片异步加载
原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/15334159 cocos2d-x中和Android,Windows都 一样, ...
- cocos2dx lua中异步加载网络图片,可用于显示微信头像
最近在做一个棋牌项目,脚本语言用的lua,登录需要使用微信登录,用户头像用微信账户的头像,微信接口返回的头像是一个url,那么遇到的一个问题就是如何在lua中异步加载这个头像,先在引擎源码里找了下可能 ...
- ztree异步加载树节点
参考文档:https://www.cnblogs.com/tenWood/p/8620708.html ztree api地址:http://www.treejs.cn/v3/api.php 说明:j ...
- ztree插件的使用及列表项拖拽的实现(jQuery)+异步加载节点数据
为了实现如图所示的树状结构图,并使列表项可拖动到盒子里,研究了ztree这个插件的使用,并仔细研究了列表项的拖动事件.完成了预期需求,对jQuery的运用得到了提高.这个插件的功能非常强大,除了基本的 ...
随机推荐
- Backup: Array in Perl6
Array in Perl6 继承List,而List又继承Iterable,Positional,Cool ARRAY.pop ARRAY.shift ARRAY.push: VALUES ARRA ...
- Calendar的问题
1. include file is not work now. remove <!-- #include file="Calendar.js" -->, add &l ...
- <mvc:annotation-driven />与<context:annotation-config />
Spring家族的配置中这两个配置的意义,说具体点其实根据标签的shecma就能看出来,mvc,主要就是为了Spring MVC来用的,提供Controller请求转发,json自动转换等功能,而co ...
- 将helps.php或者functions.php直接进行了加载
TP3系列中functions.php文件默认其实是空文件,很好找.我们可以直接封装代码. Laravel5系列中的path/vendor/laravel/framework/src/Illumina ...
- js实现通用的微信分享组件示例
一.可定义的信息 1.分享时显示的LOGO:2.分享LOGO的宽度:3.分享LOGO的高度:4.分享出去显示的标题(默认调用网页标题):5.分享出去显示的描述(默认调用网页标题):6.分享链接(默认为 ...
- [HTML][服务器]状态码列表status
AJAX中请求远端文件.或在检测远端文件是否掉链时,都需要了解到远端服务器反馈的状态以确定文件的存在与否. 当然,在我们平常浏览网页时,也会发现一些文件不存在时显示为“404错误”,这就是常见的Htt ...
- javascript对象(2)
Number对象 创建方法 var myNum=new Number(value); //返回一个新创建的Number对象var myNum=Number(value); //把Number()作为一 ...
- Cocos2dx-lua开发之c++绑定到lua
一. 简单介绍 文章介绍是在实际的游戏开发项目中,将自定义的C++类绑定到lua中,能够让lua调用c++类.会创建一个python脚本,执行python脚本会让自动将我们的c++类绑定到lua.生成 ...
- SQL Server 索引和表体系结构(三)
转自:http://www.cnblogs.com/chenmh/p/3785285.html 包含列索引 概述 包含列索引也是非聚集索引,索引结构跟聚集索引结构是一样,有一点不同的地方就是包含列索引 ...
- 使用VisualSVN建立SVN Server
首先去官网下载安装包.http://subversion.apache.org/packages.html找到windows的,选择VisualSVN->VISUALSVN SERVER 双击开 ...