文章目录

  • 官方文档
  • 开放数据域
  • 微信登录授权登录,获取微信用户信息,分享小游戏
  • 微信排行榜
    • 微信排行榜数据获取
    • 微信好友排行榜绘制
    • 主域名发送消息,共享域接受消息
  • 其他注意事项

官方文档

微信小游戏快速上手
egret微信小游戏开发指南
菜鸟|Egret微信小游戏好友排行榜教程
小程序与小游戏获取用户信息接口调整,请开发者注意升级

  • 整体的效果如下

开放数据域

  • 开放数据域的绘制文件中已经拥有一个通过Canvas API绘制的排行榜 ,SharedCanvas 是主域和开放数据域都可以访问的一个离屏画布,原理如下所示。
  • egret中的ts类文件是在主域,编译生成微信小游戏文件中会有一个openDataContext文件夹里面有一个index.js文件,这个文件中可以绑定上传积分等信息到微信后台,从微信后台获取用户信息和积分数据,清除微信后台积分数据,以及微信后台获取微信好友排行榜数据;(这个文件中可以获取微信相关数据)
  • index.js文件还有一个SharedCanvas,是主域和开放数据域都可以访问的一个离屏画布;主域和开放数据域的分工不同,在主域中创建离屏画布并添加到显示容器中,主域通知共享域去获取微信好友列表信息,然后根据这些信息去绘制排行榜;(主域中创建添加移除销毁离屏画板,并传递分数时间等信息给共享域;共享域接受到信息后经过一系列的数据判断处理后去绘制排行榜);
  • 总而言之就微信不会将一些信息给你随便用(主要是好友列表信息),所以只能在该共享域中获取微信好友列表信息;共享域是可以收到主域的信息的,但主域是不可以是收到共享域的信息;所以这个好友排行榜会的绘制只能放在共享域了.

微信登录授权登录,获取微信用户信息,分享小游戏

  • egret中有一个Platform.ts类,对应编译后微信小游戏中的platform.js文件;主要用于获取平台数据接口的,包括微信授权登录获取用户信息,分享小游戏给好友,分享小游戏到群;

  • Platform.ts中全部代码

       //正式版中只有方法声明declare interface Platform {//获取用户信息getUserInfo(): Promise<any>;//微信授权登录login(): Promise<any>;//分享转发,主要用于被动转发showSharemMenu():Promise<any>//主动转发shareAppMessage():Promise<any>openDataContext:any}//测试版class DebugPlatform implements Platform {async getUserInfo() {return { nickName: "username" }}async login() {}async showSharemMenu() {}async shareAppMessage() {}openDataContext}//设置为全局if (!window.platform) {window.platform = new DebugPlatform();}declare let platform: Platform;declare interface Window {platform: Platform}
    
  • platform.js中全部代码

    class WxgamePlatform {name = 'wxgame'//登录login() {return new Promise((resolve, reject) => {wx.login({success: (res) => {resolve(res)}})})}//获取用户信息getUserInfo() {let windowWidth = wx.getSystemInfoSync().windowWidth;let  windowHeight = wx.getSystemInfoSync().windowHeight;return new Promise((resolve, reject) => {let button = wx.createUserInfoButton({type: 'text',text: '获取用户信息',style: {left: windowWidth/2 - 100,top: windowHeight/2 - 20,width: 200,height: 40,lineHeight: 40,backgroundColor: '#008888',color: '#ffffff',textAlign: 'center',fontSize: 16,borderRadius: 4}});//允许按钮button.onTap((res) => {// button.hide();var userInfo = res.userInfo;resolve(userInfo);    console.log(res);button.destroy();});//关闭按钮button.offTap((res) => {resolve(res);button.destroy();});});}//被动分享showSharemMenu(){console.log("微信分享");return new Promise((resolve,reject) => {//显示当前页面的转发按钮wx.showShareMenu({withShareTicket:true,success:(res)=>{console.log("success", res);},fail:(res)=>{console.log("fail", res);},complete:(res)=>{console.log("complete",res);}});//被动转发wx.onShareAppMessage(() => {return {title: '捷达小飞车',imageUrl: 'openDataContext/assets/icon_first.png' // 图片 URL}});});}//主动转发  shareAppMessage() {return new Promise((resolve, reject) => {wx.shareAppMessage({title: '捷达小飞车',imageUrl: 'openDataContext/assets/icon_first.png' // 图片 URL  })})}
    openDataContext = new WxgameOpenDataContext();}
    //下面代码自动生成不要动
    class WxgameOpenDataContext {createDisplayObject(type, width, height) {const bitmapdata = new egret.BitmapData(sharedCanvas);bitmapdata.$deleteSource = false;const texture = new egret.Texture();texture._setBitmapData(bitmapdata);const bitmap = new egret.Bitmap(texture);bitmap.width = width;bitmap.height = height;if (egret.Capabilities.renderMode == "webgl") {const renderContext = egret.wxgame.WebGLRenderContext.getInstance();const context = renderContext.context;需要用到最新的微信版本调用其接口WebGLRenderingContext.wxBindCanvasTexture(number texture, Canvas canvas)如果没有该接口,会进行如下处理,保证画面渲染正确,但会占用内存。if (!context.wxBindCanvasTexture) {egret.startTick((timeStarmp) => {egret.WebGLUtils.deleteWebGLTexture(bitmapdata.webGLTexture);bitmapdata.webGLTexture = null;return false;}, this);}}return bitmap;}postMessage(data) {const openDataContext = wx.getOpenDataContext();openDataContext.postMessage(data);}
    }
    window.platform = new WxgamePlatform();
    
    • 小游戏启动时要微信授权登录获取用户信息,以及被动分享,在Main.tsrunGame方法中添加:
     private async runGame() {//微信授权登录await platform.login()//如果已经授权登录就跳过授权登录步骤if(!egret.localStorage.getItem("nickName")||!egret.localStorage.getItem("avatarUrl")){await this.loginAndGetUserInfo();}await this.loadResource();this.createGameScene();//游戏页面都加载完成后展示分享按钮await platform.showSharemMenu();const result = await RES.getResAsync("description_json")this.startAnimation(result);}//授权登录获取用户信息private async loginAndGetUserInfo() {const userInfo = await platform.getUserInfo();//微信授权登录console.log("userInfo",userInfo);if(userInfo){//名称和图片保存在本地egret.localStorage.setItem("nickName",userInfo.nickName);egret.localStorage.setItem("avatarUrl",userInfo.avatarUrl);}}
    

    微信登录授权获取用户信息效果如下:

    微信被动分享需要注意的是platform.showSharemMenu()必须在创建游戏场景后调用,否则会卡住;添加后会模拟器出现转发取消选项效果如下:

  • 微信主动转发分享:即我们自己添加一个分享按钮点击后分享给好友,代码如下

    //转发按钮点击事件
    this.forwardBtn.addEventListener(egret.TouchEvent.TOUCH_TAP,()=>{//主动转发事件platform.shareAppMessage();
    },this);
    

微信排行榜

  • 在共享获取微信相关信息和绘制排行榜,即在openDataContext文件夹的index.js文件中进行操作

微信排行榜数据获取

  • 获取和写入用户托管数据到微信后台:即游戏结束时上传分数到微信后台,但要先判断是最大分数时才上传;wx.getUserCloudStorage方法获取用户托管信息,wx.setUserCloudStorage写入用户信息,相关代码,

        //获取当前用户托管数据当中对应 key 的数据。该接口只可在开放数据域下使用,比较当前分数是否比存储的分数大,如果大就更新数据function getUserCloudData(data) {nickName = data.nickName;myCurrentScore = data.wxgame.score;console.log("当前分数", myCurrentScore);wx.getUserCloudStorage({keyList: ["gameScoreData"],success: (re) => {console.log("[wx]success", re);let userData = re.KVDataList;console.log("userData", userData);myShowRank = ShowRanking.ShowLite;if (userData.length > 0) {let value = userData[0].value;let json = JSON.parse(value);console.log("json", json);maxScore = json.wxgame.score ? json.wxgame.score : 0;console.log("maxScore", maxScore);console.log("最大分数", maxScore);if (maxScore < myCurrentScore) {//如果当前分数大于最大分数则更新最大分数updateUserDataToCloud(data);}else {if(totalGroup.length <= 0){preloadFriendData();} else {console.log("有数据并且不用更新数据,就直接绘制");renderDirty = true;//重绘标记requestAnimationFrameID = requestAnimationFrame(loop);//每一帧绘制}}} else { //第一次为空updateUserDataToCloud(data);}}, fail: (re) => {console.log("[wx]fail", re);}, complete: (re) => {console.log("[wx]complete", re);}})}//对用户托管数据进行写数据操作。允许同时写多组 KV 数据。上传分数等信息到微信云function updateUserDataToCloud(data) {console.log("上传分数", data);let userKVData = {key: "gameScoreData",value: JSON.stringify(data)}console.log(userKVData);wx.setUserCloudStorage({KVDataList: [userKVData],success: (re) => {console.log("[wx]success", re);preloadFriendData();}, fail: (re) => {console.log("[wx]fail", re);}, complete: (re) => {console.log("[wx]complete", re);}});}
    
  • 获取好友列表信息wx.getFriendCloudStorage;下面是获取用户信息,并对用户图像进行预加载,然后根据分数排序相关代码
    //获取好友排行榜数据信息
    function preloadFriendData() {wx.getFriendCloudStorage({keyList: ["gameScoreData"],success: (re) => {console.log("[wx]success", re);let dataArr = re.data;var tempArr = [];let imagUrl = [];console.log("dataArr", dataArr);for (var i = 0; i < dataArr.length; i++) {let objc = dataArr[i];let oj = {};oj.key = i;oj.name = objc.nickname;oj.url = objc.avatarUrloj.score = 0;if (objc.KVDataList.length > 0) {let userSetData = objc.KVDataList[0];let score = JSON.parse(userSetData.value).wxgame.score;console.log("分数", score);oj.score = score;}imagUrl.push(objc.avatarUrl);tempArr.push(oj);}console.log("tempArr", tempArr);totalGroup = null;totalGroup = tempArr;console.log("totalGroup1", totalGroup);if (imagUrl.length > 0) {preloadAvatarUrl(imagUrl);}}, fail: (re) => {console.log("[wx]fail", re);}, complete: (re) => {console.log("[wx]complete", re);}});
    }//先预加载图片资源
    function preloadAvatarUrl(avatarUrlList) {console.log("imgs", avatarUrlList);let preloaded = 0;let assetsAvatar = [];for (var j = 0; j < avatarUrlList.length; j++) {const img = wx.createImage();img.onload = () => {preloaded++;if (preloaded == avatarUrlList.length) {console.log("所有头像加载完成");console.log("图片", assetsAvatar);for (var i = 0; i < totalGroup.length; i++) {let objc = totalGroup[i];objc.img = assetsAvatar[i];}let data = totalGroup.sort(createComprisonFunction("score", false));for (var i = 0; i < totalGroup.length; i++) {let objc = totalGroup[i];objc.key = i + 1;}totalGroup = data;console.log("totalGroup2", totalGroup);renderDirty = true;//重绘标记requestAnimationFrameID = requestAnimationFrame(loop);//每一帧绘制      }}img.src = avatarUrlList[j];assetsAvatar.push(img);}
    }//对象数组,根据对象的key进行排序
    function createComprisonFunction(propertyName, isSequence) { //true为顺序,false为逆序return function (object1, object2) {var value1 = object1[propertyName];var value2 = object2[propertyName];if (isSequence == true) { //顺序排序if (value1 < value2) {return -1;} else if (value1 > value2) {return 1;} else {return 0;}} else {if (value1 < value2) {return 1;} else if (value1 > value2) {return -1;} else {return 0;}}}
    }
    

微信好友排行榜绘制

  • 游戏结束主域创建离屏画布,并添加显示;官方示例该画布占满整个舞台,但其实可以是自定义一个group,添加到group中;但这group的必须是舞台的宽高的等比例缩放,不然在共响域绘制就没法计算出正确的位置;

    可以看出在exml文件中,虽然我只需要在白色背景处绘制排行榜,但是由于会变形,真正要添加离屏画布的group比较长;
    在响应的ts文件中创建和添加离屏画布

    this.gameOverBitmap = platform.openDataContext.createDisplayObject(null, this.gameOverGroup.width, this.gameOverGroup.height);
    this.gameOverGroup.addChild(this.gameOverBitmap);
    

主域名发送消息,共享域接受消息

  • 游戏结束主域发送分数等信息给共享域;共享域监听接受到消息后进行一系列的数据处理,排行榜绘制工作;
  • 游戏结束够主域创建添加离屏画布,发送分数给子域;
    //游戏结束绘制分数等信息private gameOverGroup: eui.Group;// private gameOVerMask: egret.Shape;private gameOverBitmap: egret.Bitmap;//上传分数到微信private upLoadMyScore() {egret.log("gameOverGroup",this.gameOverGroup);egret.log("gameOverGroup.width",this.gameOverGroup.width);if(this.gameOverGroup){//gameOverBitmap 宽高比必须是stage的宽高比,否则变形this.gameOverBitmap = platform.openDataContext.createDisplayObject(null, this.gameOverGroup.width, this.gameOverGroup.height);this.gameOverGroup.addChild(this.gameOverBitmap);}//发送消息给子域platform.openDataContext.postMessage({wxgame: {score:this.score,update_time:new Date().getTime(),},nickName: egret.localStorage.getItem("nickName"),width:this.gameOverBitmap.width,height:this.gameOverBitmap.height,command: "updateMyScore"});}
    
  • 共享域名监听接受消息
    /*** 增加来自主域的监听函数*/
    function addOpenDataContextListener() {console.log('增加监听函数')wx.onMessage((data) => {console.log(data);if (data.command == 'open') {//打开微信好友排行榜if (!createScene()) return;myShowRank = ShowRanking.ShowAll;if (totalGroup.length > 0) {renderDirty = true;//重绘标记// requestAnimationFrameID = requestAnimationFrame(loop);//每一帧绘制  } else {preloadFriendData();}} else if (data.command == 'goBack' && requestAnimationFrameID) {console.log("goBack");//返回时重新绘制简易排行榜myShowRank = ShowRanking.ShowLite;renderDirty = true;//重绘标记} else if (data.command == 'loadRes' && !hasLoadRes) {/*** 加载资源函数* 只需要加载一次*/// console.log('加载资源')preloadAssets();} else if (data.command == "updateMyScore") {//更新用户信息if (!createScene()) return;console.log("data", data);getUserCloudData(data);} else if (data.command == "loadLastPage") {//加载上一页if (page > 0) {buttonClick(0);}} else if (data.command == "loadNextPage") {//加载下一页//在next按钮的范围内if ((page + 1) * perPageMaxNum < totalGroup.length) {buttonClick(1);}} else if (data.command == "startPlayGame"){console.log("startPlayGame");//开始游戏,停止进行循环绘图cancelAnimationFrame(requestAnimationFrameID);requestAnimationFrameID = null}});
    }
    

    效果如下:

其他注意事项

  • 展示排行榜时报错gameSubContextThirdScriptError Cannot read property 'width' of undefined;at requestAnimationFrame callback function TypeError: Cannot read property 'width' of undefined时必须在Main.ts加载资源时通知共享域预加载图片资源,及调用platform.openDataContext.postMessage({command:'loadRes'});.

    private async loadResource() {try {const loadingView = new LoadingUI();this.stage.addChild(loadingView);await RES.loadConfig("resource/default.res.json", "resource/");await this.loadTheme();await RES.loadGroup("preload", 0, loadingView);//第三个参数只要实现RES.PromiseTaskReporter协议的onProgress方法既可以this.stage.removeChild(loadingView);//添加一行代码:加载排行榜资源,否则在展示排行榜时报错gameSubContextThirdScriptError Cannot read property 'width' of undefined;at requestAnimationFrame callback function TypeError: Cannot read property 'width' of undefinedplatform.openDataContext.postMessage({command:'loadRes'});}catch (e) {console.error(e);}}
    
  • canvas画布的大小是舞台大小,但实际上是有所缩放,所以我们需要通过比例系数计算真实的大小以方便绘制;
      //500x888 //画板区域//500x604 //绘制区域//500 x 255 蓝色图片// let scale = 500/640;let topBackGroundHeight = 255/888*sharedCanvas.height;//设置图尺寸乘以下面宽度放大的倍数就是真实尺寸let widthScale = sharedCanvas.width / 640;fontScale = sharedCanvas.height/1136;
    
  • loop方法是一个递归调用,开启会一直循环调用,只要renderDirty设置为true就会绘制图像
    /*** 循环函数* 每帧判断一下是否需要渲染* 如果被标脏,则重新渲染*/
    function loop() {if (renderDirty) {context.setTransform(1, 0, 0, 1, 0, 0);context.clearRect(0, 0, sharedCanvas.width, sharedCanvas.height);if (myShowRank == ShowRanking.ShowLite) {console.log("绘制精简版排行榜");drawLiteRankPanel();} else if (myShowRank == ShowRanking.ShowAll) {console.log("绘制全部排行榜");drawRankPanel();}renderDirty = false;}// console.log("递归死循环调用");requestAnimationFrameID = requestAnimationFrame(loop);
    }
    

    所以在退出排行榜重新开始游戏时就停止循环绘制调用

    //开始游戏,停止进行循环绘图cancelAnimationFrame(requestAnimationFrameID);requestAnimationFrameID = null
    
  • 开始绘制调用requestAnimationFrame(loop)调用一次即可,renderDirty设置为true就会安装canvas去绘制,所以在涉及到绘制界面刷新改变时就将renderDirty设置为true即可.
  • 不管是本地图片资源还是网络图片资源在显示之前需要预加载,否则无法显示;微信提供了相关方法
    //创建图片容器
    const img = wx.createImage();
    //图片加载完成时回调
    img.onload = () => {}
    //本地图片资源通过图片传入图片路径,网络图片资源传入图片url
    img.src = assetsUrl[asset];
    

  • 相关源码已经上传
    egret游戏源码
    转换为微信小游戏源码

  • 其他参考
    用Egret开发微信小游戏之二
    第一次使用Egret开发微信小游戏经验总结(包括排行榜排序,每周一数据清零,超越好友等处理)
    微信好友排行榜 - 白鹭对接
    KVData到底应该怎么定义啊?
    微信小游戏如何调用关系链Api

egret微信小游戏相关相关推荐

  1. 菜鸟|Egret微信小游戏好友排行榜教程

    原文链接:https://mp.weixin.qq.com/s/kYIdnHv-C5KuR9snekPNBg 原文虽然是菜鸟教程,但是有几个地方没有说清楚,补充如下. 你可以先看原文,看不懂时,再来这 ...

  2. 2018微信公开课:微信小游戏的精华内容要点分享!

    导语:本篇汇总了上午的微信公开课和下午的小游戏分论坛上,嘉宾分享的微信小游戏相关内容要点. 今天,在2018微信公开课上,微信小游戏无疑成为了最重要的热点之一. 4000多人聚集在广州保利世贸博览馆, ...

  3. H5 微信小游戏群 openGID 解密

    这里使用的 Wechat Lib 版本是 2.0.6 ,高于此版本则不再能获得分享成功与否的回调.后来直接把基础库升级到 2.2.2 ,发现只是开发者工具拿不到回调而已,手机上还是还能拿到回调. 在使 ...

  4. 微信小游戏接入遇到的坑

    微信小游戏接入遇到的坑 1.微信web开发工具必须安装到C盘,才能被egret wing自动调取. 2.exml文件不能放在src文件夹,必现放在resource文件夹 3.egret Launche ...

  5. 微信小游戏越来越「重」,但它能赚钱么?

    氪金.直播.上 3D,小游戏已经不「小」了. 说起微信小游戏,外界总会有几个刻板标签. 比如,小游戏只能玩轻度游戏,「跳一跳」.「欢乐斗地主」是典型:小游戏不温不火,「跳一跳」之后似乎再无全民话题的爆 ...

  6. cocos微信小游戏开发-http请求-使用微信云函数-toast-loading-动态加载图片-添加触摸事件-微信分享-label点击事件-背景音乐音效-程序活动状态判断-性能优化

    cocos开发微信小游戏相关-<益智推箱> 扫码查看功能,有需要可直接提问 Cocos Creator 3.4 用户手册 cocos creator基本操作 微信开发文档|云函数 1. h ...

  7. Unity 开发微信小游戏初探

    前言 最近因项目需要开始研究Unity开发微信小游戏相关的知识.期间遇到各种坑,网上查阅的资料基本类似,无法解决自己遇到的问题.特用本文记录下过程,方便其他人遇到同样的问题时能够参考. 开发环境 Un ...

  8. Egret项目改成H5微信小游戏

    1.新版的AssetsManager在通过外部路径(Res.getResByUrl)加载资源时,一定要传入加载的类型,不然会报错的,旧的Res是不会报错的: 2.微信小游戏不允许eval函数,用JSO ...

  9. Egret 生成 自带EUI 的微信小游戏 踩坑!

    1. 首先,再次被网上一大堆屎一样的资料搞得浪费了我一天时间.各种坑. 2. 本文先讲一种正确的方式,然后再列举坑. 去www.egret.com下载最新的引擎,我的最新版本是5.2.2. 然后就会被 ...

最新文章

  1. 自动化运维之SaltStack,批量安装httpd实战
  2. MaterialEditText 控件学习
  3. 第 6 章 —— 装饰模式
  4. IOC容器(底层原理解读)
  5. 一个优秀的前端工程师应具备哪些技能?
  6. 读懂 x86 架构 CPU 虚拟化,看这文就够了 | 赠书
  7. 苹果Mac 3D 模型展开工具:Unfolder
  8. oracle的sql字符串转义,sql – 在Oracle数据库中搜索带转义的字符串
  9. 苹果ios啸叫频点测试软件_啸叫抑制之陷波法
  10. 修改Maven本地仓库路径,IDEA修改maven位置
  11. python半自动化获取QQ空间说说
  12. Ragel入门1——简介
  13. 网页数据提取----网络投票软件开发
  14. Python 文件操作出现错误(result, consumed) = self._buffer_decode(data, self.errors, final)
  15. 高级运维工程师面试题(更新中)
  16. 喜欢简洁可爱风的小可爱有没有
  17. 替代MP9486A 输入120V降压恒压IC方案 GPS防盗器IC方案
  18. 系统架构图编写(概要设计)
  19. 你选择双休还是单休?
  20. 2020-11-25T09:10:13.000Z mysql 自动生成的时间格式化 vue

热门文章

  1. 【MASM】hello world
  2. 2007------生活感悟
  3. cake fork什么意思_方学—为了世界的爱与和平
  4. 淘宝去ioe用mysql,去 IOE,MySQL 完胜 PostgreSQL
  5. 计蒜客-青出于蓝胜于蓝 dfs+树状数组
  6. 如何在xp添加无线网络连接服务器,xp怎么设置无线网络连接 windowsxp无线网络连接设置方法【图文】...
  7. 用计算机演奏歌唱祖国,温州商学院学生用计算器演奏《歌唱祖国》,拍成视频教大家弹...
  8. 老毛桃重启计算机没反应,用老毛桃装完系统后重新启动一直进不去系统,老是重启怎么回事呀?...
  9. VS(Visual Studio)应用程序无法正常启动(0xc000007b)解决办法大全
  10. android sensors 总结(一)