基于EGRET的大型项目转微信小游戏开发总结——各种坑处理

原文链接:基于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文件

<?xml version="1.0" encoding="utf-8"?>
<e:Skin class="gameskin.XXXBtn" states="up,down" xmlns:e="http://ns.egret.com/eui">
<e:Image width="320" height="152" source="xxx_png" source.down="xxx_png" />
</e:Skin>

引用
this.skinName = "gameskin.XXXBtn;// exml文件class name

4、JSON.parse时加上item != ""的判断,即

if(item != undefined && item != null && item != ""){
    obj = JSON.parse(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();
this.audio.src = "xxx.mp3";
this.audio.stop();
this.audio.play();

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;// 屏幕宽
 let displayHeight = this.stage.stageHeight;// 屏幕高
 let stageHeight = displayHeight;// 实际高
 let stageWidth = Math.round(游戏默认宽* displayHeight /游戏默认高);// 按比例缩放,得到实际宽度
 if(stageWidth > displayWidth) {
        stageWidth = displayWidth;
  }
 let scaleX = stageWidth / 游戏默认宽;// 新宽度/游戏默认宽
 let scaleY = stageHeight / 游戏默认高;// 新高度/游戏默认高度
 this.scaleY = scaleY;//关键点
 this.scaleX = scaleX; //关键点
 this.x = (displayWidth – stageWidth) / 2;// 居中对齐

17、处理刘海屏手机显示
升级微信小游戏基础库版本到2.7.0或以上。
使用wx.getSystemInfo(Object object)获取safeArea. top,如果大于0,基本判断是刘海屏,可以选择将游戏整体ui下移。

更多小游戏开发:

EGRET游戏转QQ小游戏实战总结

EGRET游戏转小米快游戏开发参考

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值