Cocos2d-html5 plist优化 & plist文件加载解析

前端之家收集整理的这篇文章主要介绍了Cocos2d-html5 plist优化 & plist文件加载解析前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
目前h5引擎正在处于研究阶段,基于Cocos2d-html5封装一个TS版的引擎库。

前言

之前在封装UI及Scene这块的内容,UI部分涉及到加载素材,也了解到cocos可以直接使用TexturePacker合成后的plist文件及png。但是对于H5的项目来说,减少网络请求是很重要的一步,特别是在页面初始化加载的时候。这时候在官网看到如下内容cc.spriteFrameCache 改造说明
通俗来说,就是在知道SpriteFrame的数据结构之后,提前将plist文件的解析(这样可以做到将多个plist文件集合到一个文件中,减少加载次数)。官网有一个做法:

我在按照此方法的处理过程中,发现_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);
        });
    }
};

cocos-pkgjson

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

{
    "frames": {
        "0.png": {
            "aliases": [
                
            ],"spriteOffset": "{0,0}","spriteSize": "{64,49}","spriteSourceSize": "{64,"textureRect": "{{1,55},{64,49}}","textureRotated": false
        },"1.png": {
            "aliases": [
                
            ],"spriteSize": "{67,52}","spriteSourceSize": "{67,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,"aliases": [
                
            ]
        },"1.png": {
            "rect": {
                "x": 1,"y": 1,"width": 67,"height": 52
            },"size": {
                "width": 67,"aliases": [
                
            ]
        }
    },"Meta": {
        "image": "radio.png"
    }
}

配合自定义的cc._pkgJsonLoader:

cc._pkgJsonLoader = {
    load: function (realUrl,cb) {
        var self = this,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;

猜你在找的Cocos2d-x相关文章