原文链接:基于EGRET的大型项目转微信小游戏开发总结——各种坑处理 http://51meaning.cn/blog/?p=412
这阵在做基于Egret的微信小游戏,项目很大,也踩了很多坑,特总结如下,供各位难兄难弟参考!
1、window.Main=Main;换成window.Main=项目实际入口Main[带包类路径];
2、目前白鹭小游戏支持解析 xml 了吗,该如何使用?
答:
升级小游戏支持库到1.0.12版本
在微信开发者工具的 Console 控制台输入egret.wxgame.version应输出1.0.12
访问http://developer.egret.com/cn/github/egret-docs/Engine2D/minigame/minigameFAQ/xmldom.zip下载小游戏xml支持库
解压支持库,并拷贝到微信小游戏目录
打开小游戏目录中 game.js
在 egret.runEgret 之前加入代码:window.DOMParser = require("./xmldom/xmldom.js").DOMParser;
3、所有自定义eui.skin修改
创建exml文件
|
引用
this.skinName = "gameskin.XXXBtn;// exml文件class name
4、JSON.parse时加上item != ""的判断,即
if(item != undefined && item != null && item != ""){ |
5、egret.localStorage.getItem(key);时,key要是字符串,如果传入的是string类型的数字,也可能在存取时出问题,如果出问题,改成egret.localStorage.getItem(“”+key);即可。
6、改用AssetsManager,不支持RES.getVersionController().getVirtualUrl(url),要把RES.getRes(RES.getVersionController().getVirtualUrl(url));换成RES.getRes(url);
7、图片尺寸长宽都不能超过2048。
8、设置分包加载、资源缓存,参考如下链接
分包加载: http://developer.egret.com/cn/github/egret-docs/Engine2D/minigame/package/index.html
资源缓存: http://developer.egret.com/cn/github/egret-docs/Engine2D/minigame/usingcache/index.html
9、修改EgretSubPackageLoading.js,可以添加启动页面/背景。
10、main.min.js过大时,可以进行分割。
js脚本如下,文件路径根据自己情况进行修改(标红处)
var path = require("path"); var fs = require("fs"); var referenceRegExp = /\<(?!\s*\/)\s*([\w:$]*)/g;//组件类名匹配 var nameSpaceRegExp = /namespace\s+([a-zA-Z0-9$_]*)/g;//代码中命名空间匹配组 var classRegExp = /(class|enum)\s+([a-zA-Z0-9$_]*)(?=(\s+extends)|(\s+implements)|(\s*{)|(<[^>]*>))/g;//代码中类名匹配组 var referenceMap = {};//类名到全限定类名映射 var needAddToGlobalNameSpaces = [];//需要添加到window上的命名空间 var needAddGlobalReferenceClassList = [];//需要添加都window上的类名 var componentReferenceClassList = [];//自定义组件的类名 //TODO — 注意换成你自己的配置啦…… var splitConfig = { codeMinifyPath: path.resolve("stage0/main.min.js"), firstPartCodeFileName: "main_part1.min.js", secondPartCodeFileName: "main_part2.min.js", firstPartCodeFilePath: "stage1", secondPartCodeFilePath: "stage2", splitSepStr: "__reflect(DebugPlatform.prototype,\"DebugPlatform\",[\"Platform\"]),window.platform||(window.platform=new DebugPlatform);" }; generateClassReferenceCode(); /** * 找出所有exml皮肤文件中用到的自定义的组件 * 生成在window对象上的引用代码 * @returns {string} */ function generateClassReferenceCode() { let codeContent = fs.readFileSync(splitConfig.codeMinifyPath, "utf-8"); let index = codeContent.indexOf(splitConfig.splitSepStr); if (index === -1) { console.warn(`在代码中未找到分割字符串${splitConfig.splitSepStr}`); return; } let codeContent1 = codeContent.substring(0, index + splitConfig.splitSepStr.length); let codeContent2 = codeContent.substr(index + splitConfig.splitSepStr.length); let testRegExp = /__reflect\s*\(\s*[^,]+,\s*”([^\"]*)"/g; //处理part1 needAddGlobalReferenceClassList.length = 0; needAddToGlobalNameSpaces.length = 0; referenceMap = {}; let mathArray = testRegExp.exec(codeContent1); let className; let nameSpaceName; while (mathArray) { let fullClassName = mathArray[1]; if (fullClassName.indexOf(".") !== -1) { nameSpaceName = fullClassName.split(".")[0]; className = fullClassName.split(".")[1]; referenceMap[className] = fullClassName; if (needAddToGlobalNameSpaces.indexOf(nameSpaceName) === -1) { needAddToGlobalNameSpaces.push(nameSpaceName); } if (needAddGlobalReferenceClassList.indexOf(className) === -1) { needAddGlobalReferenceClassList.push(className); } else { console.log(`代码中存在两个相同的类名${className},即使在同样的命名空间下也必行!`); } } else { needAddGlobalReferenceClassList.push(fullClassName); referenceMap[fullClassName] = fullClassName; } mathArray = testRegExp.exec(codeContent1); } let referenceCodeStr = ";window.egret=egret;"; needAddToGlobalNameSpaces.forEach((nameSpace) => { referenceCodeStr += "window[\"" + nameSpace + "\"]=" + nameSpace + ";" }); needAddGlobalReferenceClassList.forEach((className) => { referenceCodeStr += "window[\"" + className + "\"]=” + referenceMap[className] + ";" }); codeContent1 += referenceCodeStr; //处理part2 let firstPartNameSpaces = needAddToGlobalNameSpaces.concat(); let firstPartClassReference = needAddGlobalReferenceClassList.concat(); needAddGlobalReferenceClassList.length = 0; needAddToGlobalNameSpaces.length = 0; referenceMap = {}; mathArray = testRegExp.exec(codeContent2); while (mathArray) { let fullClassName = mathArray[1]; if (fullClassName.indexOf(".") !== -1) { nameSpaceName = fullClassName.split(".")[0]; className = fullClassName.split(".")[1]; referenceMap[className] = fullClassName; if (needAddToGlobalNameSpaces.indexOf(nameSpaceName) === -1) { needAddToGlobalNameSpaces.push(nameSpaceName); } if (needAddGlobalReferenceClassList.indexOf(className) === -1) { needAddGlobalReferenceClassList.push(className); } else { console.log(`代码中存在两个相同的类名${className},即使在同样的命名空间下也必行!`); } } else { needAddGlobalReferenceClassList.push(fullClassName); referenceMap[fullClassName] = fullClassName; } mathArray = testRegExp.exec(codeContent2); } referenceCodeStr = ";window.egret=egret;"; needAddToGlobalNameSpaces.forEach((nameSpace) => { referenceCodeStr += "window[\"" + nameSpace + "\"]=" + nameSpace + ";" }); needAddGlobalReferenceClassList.forEach((className) => { referenceCodeStr += "window[\"" + className + "\"]=” + referenceMap[className] + ";" }); //part2中必须引入part1中的所有命名空间以及类名定义,否则part2运行时一堆找不到 let part1CodeDeclare = ""; if (firstPartNameSpaces.length) { firstPartNameSpaces.forEach(ns => { part1CodeDeclare += "var " + ns + "=window[\"" + ns + "\"];"; }) } if (firstPartClassReference) { firstPartClassReference.forEach(classzz => { part1CodeDeclare += "var " + classzz + "=window[\"" + classzz + "\"];"; }) } codeContent2 = "var __reflect=this&&this.__reflect||function(t,e,i){t.__class__=e,i?i.push(e):i=[e],t.__types__=t.__types__?i.concat(t.__types__):i},__extends=this&&this.__extends||function(t,e){function i(){this.constructor=t}for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);i.prototype=e.prototype,t.prototype=new i};" + part1CodeDeclare + codeContent2 + referenceCodeStr; fs.writeFileSync(path.join(splitConfig.firstPartCodeFilePath, splitConfig.firstPartCodeFileName), codeContent1, "utf-8"); fs.writeFileSync(path.join(splitConfig.secondPartCodeFilePath, splitConfig.secondPartCodeFileName), codeContent2, "utf-8"); } |
最后,使用cmd执行命令:node 脚本名.js,
11、渲染模式,egret在发布时不会自动生成,这点确实让人有些郁闷,为此查了好一阵游戏卡的问题。需手动在game.js下设置为renderMode: "webgl", 请写在—-auto option end—-后面,这样不会每次编译都被删除掉。
12、需手动指定liberary下needCache方法的缓存文件,否则不缓存。
13、声音播放有回音,可以修改egret.wxgame.js HtmlSoundChannel注释 audio.volume = 0;
14、短声音播放不出来的处理:将声音资源放在小游戏项目下,使用wx.createInnerAudioContext()来播放。
this.audio = wx.createInnerAudioContext(); |
15、支付问题处理:
access_token missing hint 41001错误
仔细看文档发现要把access_token放到url里 https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN而不是放到post参数里。官方的这个文档有点迷,说实话。
16、屏幕适配问题,伪代码如下
let displayWidth = this.stage.stageWidth;// 屏幕宽 |
17、处理刘海屏手机显示
升级微信小游戏基础库版本到2.7.0或以上。
使用wx.getSystemInfo(Object object)获取safeArea. top,如果大于0,基本判断是刘海屏,可以选择将游戏整体ui下移。
更多小游戏开发:
EGRET游戏转QQ小游戏实战总结
EGRET游戏转小米快游戏开发参考