Cocos CreatorH5游戏开发cocos2dx

cocos creator 实现原生微信小游戏排行榜

2019-02-20  本文已影响13人  洒一地阳光_217d

本文以玩家身上钱为例,主要讲述在cocos中,如何使用原生的排行榜,显示好友排行
效果如图:


排行1.png 排行2.png

一、准备工作:
1、在打包出的目录里,创建src/myOpenDataContext文件夹,在文件夹myOpenDataContext中新建空js文件index.js,稍等我们再来完善index.js里的内容;
2、在打包出的目录里,在gmae.json中加上"openDataContext": "src/myOpenDataContext"

二、上传玩家数据:
本文以玩家身上金钱为例,注意上传的key

 // 上传玩家数据
        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");
            },
        });

三、向子域发送消息

        // 向子域发送消息 请注意此处key的值,和之前上传的key一致
        // 若实现的是群排行,则需要传shareTicket(可从onShow中获得)
        wx.getOpenDataContext().postMessage({
            keyName: "person_total_money",
            shareTicket: this.shareTicket,
            keyUsername: "username",
            keyUnit: "金蛋",
        });

四、完善子域中的代码(index.js),添加以下代码

        let heightPerUser = 146; // 单个玩家排行的高度
        let widthPerUser = 808; // 单个玩家排行的宽度

        wx.onMessage(function (data) {
            sharedCanvas = wx.getSharedCanvas();
            context = sharedCanvas.getContext('2d');

            // 清除画布上在该矩形区域内的内容
            context.clearRect(0, 0, widthPerUser, heightPerUser * 10);

            wx.getUserCloudStorage({
                keyList: ["username"],

                success: function (res) {
                    // 先获得自己的数据,这样在排行榜中可以突显自己的位置
                    // (若没有这个需求,可以不要这一步)
                    let kvData = res.KVDataList;
                    let myKvData = kvData[0];
                    let myUsername = "";
                    if (myKvData != null) {
                        myUsername = res.KVDataList[0].value;
                    }

                    if (data.shareTicket) {
                        // 获取群同玩成员的游戏托管数据
                        wx.getGroupCloudStorage({
                            shareTicket: data.shareTicket,
                            keyList: [data.keyName, data.keyUsername],

                            success: function (res) {
                                // res.data有所有在玩好友的数据
                                // 包含 头像:avatarUrl, 昵称:nickname, 用户的托管KV数据列表:KVDataList, 
                                drawRankList(res, myUsername, data.keyName, data.keyUsername, data.keyUnit);
                            },

                            fail: function (res) {
                                drawFail();
                            },
                        });
                    } else {
                        // 当前用户所有同玩好友的托管数据
                        wx.getFriendCloudStorage({
                            keyList: [data.keyName, data.keyUsername],

                            success: function (res) {
                                // res.data有所有在玩好友的数据
                                // 包含 头像:avatarUrl, 昵称:nickname, 用户的托管KV数据列表: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 数据列表
            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("共获取到了排行数据数量:" + rankInfo.length);

        //对排行数据排序
        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 {
                // 名次相等,按固定规则排序
                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 = "暂无数据";
            } else {
                st = st + unitName;
            }
            rankInfo[i].score = st;

            if (rankInfo[i].username === myUsername) {
                // 找到自己 方便后面排名时,突显自己
                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("无法获得玩家数据", 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;

            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 > 8) {
                // 仅绘制前10个玩家
                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);
        }
    }

    // 渲染长度
    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);
    }

    //截断过长的文字,用...代替过长的部分,注意这里判断是基于文字的渲染长度
    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("无法获取排行数据", 110, 90);
        context.fillStyle = '#FFDEC0';
        context.fillText("请过段时间再来", 110, heightPerUser + 90);
    }

    function drawEmpty() {
        context.textAlign = 'left';
        context.font = "bold 56px SimHei";
        context.fillStyle = '#FFFFFF';

        context.fillText("无人占据排行榜哦", 110, 90);
        context.fillStyle = '#FFDEC0';
        context.fillText("排行榜数据定期重置", 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;

        // 防止子域响应慢,或者头像加载慢
        // 每隔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);

            // 此处已经拿到了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,至此,绘制排行榜全部完成。

上一篇下一篇

猜你喜欢

热点阅读