当前位置:   article > 正文

《Cocos Creator游戏实战》实现微信小游戏排行榜_cocoscreator 排行榜

cocoscreator 排行榜

实现微信小游戏排行榜

 

完成主域项目

完成子域项目

构建运行


在游戏中加入排行榜是非常有必要的。本节教程就带大家了解下如何在微信小游戏中加入排行榜。

运行效果如下:

Cocos Creator版本:2.2.0

后台回复"排行榜",获取该项目完整文件:

其实Cocos官方在文档中已经提供了较为详细的说明,并给出了一个Demo,大家可以先去了解下。

请大家点击该链接查看微信开放数据域各个API的用法。

完成主域项目

下图显示了笔者在主域项目中创建的节点:

1. bg节点用作背景,颜色为白色。

2. showRanksBtn是一个按钮节点,用于显示和关闭排行榜。

3. WXSubContextView节点非常关键,我们必须通过它来显示开放数据域(以下统称子域)中的贴图。它上面挂有WXSubContextView组件。

注:对各个节点的尺寸和属性设置,请大家直接打开项目去查看下,笔者这里不再赘述。

进行适当布局后,显示如下:

新建一个ShowRanks.js脚本,并挂到Canvas节点上。脚本编写如下:

  1. // ShowRanks.js
  2. cc.Class({
  3. extends: cc.Component,
  4. properties: {
  5. wxSubContextView: cc.Node //主域视窗容器
  6. },
  7. // LIFE-CYCLE CALLBACKS:
  8. onLoad () {
  9. // 获取授权
  10. this.initUserInfoButton();
  11. },
  12. showRanks() {
  13. if (typeof wx === 'undefined') {
  14. return;
  15. }
  16. if (!this.wxSubContextView.active) {
  17. // 设置容器可见
  18. this.wxSubContextView.active = true;
  19. // 设置随机数(把这个当做玩家的分数)
  20. let score = Math.round(Math.random()*10);
  21. // 发送结算分数到开放域
  22. wx.getOpenDataContext().postMessage({
  23. message: score
  24. });
  25. }
  26. else {
  27. // 设置容器不可见,即关闭排行榜,并让开放域清空排名信息
  28. this.wxSubContextView.active = false;
  29. wx.getOpenDataContext().postMessage({
  30. message: 'clear'
  31. });
  32. }
  33. },
  34. initUserInfoButton () {
  35. // 微信授权,此代码来自Cocos官方
  36. if (typeof wx === 'undefined') {
  37. return;
  38. }
  39. let systemInfo = wx.getSystemInfoSync();
  40. let width = systemInfo.windowWidth;
  41. let height = systemInfo.windowHeight;
  42. let button = wx.createUserInfoButton({
  43. type: 'text',
  44. text: '',
  45. style: {
  46. left: 0,
  47. top: 0,
  48. width: width,
  49. height: height,
  50. lineHeight: 40,
  51. backgroundColor: '#00000000',
  52. color: '#00000000',
  53. textAlign: 'center',
  54. fontSize: 10,
  55. borderRadius: 4
  56. }
  57. });
  58. button.onTap((res) => {
  59. if (res.userInfo) {
  60. // 可以在这里获取当前玩家的个人信息,如头像、微信名等。
  61. console.log('授权成功!');
  62. }
  63. else {
  64. console.log('授权失败!');
  65. }
  66. button.hide();
  67. button.destroy();
  68. });
  69. },
  70. });

1. initUserInfoButton这个方法用于用户授权,大家不必对该方法留意过多,照抄就行(调用微信开放数据域中的方法前需要用户授权)。

2. 重点是showRanks方法,每次玩家点击按钮后,都会调用该方法。

其中我们首先判断WXSubContextView节点是否可见,若不是,则显示可见并调用wx.getOpenDataContext().postMessage()发送当前玩家的分数,与子域进行通信请求生成排行榜内容。

若WXSubContextView可见,那么我们设置其active属性为false,并再次与子域通信,请求删除之前生成的排行榜信息。如果不删除,那么等玩家下次再点击按钮打开排行榜时,会发现有重复内容出现。

完成子域项目

子域节点内容如下:

1. 首选确保Canvas节点大小同主域中的WXSubContextView大小相同,记得将Fit Height和Fit Width都勾选上。

2. bg为背景,颜色为白色,跟主域背景颜色一样(这由项目素材决定,不必跟笔者这里一样)。

3. rankScrollView是一个滑动视窗节点(笔者删除了一些用不到的子节点),读者可以将该视窗的背景换成自己的素材。

注意笔者这里在content节点上加了一个Layout组件,并将Type和Resize Mode分别设置为VERTICAL和CONTAINER。因为content下会有很多的子节点生成,这样做可以更好地排版,content高度也可以自动调整。

效果如下:

现在我们需要一个预制,在该预制节点上会显示各个玩家的信息。

  1. rank子节点用于显示名次。
  2. avatar子节点用于显示微信头像。
  3. nameTip子节点显示固定文本Name:。
  4. scoreTip子节点显示固定文本Score:。
  5. name子节点显示玩家的微信名。
  6. score子节点显示玩家的分数。

设置好后的效果如下:

接下来新建OpenData.js脚本,在properties中添加以下两个属性:

  1. // OpenData.js
  2. properties: {
  3. itemPrefab: cc.Prefab, // item预制
  4. content: cc.Node, // content节点
  5. },

onLoad方法实现如下:

  1. // OpenData.js
  2. onLoad () {
  3. if (typeof wx === 'undefined') {
  4. return;
  5. }
  6. wx.onMessage( data => {
  7. if (data.message) {
  8. if (data.message != 'clear') {
  9. this.score = data.message; // 将主域传过来的分数保存在this.score中
  10. this.compareOldNewScore(); // 将当前玩家的新分数和之前玩的分数进行比较
  11. this.allInfoList = []; // 所有玩家的数据保存在这个数组中,用于排序
  12. this.getFriendInfo(); // 获取同城好友信息(当前玩家的信息也会返回)
  13. // this.getPlayerInfo(); // 用于读者Demo测试,实际项目中调用getFriendInfo()
  14. }
  15. else {
  16. this.content.removeAllChildren(); // 关闭排行榜时清空节点
  17. }
  18. }
  19. });
  20. },

在子域中我们调用wx.onMessage方法获取从主域传过来的数据。如果主域传来的是'clear',那么我们就清空content节点下的所有子节点;如果传来的是分数,那么我们首先调用this.compareOldNewScore方法来比较该分数与之前的云托管分数。接着调用getFriendInfo()来获取所有玩家的信息(在该方法中会进行排名)。

由于不是实际上线项目(没有其他好友云托管的数据),所以读者在微信开发工具上运行该项目后,会发现生成的排名只有读者一人。那为了缓解这种尴尬,笔者放了getPlayerInfo方法,读者可以使用该方法来生成多个玩家信息(其实就是多个自己啦)。当然实际项目中要用getFriendInfo()。

this.compareOldNewScore方法实现如下:

  1. // OpenData.js
  2. compareOldNewScore() {
  3. // 将传过来的新分数和之前玩的分数进行比较
  4. wx.getUserCloudStorage({
  5. keyList: ['score'],
  6. success: (res) => {
  7. if (res.KVDataList.length) {
  8. let KVData = res.KVDataList[0];
  9. let storedScore = Number(KVData['value']);
  10. if (this.score > storedScore) {
  11. // 如果新分数大于存储分数,则将新分数存入云托管
  12. let newKVData = {key: 'score', value: String(this.score)}
  13. this.setNewCloudScore(newKVData);
  14. }
  15. }
  16. else {
  17. // 如果第一次玩,那么直接将传过来的分数设置到云托管
  18. let newKVData = {key:'score', value:String(this.score)}
  19. this.setNewCloudScore(newKVData);
  20. }
  21. },
  22. fail: (res) => {
  23. console.log(res);
  24. }
  25. });
  26. },

在该方法中我们调用 wx.getUserCloudStorage()来获取自己的云托管分数(之前玩过保存到云托管上的分数)。如果调用成功,则首选判断有没有云托管分数(因为这可能是第一次玩),如果没有那么我们直接创建一个newKVData变量,并调用setNewCloudScore方法将传过来的分数设置到云托管。如果之前玩过,那么我们来比较下新分数和云托管上的分数,看看哪个比较高。若新分数较大,则同理将新分数存入云托管。

setNewCloudScore方法实现如下:

  1. setNewCloudScore (newKVData) {
  2. // 设置新云托管分数(第一次游戏时,也调用该方法设置云托管分数)
  3. wx.setUserCloudStorage({
  4. KVDataList: [newKVData],
  5. success: (res) => {
  6. console.log('更新玩家分数成功!');
  7. },
  8. fail: (res) => {
  9. console.log(res);
  10. }
  11. });
  12. },

大家可以去微信小游戏API文档上看下具体解释。

更新:请读者在主域中比较分数,并调用wx.setUserCloudStorage这个API来更新云托管分数(该API可以在主域中使用),否则玩家只有在点击了排行榜按钮后才会将分数存入云托管。


逻辑:将每局分数与存储在本地的最高分进行比较,如果超过历史最高分数则同时更新本地和云托管数据。不需要再将分数传到子域。

getPlayerInfo方法笔者略过,这里重点讲下getFriendInfo方法:

  1. // OpenData.js
  2. getFriendInfo () {
  3. // 获取同城好友信息(包括自身)
  4. wx.getFriendCloudStorage({
  5. keyList: ['score'],
  6. success: (res) => {
  7. for (let i = 0; i < res.data.length; i++) {
  8. // 获取玩家微信名,头像url和分数
  9. let nickName = res.data[i].nickname;
  10. let avatarUrl = res.data[i].avatarUrl;
  11. let score = 0;
  12. if (res.data[i].KVDataList.length)
  13. score = res.data[i].KVDataList[0]['value'];
  14. // 加入到数组中
  15. this.allInfoList.push({
  16. nickName: nickName,
  17. avatarUrl: avatarUrl,
  18. score: score
  19. });
  20. }
  21. // 开始排名
  22. this.makeRanks();
  23. },
  24. fail: (res) => {
  25. console.log(res);
  26. }
  27. });
  28. },

在该方法中笔者调用wx.getFriendCloudStorage()获取同城好友的云托管数据(只要好友玩过你的游戏,那他们的信息就可以从云托管中读取到)。注意wx.getFriendCloudStorage()也会返回自身的数据。

如果调用成功,我们就循环读取玩家的信息,并将数据添加到allInfoList数组中。获取完毕之后,就可以调用makeRanks方法进行排名了。

makeRanks方法编写如下:

  1. // OpenData.js
  2. makeRanks () {
  3. // 首先将allInfoList内部元素进行排序,根据分数来降序排列
  4. this.allInfoList.sort((a, b) => {
  5. return b['score'] - a['score'];
  6. });
  7. // 根据各个玩家的分数制作排名
  8. for (let i=0; i<this.allInfoList.length; i++) {
  9. let nickName = this.allInfoList[i]['nickName'];
  10. let avatarUrl = this.allInfoList[i]['avatarUrl'];
  11. let score = this.allInfoList[i]['score'];
  12. this.createItem(i+1, nickName, avatarUrl, score);
  13. }
  14. },

第一步必须先对allInfoList内的元素按照分数进行排序,分数高排在最前。

接着循环数组,调用createItem方法生成预制:

  1. // OpenData.js
  2. createItem (rank, nickName, avatarUrl, score) {
  3. // 生成item
  4. let item = cc.instantiate(this.itemPrefab);
  5. // 排名
  6. item.children[0].getComponent(cc.Label).string = String(rank);
  7. // 微信名
  8. item.children[4].getComponent(cc.Label).string = nickName;
  9. // 分数
  10. item.children[5].getComponent(cc.Label).string = score;
  11. // 头像
  12. cc.loader.load({url: avatarUrl, type: 'png'}, (err, texture) => {
  13. if (err) console.error(err);
  14. item.children[1].getComponent(cc.Sprite).spriteFrame = new cc.SpriteFrame(texture);
  15. });
  16. // 添加到content中
  17. this.content.addChild(item);
  18. }

构建运行

对主域项目和子域项目分别进行构建(哪个先构建没关系)。

主域:

  1. 发布平台选择微信小游戏。
  2. appid中填写自己小游戏的appid。
  3. 开放数据域代码目录填写子域项目文件夹名称。
  4. 填好之后点击构建。

子域:

  1. 发布平台选择微信小游戏开放数据域。
  2. 选好之后点击构建。

接着我们将子域项目下build文件夹中构建好的OpenDataDomain文件夹拷贝到主域项目下build文件夹下的wechatgame文件夹中:

P.S.其实我们在构建子域项目前修改下发布路径到主域的wechatgame文件夹中也可以。

如果微信开发者工具在引擎中配置好了的话,那我们打开主域项目的构建面板,点击运行就行了。

好,本节教程就到这,希望大家有所收获!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/932603
推荐阅读
相关标签
  

闽ICP备14008679号