COCOS2D-HTML5 PLIST Optimization & PLIST File Load Analysis

The h5 engine is currently in the research phase, and a TS version of the engine library is packaged based on Cocos2d-html5.

Foreword

In the past, we encapsulated the content of UI and Scene. The UI part involved loading materials. We also learned that cocos can directly use the plist file and png synthesized by TexturePacker. But for the H5 project, reducing network requests is a very important step, especially when the page is initially loaded. At this time, I saw the following content on the official website: cc.spriteFrameCache Transformation Instructions
In layman’s terms, it means to parse the plist file in advance after knowing the data structure of SpriteFrame (in this way, multiple plist files can be collected into one file. In, reduce the number of loading). There is a way on the official website:

  • Extract n plist files to a xx.pkgJson file, after the file is loaded, use the custom _pkgJsonLoader to process the file content again
  • ul>

    In the process of processing according to this method, I found that _pkgJsonLoader does very little to deal with the data structure, only the data extraction part. So I personally feel that when generating a .pkgJson file, you can directly generate data according to the SpriteFrame data structure, and there is no need to go through two processes. The following is the idea provided by the official website:

    // SpriteFrame data structure
    {
    _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 core code
    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 of fset = 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]},< br /> 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

    As mentioned above, the first thing that needs to be solved is the plist data parsing tool, but unfortunately only the parsing tool is provided on the official website There is no analytical tool for the data structure. For this reason, I asked it in the Chinese forum and other related forums, but did not get a satisfactory answer. So, I decided to build a wheel myself. I found the plist package on npm. After trying it out, I found that plist can extract the data of the plist file. The data structure is as follows:

    {
    "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 }",
    "smar tupdate": "$TexturePacker:SmartUpdate:305947cb63527c2d3a81c456831d3508:0ffe9fa733c7901a53ebea001548ed6d:eed519fbbdd46973eb5ec3b717bd80b1$",
    "textureFileName": "radio.png>"
    , actually, it’s

    In this step, what I have to do is very simple. Based on the converted structure of plist, extract the data needed by SprimeFrame. Extraction result:

    {
    "_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"
    }
    }

    With custom 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);

    Problem analysis

    People who may not understand will have questions. Why do we need to deal with plist and what are the advantages?

    In fact, I mentioned a part before, but I will focus on it again:

    • Reduce network requests-when the original game starts, all plist files must be loaded (not Know how many there are), now let’s talk about integrating n plists into a .pkgJson file, one network request can be done
    • Avoid parsing data-after the original plist file is loaded, the bottom layer needs to be re-loaded Parsing, and now, the content in .pkgJson is directly usable

    What happened when cocos loaded the png plist

    This part was discovered when communicating with colleagues I have used cocos for a long time in the development, and I don’t know exactly what happened in the process.

    png (the same is true for other image resources)

    • Initiate a request to load png resources
    • cc.loader.cache caches corresponding data

      li>

    • cc.textureCache._textures caches corresponding data

    plist

    • Initiate a request to load plist resources
    • cc. loader.cache caches the corresponding data

    At this time, cc.loader.cache stores the content in xml:
    When we use the following command: cc.spriteFrameCache. addSpriteFrames("xx.plist");

    • Get the content corresponding to plist

      • Uninitialized: parse the data, parse the data After adding: "_inited": true attribute, mark parsing is complete
      • Initialized: use data directly
    • from plist Load resources in the corresponding image resources (this time use cc.textureCache._textures, if there is no data, a network request will be initiated)
    • Store spriteFrame in _spriteFrames;

    < /p>

Leave a Comment

Your email address will not be published.