cocos html5只有一个文件,Cocos2d-html5 plist优化 & plist文件加载解析

目前h5引擎正在处于研究阶段,基于Cocos2d-html5封装一个TS版的引擎库。

前言

之前在封装UI及Scene这块的内容,UI部分涉及到加载素材,也了解到cocos可以直接使用TexturePacker合成后的plist文件及png。但是对于H5的项目来说,减少网络请求是很重要的一步,特别是在页面初始化加载的时候。这时候在官网看到如下内容:cc.spriteFrameCache 改造说明

通俗来说,就是在知道SpriteFrame的数据结构之后,提前将plist文件的解析(这样可以做到将多个plist文件集合到一个文件中,减少加载次数)。官网有一个做法:

提取n个plist文件至一个xx.pkgJson文件中,文件加载完毕后,使用自定义的_pkgJsonLoader对文件内容再次处理

我在按照此方法的处理过程中,发现_pkgJsonLoader中对数据结构处理的很少,只是做了数据提取部分。所以个人觉得在生成.pkgJson文件时,就可以直接按照SpriteFrame数据结构来生成数据,没有必要经过两次处理。以下是官网提供的思路:

// SpriteFrame数据结构

{

_inited : true,

frames : {

"a_frame_0.png" : {

rect : {x : 0, y : 0, width : 1, height : 1},

rotated : false,

offset : {x : 0, y : 0},

size : {width : 1, height : 1}

aliases : ["a_f_0"]

}

},

meta : {

image : "a.png"

}

}

// pkgJsonLoader核心代码

cc._pkgJsonLoader = {

/**

* @constant

*/

_parse : function(data){

var KEY = data instanceof Array ? this.MIN_KEY : this.KEY;

var frames = {}, meta = data[KEY.meta] ? {image : data[KEY.meta][KEY.image]} : {};

var tempFrames = data[KEY.frames];

for (var frameName in tempFrames) {

var f = tempFrames[frameName];

var rect = f[KEY.rect];

var size = f[KEY.size];

var offset = f[KEY.offset];

frames[frameName] = {

rect : {x : rect[0], y : rect[1], width : rect[2], height : rect[3]},

size : {width : size[0], height : size[1]},

offset : {x : offset[0], y : offset[1]},

rotated : f[KEY.rotated],

aliases : f[KEY.aliases]

}

}

return {_inited : true, frames : frames, meta : meta};

},

load : function(realUrl, url, res, cb){

var self = this, locLoader = cc.loader, cache = locLoader.cache;

locLoader.loadJson(realUrl, function(err, pkg){

if(err) return cb(err);

var dir = cc.path.dirname(url);

for (var key in pkg) {

var filePath = cc.path.join(dir, key);

cache[filePath] = self._parse(pkg[key]);

}

cb(null, true);

});

}

};

上面说了那么多,首先需要解决的是plist数据解析的工具,可惜在官网上只提供了解析后的数据结构,没有解析工具。为此我在中文论坛及其它相关论坛都问了一遍,但是没有得到满意的答复。所以,决定自己造个轮子。我在npm上找到了plist包,试用了之后,发现plist可以将plist文件的数据提取出来,数据结构如下:

{

"frames": {

"0.png": {

"aliases": [

],

"spriteOffset": "{0,0}",

"spriteSize": "{64,49}",

"spriteSourceSize": "{64,49}",

"textureRect": "{{1,55},{64,49}}",

"textureRotated": false

},

"1.png": {

"aliases": [

],

"spriteOffset": "{0,0}",

"spriteSize": "{67,52}",

"spriteSourceSize": "{67,52}",

"textureRect": "{{1,1},{67,52}}",

"textureRotated": false

}

},

"metadata": {

"format": 3,

"pixelFormat": "RGBA8888",

"premultiplyAlpha": false,

"realTextureFileName": "radio.png",

"size": "{69,105}",

"smartupdate": "$TexturePacker:SmartUpdate:305947cb63527c2d3a81c456831d3508:0ffe9fa733c7901a53ebea001548ed6d:eed519fbbdd46973eb5ec3b717bd80b1$",

"textureFileName": "radio.png"

}

}

其实,到了这一步,我要做的东西就很简单了。基于plist转换后的结构,提取出SprimeFrame需要的数据即可。提取结果:

{

"_inited": true,

"frames": {

"0.png": {

"rect": {

"x": 1,

"y": 55,

"width": 64,

"height": 49

},

"rotated": false,

"offset": {

"x": 0,

"y": 0

},

"size": {

"width": 64,

"height": 49

},

"aliases": [

]

},

"1.png": {

"rect": {

"x": 1,

"y": 1,

"width": 67,

"height": 52

},

"rotated": false,

"offset": {

"x": 0,

"y": 0

},

"size": {

"width": 67,

"height": 52

},

"aliases": [

]

}

},

"meta": {

"image": "radio.png"

}

}

配合自定义的cc._pkgJsonLoader:

cc._pkgJsonLoader = {

load: function (realUrl, url, res, cb) {

var self = this, locLoader = cc.loader, cache = locLoader.cache;

locLoader.loadJson(realUrl, function (err, pkg) {

if (err) return cb(err);

var dir = cc.path.dirname(url);

for (var key in pkg) {

var filePath = cc.path.join(dir, key);

cache[filePath] = pkg[key];

}

cb(null, true);

});

}

};

cc.loader.register(["pkgJson"], cc._pkgJsonLoader);

问题解析

可能不了解的人会有疑问,为什么要处理plist,有什么优点呢?

其实之前提到过一部分,在此重点再说一次:

减少网络请求——原先游戏在启动时,要将plist文件全部加载完成(不清楚到底有多少个),现在讲n个plist集成到一个.pkgJson文件中,一次网络请求即可

避免解析数据——原有的plist文件加载完成后,底层还需要再次解析,而现在,.pkgJson中的内容就是直接可用的

cocos加载png plist时发生了什么

这部分是在和同事交流时发现一位使用了cocos很久的开发,对此过程中到底发生了什么也不太了解。

png(其它图片资源也是同样的情况)

发起加载png资源的请求

cc.loader.cache缓存对应数据

cc.textureCache._textures缓存对应数据

plist

发起加载plist资源的请求

cc.loader.cache缓存对应数据

此时,cc.loader.cache存储的还是xml中的内容:

当我们使用如下命令是:cc.spriteFrameCache.addSpriteFrames("xx.plist");

获取plist对应的内容

未初始化:解析数据,解析完数据后添加:"_inited": true属性,标记解析完成

已初始化:直接使用数据

从plist对应的图片资源中加载资源(这个时候使用cc.textureCache._textures,如果没有数据,会发起一次网络请求)

将spriteFrame存储至_spriteFrames;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值