TexturePacker是纹理资源打包工具,支持Cocos2dx的游戏资源打包。
如果用过的同学可以直接看下面的资源的异步加载处理
首先为什么用TexturePacker?
1,节省图片资源实际大小
2,减少我们游戏中大量资源带来的内存负荷
3,方便游戏对纹理资源的内存管理
游戏开发到后期,我们或许都会遇到的瓶颈就是需要对游戏包进行“瘦身”和内存优化。那么使用TexturePacker
就能达到我们的目的;
我们以一组技能特效图片来举例,进行TexturePacker的图片打包,然后在程序中使用:
我们对这些文件进行打包成一张大图.png和cocos2dx-JS中会使用到的.plist文件
打包注意一下几点:
1,文件格式,选择cocos2d
2,设置导出文件的plist和png路径
3,图片格式,一般使用RGBA8888,但根据平台需求现在也可以导出Pvr格式图片类型;
使用:1)Textuer Format 选择Pvr图片类型 2)Image Format 选择 PVRCT4 这种类型的;
可大大节省图片的大小!
4,每张大图的png尺寸一定不能大于2048*2048!因为目前比较低端的android手机是不支持加载这么大的图片的!
所以我们的游戏要被大部分机型适配,那就最好不要用太大的图片包
OK。我们打包完成后将文件拷贝到我们的Gofinght目录中,继续我们上一节知识点开始写我们这节知识点的代码:
我们需要实现图片资源的加载!这个是我们的目的。
那么我们就需要书写一个GameFrameCache.js的类,来单独处理我们的图片资源加载;
GameFrameCache.js:
/**
* Created by yangshengjiepro on 15/5/11.
*/
/**
* 游戏资源加载处理
*/
var GameFrameCache = function () {
this.flag = 0;
}
var LOADINGBARPROALLNUM=0;
//异步加载
GameFrameCache.setAllCache = function (obj,objcallback) {
//异步加载所有游戏资源
var texCache = cc.textureCache;
//遍历所有的资源
var reslist = res;
var allnum = 0;
for (var key = 0 in reslist) {
Mlog.c("reslist key"+key+"value:"+reslist[key]);
allnum++;
}
LOADINGBARPROALLNUM = allnum;
Mlog.c("LOADINGBARPROALLNUM>>",LOADINGBARPROALLNUM);
var readnum = 0;
for (var key = 0 in reslist) {
//开始装载
texCache.addImageAsync(reslist[key], objcallback, obj);
}
};
//资源加载
GameFrameCache.setCache = function (plist) {
if (jsb.fileUtils.isFileExist(plist) == true) {
cc.SpriteFrameCache.getInstance().addSpriteFrames(plist);
}
else
{
Mlog.c("No Add File>>",plist);
}
};
//获取Frame
GameFrameCache.getCache = function (name) {
var frame;
frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(name);
return frame;
};
//移除Plist
GameFrameCache.removeCache = function(plist){
if (jsb.fileUtils.isFileExist(plist) == true) {
cc.SpriteFrameCache.getInstance().removeSpriteFramesFromFile(plist);
}
}
代码中有三个方法:
GameFrameCache.setCache
GameFrameCache.getCache
GameFrameCache.removeCache
顾名思义就是,添加,获取,和删除
添加一张大图资源方法:
cc.SpriteFrameCache.getInstance().addSpriteFrames(plist);
我们知道SpriteFrameCache可以帮我们预加载plist图片,并且能大大提高我们游戏对图片的渲染效率
所以我们尽可能的使用这样的方式去做图片的渲染,而且我们能更方便的,在合适的地方去添加,获取,删除;
从而达到我们内存资源最佳管理的方式!就不会导致我们因为加载过多图片导致程序效率缓慢甚至卡死的情况!
那么下面我们来使用SpriteFrameCache这个类,我们需要在我们上一节课中的基类中添加一个方法
setGameFrameCache:function(plistfile){
GameFrameCache.setCache(plistfile);
},
很简单,就是调用我们GameFrameCache的set方法!
在我们MainLayer中添加调用方法,直接:
this.setGameFrameCache("plist文件路径");
就能调用到我们基类的加载大图方法!
然后我们来尝试调用一下我们的大图纹理使用,我们新建一个PFuns.js动作类来播放我们的技能特效!
PFun.js
/**
* Created by yangshengjiepro on 15/5/11.
*/
var PFuns = function () {
this.flag = 0;
}
//执行某个特效
PFuns.runEFFAttack_SP = function (sp , Url , name , num, speed , loop , delay , zorder , scale , tag , cp) {
var sprite = sp;
var sp_eff = new cc.Sprite();
var animation = new cc.Animation();
for (var i = 1; i <= num; i++) {
var toi="";
if(i<10)
{
toi = "0"+i;
}
else
{
toi = i;
}
var frameName = Url + "/" + name + toi + ".png";
Mlog.c("frameName>>"+frameName);
var frame =GameFrameCache.getCache(frameName);
if(frame!=null) {
Mlog.c("frameName>ok>>"+frameName);
animation.addSpriteFrame(frame);
}
}
var usetime =1 / parseInt(speed);
animation.setDelayPerUnit(usetime);
animation.setRestoreOriginalFrame(true);
animation.setLoops(loop);
var action = cc.animate(animation);
var actdelay2 = cc.DelayTime.create(delay);
if(delay>0)
{
sp_eff.runAction(cc.Sequence(actdelay2,action,cc.callFunc(PFuns.effremove, sp_eff)));
}
else
{
sp_eff.runAction(cc.Sequence(action,cc.callFunc(PFuns.effremove, sp_eff)));
}
if(cp!=null)
{
sp_eff.setPosition(cc.p(cp.x,cp.y));
}
else
{
sp_eff.setPosition(cc.p(sprite.getContentSize().width/2,sprite.getContentSize().height/2));
}
sp_eff.setScale(scale);
sprite.addChild(sp_eff,zorder,tag);
};
//移除
PFuns.effremove = function () {
this.removeFromParent();
};
我们使用帧动画的方式来进行技能特效的播放,帧动画的每帧的Frame获取方式使用:
var frame =GameFrameCache.getCache(frameName);
OK,我们可以Run起来看一下效果:
我们的技能帧动画已经非常漂亮的渲染出来了!看起来非常不错!那么这个小知识点就完了!
好,那么下面我们来讲解一下我们所有图片的异步加载!我们知道在Cocos2dx中提供了textureCache来
帮助我们实现图片资源文件的管理,和使用。
试想我们是需要使用图片时临时加载图片快,还是先通过一个Loading界面将资源加载完毕后,在从textureCache中
取出来快呢?
答案当然是后者!
那么我们现在来进行LoadIng异步加载的实现方式,GameFrameCache.js类中有
GameFrameCache.setAllCache
这样一个方法,通过遍历我们的res目录中所有的png文件来获取文件路径,并且加载所有的图片;
这里要注意一下:res这个数组中只能填写png,jpg等图片文件类型
可以这样来写我们的各种文件路径。
接下来我们就来实现一个进度条的实现来异步加载我们的所有程序资源,在MainLayer中添加两个方法:
//加载进度条
initloadingbar:function(sp_loading){
//加载Loading条
var sp_loadingtiao = new cc.Sprite(res.UILOADINGBD_png);
sp_loadingtiao.attr({
x: sp_loading.getContentSize().width/2,
y: sp_loading.getContentSize().height/2-180,
scale: 1,
rotation: 0
});
sp_loading.addChild(sp_loadingtiao,1);
var loadingBar = new ccui.LoadingBar(res.UILOADINGBAR_png);
loadingBar.x = sp_loading.getContentSize().width/2;
loadingBar.y = sp_loading.getContentSize().height/2-180;
sp_loading.addChild(loadingBar,2,LOADINGBAR_TAG);
loadingBar.setPercent(0);
},
//资源loadding buffer进度回调
setloadingbar:function(){
var pernum = parseInt(LOADINGBARPRONUM/LOADINGBARPROALLNUM *100);
Mlog.c("pernum >>" +pernum);
LOADINGBARPRONUM++;
var loadingBar = this.getChildByTag(LOADINGBAR_TAG);
if(loadingBar!=null)
{
loadingBar.setPercent(pernum);
}
//进度条加载完毕进行跳转
if(pernum==100)
{
//加载完毕
Mlog.c("异步加载资源完毕");
PFuns.runEFFAttack_SP(this , "skill_dianjin" , "000" , 13, 6 , 3 ,1 , 11111 , 1 ,1000 , null);
}
},
setloadingbar这个方法是我们的回调;在GameFrameCache会使用addImageAsync方法来进行资源加载成功的回调!
并且获取两个值:
var LOADINGBARPRONUM = 1;
var LOADINGBARPROALLNUM=0;
和LOADINGBARPROALLNUM来进行进度条的计算和更新;
最后进度条的比例为100时,那么播放我们的技能动画:
texCache.addImageAsync(reslist[key], objcallback, obj);
在构造函数尾部,直接加上调用方法:
//加载进度条调用
this.initloadingbar(this);
//异步加载所有资源调用
GameFrameCache.setAllCache(this,this.setloadingbar);
这样就实现了我们整个项目的图片资源的异步加载
我们可以跑起来看看效果!
好了,本章知识点在我们游戏开发中是非常的常用,也是非常重要的!所以我觉得会对大家一定有帮助!
本节知识点源码:
自己创建新工程,解压下载的文件,将所有文件拷贝到你新工程的目录下全部覆盖既可以运行!