本文以玩家身上錢為例码泛,主要講述在cocos中收津,如何使用原生的排行榜伙窃,顯示好友排行
效果如圖:
一菩颖、準(zhǔn)備工作:
1、在打包出的目錄里对供,創(chuàng)建src/myOpenDataContext文件夾位他,在文件夾myOpenDataContext中新建空js文件index.js,稍等我們?cè)賮硗晟苅ndex.js里的內(nèi)容产场;
2鹅髓、在打包出的目錄里,在gmae.json中加上"openDataContext": "src/myOpenDataContext"
二京景、上傳玩家數(shù)據(jù):
本文以玩家身上金錢為例窿冯,注意上傳的key
// 上傳玩家數(shù)據(jù)
wx.setUserCloudStorage({
KVDataList: [{
key: "person_total_money",
value: money
}, {
key: "username",
value: username
}],
success: function (res) {
console.log("upload success");
},
fail: function (res) {
console.log("upload fail");
},
});
三、向子域發(fā)送消息
// 向子域發(fā)送消息 請(qǐng)注意此處key的值确徙,和之前上傳的key一致
// 若實(shí)現(xiàn)的是群排行醒串,則需要傳shareTicket(可從onShow中獲得)
wx.getOpenDataContext().postMessage({
keyName: "person_total_money",
shareTicket: this.shareTicket,
keyUsername: "username",
keyUnit: "金蛋",
});
四、完善子域中的代碼(index.js)鄙皇,添加以下代碼
let sharedCanvas = null;
let context = null;
let heightPerUser = 146; // 單個(gè)玩家排行的高度
let widthPerUser = 808; // 單個(gè)玩家排行的寬度
wx.onMessage(function (data) {
if (sharedCanvas == null) {
sharedCanvas = wx.getSharedCanvas();
}
if (context == null) {
// 獲取畫布對(duì)象的繪圖上下文
context = sharedCanvas.getContext('2d');
}
// 清除畫布上在該矩形區(qū)域內(nèi)的內(nèi)容
context.clearRect(0, 0, widthPerUser, heightPerUser * 10);
wx.getUserCloudStorage({
keyList: ["username"],
success: function (res) {
// 先獲得自己的數(shù)據(jù)芜赌,這樣在排行榜中可以突顯自己的位置
// (若沒有這個(gè)需求,可以不要這一步)
let kvData = res.KVDataList;
let myKvData = kvData[0];
let myUsername = "";
if (myKvData != null) {
myUsername = res.KVDataList[0].value;
}
if (data.shareTicket) {
// 獲取群同玩成員的游戲托管數(shù)據(jù)
wx.getGroupCloudStorage({
shareTicket: data.shareTicket,
keyList: [data.keyName, data.keyUsername],
success: function (res) {
// res.data有所有在玩好友的數(shù)據(jù)
// 包含 頭像:avatarUrl, 昵稱:nickname, 用戶的托管KV數(shù)據(jù)列表:KVDataList,
drawRankList(res, myUsername, data.keyName, data.keyUsername, data.keyUnit);
},
fail: function (res) {
drawFail();
},
});
} else {
// 當(dāng)前用戶所有同玩好友的托管數(shù)據(jù)
wx.getFriendCloudStorage({
keyList: [data.keyName, data.keyUsername],
success: function (res) {
// res.data有所有在玩好友的數(shù)據(jù)
// 包含 頭像:avatarUrl, 昵稱:nickname, 用戶的托管KV數(shù)據(jù)列表:KVDataList,
drawRankList(res, myUsername, data.keyName, data.keyUsername, data.keyUnit);
},
fail: function (res) {
drawFail();
},
});
}
},
fail: function (res) {
console.log("getUserCloudStorage 失敗");
drawFail();
}
});
});
},
function drawRankList(res, myUsername, keyName, keyUsername, unitName = "") {
if (res == null || res.data == null || res.data.length == null || res.data.length < 1) {
drawFail();
return;
}
//初始化信息
let data = res.data;
let rankInfo = [];
for (let i in data) {
let personData = data[i];
let usernameKeyIndex = -1;
let keyNameIndex = -1;
let KVDataLen = personData.KVDataList.length; // KVDataList是用戶的托管 KV 數(shù)據(jù)列表
for (let i = 0; i < KVDataLen; i++) {
if (personData.KVDataList[i].key === keyUsername) {
usernameKeyIndex = i;
} else if (personData.KVDataList[i].key === keyName) {
keyNameIndex = i;
}
}
let obj = {};
if (personData.KVDataList[keyNameIndex] != null) {
obj.score = personData.KVDataList[keyNameIndex].value;
} else {
obj.score = "-1";
}
if (personData.nickname) {
obj.nickname = personData.nickname;
}
if (personData.avatarUrl) {
obj.headimgurl = personData.avatarUrl;
}
if (personData.KVDataList[usernameKeyIndex] != null) {
obj.username = personData.KVDataList[usernameKeyIndex].value;
}
obj.rank = 0;
obj.isSelf = false;
rankInfo.push(obj);
}
console.log("共獲取到了排行數(shù)據(jù)數(shù)量:" + rankInfo.length);
//對(duì)排行數(shù)據(jù)排序
rankInfo.sort(function (m, n) {
let intM = parseInt(m.score);
let intN = parseInt(n.score);
if (typeof intM !== "number" || intM == NaN || intM < 0) {
intM = -1;
}
if (typeof intN !== "number" || intN == NaN || intN < 0) {
intN = -1;
}
m.score = intM;
n.score = intN;
if (intM > intN) {
return -1;
} else if (intM < intN) {
return 1;
} else {
// 名次相等伴逸,按固定規(guī)則排序
if (m.nickname > n.nickname) {
return 1;
}
if (m.nickname < n.nickname) {
return -1;
}
return 0;
}
});
let rank = 0;
for (let i = 0; i < rankInfo.length; i++) {
rank++;
rankInfo[i].rank = rank;
}
for (let i = 0; i < rankInfo.length; i++) {
let st = rankInfo[i].score;
if (st == -1) {
st = "暫無數(shù)據(jù)";
} else {
st = st + unitName;
}
rankInfo[i].score = st;
if (rankInfo[i].username === myUsername) {
// 找到自己 方便后面排名時(shí)缠沈,突顯自己
rankInfo[i].isSelf = true;
}
}
draw(rankInfo);
}
function draw(rankInfo) {
for (let i = 0; i < rankInfo.length; i++) {
let rankItem = rankInfo[i];
let y = i * heightPerUser;
context.textAlign = 'left';
if (rankItem == null || rankItem == {}) {
context.fillStyle = "#FFDEC0";
context.font = "bold 56px SimHei";
context.fillText("無法獲得玩家數(shù)據(jù)", 110, y + 90);
continue;
}
if (rankItem.isSelf) {
context.fillStyle = "#a37d56";
context.fillRect(0, y, widthPerUser, heightPerUser);
}
let nickname = rankItem.nickname;
let score = rankItem.score;
let headimgurl = rankItem.headimgurl;
let rank = "" + rankItem.rank;
// 繪制分?jǐn)?shù)
let scoreTextLen = renderLengthOf(score);
let fontReduce = Math.floor(scoreTextLen - 11);
if (fontReduce < 0) {
fontReduce = 0;
}
context.font = (48 - fontReduce) + "px SimHei";
context.fillStyle = '#FFDEC0';
context.fillText(score, 344, y + 126);
// 繪制昵稱
context.fillStyle = "#FFFFFF";
nickname = trimString(nickname, 13);
context.font = "48px SimHei";
context.fillText(nickname, 344, y + 58);
// 繪制頭像
let img = wx.createImage();
img.src = headimgurl;
img.onload = function (res) {
let heightImg = res.target.height;
let widthImg = res.target.width;
context.drawImage(img, 0, 0, widthImg, heightImg, 160, y + 10, 124, 124);
}
// 繪制排名
context.textAlign = 'center';
drawRankNum(rank, y);
if (i >= 10) {
// 僅繪制前10個(gè)玩家
break;
}
}
for (let j = 0; j < 10; j++) {
let y = j * heightPerUser;
context.fillStyle = "#a5805a";
context.fillRect(0, y + heightPerUser - 4, widthPerUser, 2);
context.fillStyle = "#d5ad88";
context.fillRect(0, y + heightPerUser - 2, widthPerUser, 2);
}
}
// 渲染長(zhǎng)度
function renderLengthOf(str) {
var len = 0;
for (var i = 0; i < str.length; i++) {
if (isChinese(str.charAt(i))) {
len += 2;
} else {
len += 1;
}
}
return len;
},
//判斷是不是中文
function isChinese(char) {
var reCh = /[u00-uff]/;
return !reCh.test(char);
}
//截?cái)噙^長(zhǎng)的文字,用...代替過長(zhǎng)的部分错蝴,注意這里判斷是基于文字的渲染長(zhǎng)度
function trimString(string, renderLengthMax) {
let len = string.length;
let renderLen = renderLengthOf(string);
let l = 0;
if (renderLen > renderLengthMax) {
let lenToSubstr = 0;
for (let i = 0; i < len; i++) {
if (isChinese(string[i])) {
l += 2;
} else {
l += 1;
}
lenToSubstr++;
if (l >= renderLengthMax) {
string = string.substr(0, lenToSubstr);
string = string + "..";
break;
}
}
}
return string;
}
function drawRankNum(rank, y) {
if (rank <= 3) {
// 繪制排名的名次圖片 此處僅繪制前3名
let img = wx.createImage();
img.src = "customRes/rank" + rank + ".png";
img.onload = function (res) {
let heightImg = res.target.height;
let widthImg = res.target.width;
context.drawImage(img, 0, 0, widthImg, heightImg, 10, y + 14, 114, 112)
}
} else if (rank < 10) {
context.font = "bold 64px Calibri";
context.fillText(rank, 68, y + 94);
} else if (rank < 100) {
context.font = "bold 60px Calibri";
context.fillText(rank, 68, y + 94);
} else {
context.font = "bold 60px Calibri";
context.fillText("99+", 64, y + 94);
}
}
function drawFail() {
context.textAlign = 'left';
context.font = "bold 56px SimHei";
context.fillStyle = '#FFFFFF';
context.fillText("無法獲取排行數(shù)據(jù)", 110, 90);
context.fillStyle = '#FFDEC0';
context.fillText("請(qǐng)過段時(shí)間再來", 110, heightPerUser + 90);
}
function drawEmpty() {
context.textAlign = 'left';
context.font = "bold 56px SimHei";
context.fillStyle = '#FFFFFF';
context.fillText("無人占據(jù)排行榜哦", 110, 90);
context.fillStyle = '#FFDEC0';
context.fillText("排行榜數(shù)據(jù)定期重置", 110, heightPerUser + 90);
}
五洲愤、在游戲中將子域中的排行榜繪制出來
init: function () {
let openDataContext = wx.getOpenDataContext();
this.sharedCanvas = openDataContext.canvas;
this.sharedCanvas.width = 808;
this.sharedCanvas.height = 1460;
},
startRefesh: function () {
if (!this.sharedCanvas) {
this.init();
}
this.refreshStart = true;
// 防止子域響應(yīng)慢,或者頭像加載慢
// 每隔0.7s 繪制1次 總共繪制6次
this.refreshTimeRest = 6;
this.refreshTimer = 0.4
this.refreshInterval = 0.7;
},
update: function (dt) {
if (this.texture == null) {
this.texture = new cc.Texture2D();
}
if (this.refreshStart && this.refreshTimeRest > 0) {
// 每隔0.7s 繪制1次 總共繪制6次
this.refreshTimer += dt;
if (this.refreshTimer > this.refreshInterval) {
this.refreshTimer -= this.refreshInterval;
this.refreshTimeRest--;
this.show();
}
}
},
show: function () {
if (this.spriteFrame) {
this.spriteFrame.clearTexture();
}
if (this.texture) {
if (!this.sharedCanvas) {
this.init()
}
this.texture.initWithElement(this.sharedCanvas);
this.texture.handleLoadedTexture();
this.spriteFrame = new cc.SpriteFrame(this.texture);
// 此處已經(jīng)拿到了spriteFrame顷锰,可以隨便放在需要的sprite上了
this.rankSprite.spriteFrame = this.spriteFrame;
}
},
hide: function () {
if (this.spriteFrame) {
this.spriteFrame.clearTexture();
this.spriteFrame = null;
}
if (this.texture) {
this.texture.destroy();
}
},
OK柬赐,至此,繪制排行榜全部完成官紫。