cocos creator 2.1.2
查阅代码目录:[cocos creator 2.1.2项目目录]\resources\engine
\cocos2d\core\load-pipeline\text-loader.js
\cocos2d\core\load-pipeline\binary-loader.js
\resources\builtin\weapp-adapter\wx-downloader.js
\resources\builtin\weapp-adapter\wx-fs-utils.js
等等
1. 游戏是关卡类型的
2. 关卡全部使用预制件的形式制作
3. 关卡打包的时候生成的json文件过大
4. 需要对这些文件进行压缩
1. 在cocos creator中加载的大题流程是
a. download
b. loader
大概这样的形式,那么只要替换调加载的函数就可以了
2. 在download中替换相应的函数
例如: web直接替换loadJson函数
大概:cc.loader.addDownloadHandlers({"json":funcJsonGz});
cc.loader.addDownloadHandlers({"gz":funcJsonGz});
wx大需要修改wx-downloader.js中
readFile函数
内容大概是:
a. 判断后缀是否json文件
b. 使用binary加载
c. 判断头部是否是压缩文件
d. 进行解压或者直接返回数据
1. 编写插件在发布结束的时候,读取所有json后缀文件
2. 判断大小进行gz压缩写会原来的文件
这里选择的是直接对json进行压缩,文件后缀不变,使用pako库
// utils.js web使用的加载方式, wx远程加载没有做设计考虑
"use strict";
var Uint8ArrayToString = function(uint8array){
return new TextDecoder("utf-8").decode(uint8array);
}
//=============================================
var funcJsonGz = function(item, callback) {
// 根据不同情况进行判断处理否则问题多多
var url = item.url;
if (!CC_EDITOR && CC_BUILD && !CC_PREVIEW){
url = url.replace(".json", ".gz");
}
var errInfo = 'Load binary data failed: ' + url + '';
var xhr = cc.loader.getXMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
var arrayBuffer = xhr.response;
if (arrayBuffer) {
var result = new Uint8Array(arrayBuffer);
let outString = "";
let uerr = null;
//===================================
// 判断开头的处理 是否是压缩方式
if (result[0] == 0x1f && result[1] == 0x8b){
try {
outString = pako.inflate(result, { gzip: true, to: 'string'});
} catch (error) {
cc.log(error);
uerr = error;
}
}else{
outString = Uint8ArrayToString(result);
}
//===================================
if (!uerr){
callback(null, outString);
}else{
callback({status:-1, err:uerr,errorMessage:errInfo + " pako.inflate fail "});
}
}
else {
callback({status:xhr.status, errorMessage:errInfo + '(no response)'});
}
};
xhr.onerror = function(){
callback({status:xhr.status, errorMessage:errInfo + '(error)'});
};
xhr.ontimeout = function(){
callback({status:xhr.status, errorMessage:errInfo + '(time out)'});
};
xhr.send(null);
}
cc.loader.addDownloadHandlers({"json":funcJsonGz});
cc.loader.addDownloadHandlers({"gz":funcJsonGz});
//=========================================
// Game.js
cc.Class({
extends: cc.Component,
properties: {
},
start () {
cc.loader.loadRes("prefabs/node_01", (err, prefab)=>{
if (err) {
cc.error(err.message || err);
return;
}
var n = cc.instantiate(prefab);
this.node.addChild(n);
});
},
// update (dt) {},
});
// package.json
{
"name": "gz_tool",
"version": "0.0.1",
"description": "The package template for getting started.",
"author": "Cocos Creator",
"main": "main.js",
"scene-script": "scene-walker.js",
"main-menu": {
"i18n:MAIN_MENU.package.title/gz_tool/open": {
"message": "gz_tool:open"
},
"i18n:MAIN_MENU.package.title/gz_tool/hello": {
"message": "gz_tool:say-hello"
}
},
"panel": {
"main": "panel/index.js",
"type": "dockable",
"title": "gz_tool",
"width": 400,
"height": 300
}
}
// main.js
'use strict';
function onBeforeBuildFinish (options, callback) {
Editor.log('Building ' + options.platform + ' to ' + options.dest); // 你可以在控制台输出点什么
Editor.Scene.callSceneScript('gz_tool', 'say-gzstart', options, function (err, val) {
Editor.log(`say-gzstart rep:${val}`);
});
callback();
}
module.exports = {
load () {
// execute when package loaded
Editor.Builder.on('before-change-files', onBeforeBuildFinish);
},
unload () {
// execute when package unloaded
Editor.Builder.removeListener('before-change-files', onBeforeBuildFinish);
},
// register your ipc messages here
messages: {
'open' () {
// open entry panel registered in package.json
Editor.Panel.open('gz_tool');
},
'say-hello' () {
Editor.log('Hello World!');
// send ipc message to panel
//Editor.Ipc.sendToPanel('gz_tool', 'gz_tool:hello');
Editor.Scene.callSceneScript('gz_tool', 'say-gzfile', function (err, val) {
Editor.log(`say-gzfile rep:${val}`);
});
},
'clicked' () {
}
},
};
// scene-walker.js
const path = require('path');
const fs = require('fs');
const zlib = require('zlib');
// 遍历目录
function findPaths(ph, list, ext, filters){
var pa = fs.readdirSync(ph);
pa.forEach(function(file,index){
var info = fs.statSync(ph+"/"+file)
if(info.isDirectory()){
findPaths(ph+"/"+file, list, ext, filters);
}else{
if (!ext || path.extname(file) == ext){
var onlyname = path.basename(file, ext);
if (!filters || !filters[onlyname]){
list.push(ph+"/"+file);
}
}
}
})
}
module.exports = {
'ouput_deepQuery':function(){
Editor.assetdb.deepQuery(function (err, results) {
results.forEach(function (result) {
// result.name
// result.extname
// result.uuid
// result.type
// result.isSubAsset
// result.children - the array of children result
Editor.log('===>> xx==>', result.name, result.type);
});
});
/*
Editor.assetdb.queryAssets('db://assets/**\/*', 'texture', function (err, results) {
results.forEach(function (result) {
// result.url
// result.path
// result.uuid
// result.type
});
});
*/
},
'say-gzstart':function(event,options){
// Editor.log("options", options);
// 输出目录
var dest = options.dest;
var startScene = options.startScene;
var buildResults = options.buildResults;
var _buildAssets = buildResults._buildAssets;
var _packedAssets = buildResults._packedAssets;
// 遍历所有json文件
var jsons = [];
// 排除开始场景, 需要开始场景中加入json的加密加载方案,否则可能有问题
// 这里这对wechat 中的开始的两个json配置文件先排除掉
var filters = {'game':true,'project.config':true};//{startScene:true};
findPaths(dest, jsons, '.json', filters);
jsons.forEach(jsonPath=>{
// 替换成gz文件
var outpath = jsonPath.replace(".json", ".gz");
var data = fs.readFileSync(jsonPath);
var buff = zlib.gzipSync(data);
fs.writeFileSync(outpath, buff);
});
jsons.forEach(jsonPath=>{
fs.unlinkSync(jsonPath);
});
// 复制文件和处理头部 这里用于复制一些需要的文件和设置一些信息
// if (cc.sys.platform == cc.sys.WECHAT_GAME){
if (options.platform == "wechatgame"){
/*
var sdkpath = 'xxxx';
var cps = [];
findPaths(sdkpath, cps);
var outpath = dest+'/utils';
if (!fs.existsSync(outpath)){
fs.mkdirSync(outpath);
}
cps.forEach(fp=>{
var fn = path.basename(fp);
fs.writeFileSync(outpath + "/" + fn, fs.readFileSync(fp));
});
// 添加头部
var gamefn = dest + '/game.js';
var gamedt = 'require(\'utils/ald-game.js\')\n' + fs.readFileSync(gamefn, 'utf8');
fs.writeFileSync(gamefn, gamedt);
*/
}
},
};
上面的代码if (options.platform == "wechatgame")
// [cocos creator 2.1.2项目目录]\resources\builtin\weapp-adapter
// wx-downloader.js
const pako = require('../src/assets/scripts/utils/pako.min.js');
var Uint8ArrayToString = function(array){
var out, i, len, c;
var char2, char3;
out = "";
len = array.length;
i = 0;
while(i < len) {
c = array[i++];
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
//return new TextDecoder("utf-8").decode(array);
}
function readFile (item, callback) {
var url = item.url;
var bJson = cc.path.extname(url) == '.json';
if (bJson && url.indexOf("project.config.json") < 0 && url.indexOf('game.json') < 0){
url = url.replace(".json", ".gz");
}
var func = wxFsUtils.readText;
if (getFileType(item.type) === FileType.BIN || bJson)
func = wxFsUtils.readArrayBuffer;
var result = func(url, function (err, data) {
if (err) {
callback(err);
return;
}
if (data) {
item.states[cc.loader.downloader.id] = cc.Pipeline.ItemState.COMPLETE;
let outString = "";
let uerr = null;
if (item.type == 'json' || bJson){
var result = new Uint8Array(data);
//===================================
if (result[0] == 0x1f && result[1] == 0x8b){
try {
outString = pako.inflate(result, { gzip: true, to: 'string'});
} catch (error) {
cc.log("error",error);
uerr = error;
}
}else{
outString = Uint8ArrayToString(result);
}
}else{
outString = data;
}
callback(uerr, outString);
}
else {
callback(new Error("Empty file: " + url));
}
});
if (result) callback(result);
}
var map = {
......
'json' : FileType.BIN,
.....
}
// wx-fs-utils.js
// 排除wechat中的初始两个json配置文件
function getRealPath(filePath){
if (filePath.indexOf('game.json') > 0 || filePath.indexOf('project.config.json') > 0){
return filePath;
}
if (cc.path.extname(filePath) == '.json'){
filePath = filePath.replace('.json', '.gz');
}
return filePath;
}
function exists (filePath, callback) {
filePath = getRealPath(filePath);
var result = checkFsValid();
if (result) return result;
fs.access({
path: filePath,
success: callback ? function () {
callback(true);
} : undefined,
fail: callback ? function () {
callback(false);
} : undefined,
});
}
最后是整个项目的下载地址
包含
https://github.com/hcqmaker/sharething/blob/master/gz_exmaple_v1.0.7z