参考:
cocos版本:2.4.4
微信开发者工具版本:1.05.2103190
demo下载地址:cocos2_4_4_wx_rank.zip
一般微信小游戏排行榜分为世界排行榜和好友排行榜,现在来实现排行榜功能。

原理
为了保护数据,微信好友数据只能在开放域使用,所以除了游戏主项目以外,需要再创建一个项目作为开放域项目。
开放域项目要显示在主域中,需要组件subContextView,这个组件就像小电视,播放开放域的界面。
当显示世界排行榜时,关闭小电视。当显示好友排行榜时,打开小电视。

一 创建主项目
创建一个普通的ts项目

主场景只放一个排行榜按钮

点击排行榜按钮,打开排行榜面板

点击世界排行榜时,隐藏subContextView;点击好友排行榜时,显示subContextView,并使用微信接口postMessage通知开放域我要显示好友排行榜。
RankPanel.ts代码如下:
const { ccclass, property } = cc._decorator;
/**
* 排行榜
* @author chenkai 2021.3.2
*/
@ccclass
export default class RankPanel extends cc.Component {
@property(cc.Toggle) //世界排行榜按钮
worldToggle: cc.Toggle = null;
@property(cc.Toggle) //好友排行榜按钮
friendToggle: cc.Toggle = null;
@property(cc.Node) //世界排行榜
worldRank: cc.Node = null;
@property(cc.Node) //好友排行榜
friendRank: cc.Node = null;
@property(cc.Button) //关闭按钮
closeBtn: cc.Button = null;
@property(cc.SubContextView) //开放域容器
subContextView: cc.SubContextView = null;
onLoad() {
//按钮事件
this.worldToggle.node.on("toggle", this.onToggleTap, this);
this.friendToggle.node.on("toggle", this.onToggleTap, this);
this.closeBtn.node.on(cc.Node.EventType.TOUCH_END, this.onCloseTap, this);
//默认显示世界排行榜
this.showWorldRank();
}
/**关闭排行榜 */
private onCloseTap() {
this.node.removeFromParent(false);
this.node.destroy();
}
/**点击切换排行榜 */
private onToggleTap(e: cc.Toggle) {
switch (e) {
case this.worldToggle:
this.showWorldRank();
break;
case this.friendToggle:
this.showFriendRank();
break;
}
}
/**显示世界排行榜 */
private showWorldRank() {
this.worldRank.active = true;
this.friendRank.active = false;
this.subContextView.node.active = false;
}
/**显示好友排行榜 */
private showFriendRank() {
this.worldRank.active = false;
this.friendRank.active = true;
this.subContextView.node.active = true;
window["wx"].getOpenDataContext().postMessage({ cmd: "ShowFriendRank", data: null });
}
}
因为好友数据里是空的,所以每次进入排行榜,我们就使用setUserCloudStorage保存一个测试数据,托管数据的key值是score,获取托管数据是根据这个key值来获取的。
玩家的分数score=999,这个保存函数可以在Main.ts里或者RankPanel.ts里调用。
/**保存用户数据 */
public setUserCloudStorage() {
return new Promise((resolve, reject) => {
//测试数据
let value = {
"wxgame": {
"score": 999,
"update_time": 1513080573
},
"cost_ms": 36500
}
let key = "score";
let KVData = { key: key, value: JSON.stringify(value) };
let KVDataList = [KVData];
window["wx"].setUserCloudStorage({
KVDataList: KVDataList,
success(res) {
console.log("[WxPlatform] 保存用户数据成功:", KVDataList);
resolve(true);
},
fail(res) {
console.log("[WxPlatform] 保存用户数据失败:", KVDataList);
reject(false);
}
})
});
}
构建发布平台选择微信小游戏,设置开放域代码目录为wxOpenData,这个名称必须和开放域项目构建发布时的游戏名称一致。开放域游戏名称后面会讲到。

发布的项目用微信小游戏工具打开,没有appid,可以选择工具提供的测试号。

二 创建开放域项目
同样创建一个ts项目,设置场景和主项目的subContextView一样大小,例如500x500。

在开放域项目中创建好友排行榜面板

当主项目点击好友排行榜,使用微信接口postMessage向开放域发送消息,开放域用window["wx"].onMessage来接收消息
//接收主域来的消息
window["wx"].onMessage((obj)=>{
switch (obj.cmd) {
case "ShowFriendRank": //显示好友排行榜
break;
case "HideFriendRank": //隐藏好友排行榜
break;
}
});
当收到显示好友排行榜的消息时,开放域使用getFriendCloudStorage获取好友数据,KVDataList就是之前保存的托管数据,key值是socre,因为只有一条数据,所以取KVDataList[0]也可以
根据好友数据创建排行榜列表Item
window["wx"].getFriendCloudStorage({
keyList: keyList,
success:(res)=>{
console.log("[openData] 获取所有好友数据成功:", res);
let data = res.data;
for (var i = 0; i < data.length; i++) {
//解析数据
let userInfo: any = data[i];
let openid = userInfo.openid; //微信好友openid
let nickname = userInfo.nickname; //微信好友昵称
let avatarUrl = userInfo.avatarUrl; //微信好友头像
let KVDataList = userInfo.KVDataList; //微信好友托管数据
let score = 0; //从托管数据中解析出分数
if (KVDataList[0] != null) {
score = JSON.parse(KVDataList[0].value).wxgame.score;
}
//to do 创建item
}
}, fail(res) {
//to do
}
});

微信的头像加载,使用远程加载loadRemote。
/**加载微信头像 */
public setSprite(icon: cc.Sprite, avatarUrl: string) {
if (avatarUrl == null || avatarUrl.length == 0) {
icon.spriteFrame = null
} else {
cc.assetManager.loadRemote(avatarUrl, { ext: '.png' }, (err, texture: any) => {
icon.spriteFrame = new cc.SpriteFrame(texture);
});
}
}
构建发布开放域
游戏名称wxOpenData,必须和主项目的构建发布时配置的开放域代码目录一致。
发布平台选择微信小游戏开放数据域
发布路径是主项目微信小游戏的发布目录: C:\Users\lexun\Desktop\cocos2_4_4_wx_rank\client\build\wechatgame

到这里,基本完成了。每次修改主项目或者开放域项目,都必须重新构建发布一次,微信开放者工具会自动更新编译。
浙公网安备 33010602011771号