微信小游戏排行榜设计技术梳理

要制作排行榜,我们需要使用一个数组totalGroup来存储同玩好友的数据,totalGroup中同玩好友数据格式如下:

 1 const totalGroup = [
 2 {
 3     key: 1,//用户排名
 4     name: "xiaoming",//用户昵称
 5     url: avatarUrl,//用户头像地址
 6     img:image,//用户头像,根据头像地址生成image
 7     scroes: 95//用户得分
 8 },
 9 
10 {
11     key: 2,
12     name: "xiaohua",
13     url: avatarUrl,
14     img:image,
15     scroes: 90
16 },
17 //...
18 ]

 当游戏完成时,玩家得分会上传至用户托管数据,totalGroup根据用户同玩好友托管数据进行更新,排行榜根据totalGroup中的数据进行渲染。

游戏各阶段实现的功能总结如下:

1.游戏初始化时

根据同玩好友数据更新totalGroup;

2.游戏完成时

将玩家得分上传至用户托管数据

3.玩家打开排行榜时

根据同玩好友数据更新totalGroup,然后根据totalGroup渲染排行榜;

本文不会详解排行榜的渲染,主要分析下面两个问题:

1.上传玩家得分至用户托管数据

2.根据同玩好友数据更新totalGroup

一、上传玩家得分至用户托管数据

由于游戏逻辑是在主域中编写的,所以需要在主域中把得分等数据传入开方数据域(关于主域和开放数据域的概念请参考官方文档,这里不详述),接口如下:

 1 //主域中编写
 2 function setScore(score){
 3     var openDataContext = new WxgameOpenDataContext();
 4 
 5     var info={
 6         command:"setScore",
 7         score:score,
 8         timeStamp:new Date().getTime()
 9     };
10 
11     openDataContext.postMessage(info);
12 }

这里的timeStamp属性是得分时的时间戳,为了实现只对本周同玩好友进行排行的功能。然后在开方数据域中接受并处理信息:

 1 //在开方数据域中编写
 2 wx.onMessage((data) => {
 3     if (data.command == 'setScore'){
 4         setScore(data);//处理得分
 5     }else if(data.command == 'preload'){
 6         //游戏初始化时预加载资源和根据同玩好友数据更新totalGroup;
 7     }else if(data.command == 'open'){
 8         //根据同玩好友数据更新totalGroup及渲染排行榜;
 9     }
10 });    

在setStore中先判断分数是否是本周最高分,若是则将分数上传至用户托管数据:

 1 //在开方数据域中编写
 2 function setScore(data){
 3     var score=data.score;
 4     var timestamp=data.timeStamp;
 5 
 6     /*
 7     判断totalGroup是否存在当前用户,若不存在则更新分数,若存在则判    断其中的分数是否大于score,若大于则退出,否则更新分数。
 8     */
 9     for(var i=0;i<totalGroup.length;i++){
10         var name=totalGroup[i].name;
11         var lastScore=totalGroup[i].scroes;
12         var username=userData[0].nickname;//userData中存储用户数据信息,在游戏加载时初始化,代码附在后面
13         if (username == name && lastScore >= score){
14             return;
15         }
16     }
17 
18     //更新用户托管数据
19     return new Promise((resolve, reject) => {
20         wx.setUserCloudStorage({
21             KVDataList: [{
22                 key: "score",
23                 value: JSON.stringify(score),
24             }, {
25                 key: "timestamp",
26                 value: JSON.stringify(timestamp),
27             }, ],
28 
29             success: function (res) {
30                 resolve();
31             },
32         })
33     })
34 }            

获取用户数据userData,游戏初始化时执行

1 //在开方数据域中编写
2 wx.getUserInfo({
3     openIdList: ['selfOpenId'],
4     lang: '',
5     success: function(res) {
6         userData=res.data;
7     },
8 })

二、根据同玩好友数据更新totalGroup

为了实现只对本周玩家分数进行排行的功能,totalGroup中只存储本周玩家的数据;

 1 function updateTotalGroup (){
 2     
 3     //按分数大小进行排序的排序函数
 4     function compare(obj1, obj2) {
 5         var score1 = parseInt(obj1.scroes);
 6         var score2 = parseInt(obj2.scroes);
 7         if (score1 > score2) {
 8             return -1;
 9         } else {
10             return 1;
11         }
12     }
13 
14     wx.getFriendCloudStorage({
15         keyList: ["score","timestamp"],
16         success: function (res) {
17         //先清空totolGroup
18         totalGroup.splice(0,totalGroup.length);
19         var data = res.data;
20 
21         for (let i = 0; i < data.length; i++) {
22             if (data[i].KVDataList.length<2){
23                 continue;
24             }
25             //获取得分的时间戳并判断是否是本周,如果是则将数据存入totalGroup
26             var timestamp=data[i].KVDataList[1].value;
27             if (isCurrentWeek(timestamp)){
28                 var obj = {
29                     key: i,
30                     openid:data[i].openid,
31                     name: data[i].nickname,
32                     url: data[i].avatarUrl,
33                     img: null,
34                     scroes: data[i].KVDataList[0].value
35                 }
36                 totalGroup.push(obj);
37             }
38         }
39         //排序及设置头像
40         totalGroup.sort(compare);
41         for (let i = 0; i < totalGroup.length; i++) {
42             const img = wx.createImage();
43             img.src = totalGroup[i].url;
44             totalGroup[i].img = img;
45             totalGroup[i].key = i + 1;
46         } 
47         //渲染排行榜
48         renderRank(totalGroup)//实现过程省略
49 
50     })
51 }

通过时间戳判断分数是否是本周更新:

 1 function isCurrentWeek(timestamp){
 2     if(timestamp==undefined){
 3         return false;
 4     }
 5     var date=new Date(),
 6     day=date.getDay()==0?7:date.getDate(),
 7     hours=date.getHours(),
 8     minutes=date.getMinutes(),
 9     seconds = date.getSeconds(),
10     timefromSunday=(day*24*3600+hours*3600+minutes*60+seconds)*1000,//星期日凌晨0点到此时的毫秒数
11     time=date.getTime()-timefromSunday;//1970年1月1人至上周日凌晨的毫秒数;
12 
13     return parseInt(timestamp)>time//若时间戳大于周日,则时间戳标志的事件发生在本周;
14 }

三、显示排行榜

在开方数据中渲染完排行榜后,在主域中可通过下面接口获取在开方数据域中创建的canvas;

const openDataContext = wx.getOpenDataContext();
const sharedCanvas = openDataContext.canvas;

 

posted @ 2019-06-10 18:24  snsart  阅读(1380)  评论(1编辑  收藏  举报