要製作排行榜,我們需要使用一個陣列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;