cocos creator 實(shí)現(xiàn)原生微信小游戲排行榜

本文以玩家身上錢為例码泛,主要講述在cocos中收津,如何使用原生的排行榜伙窃,顯示好友排行
效果如圖:

排行1
排行2

一菩颖、準(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柬赐,至此,繪制排行榜全部完成官紫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肛宋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子束世,更是在濱河造成了極大的恐慌悼吱,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件良狈,死亡現(xiàn)場(chǎng)離奇詭異后添,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門遇西,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馅精,“玉大人,你說我怎么就攤上這事粱檀≈薷遥” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵茄蚯,是天一觀的道長(zhǎng)压彭。 經(jīng)常有香客問我,道長(zhǎng)渗常,這世上最難降的妖魔是什么壮不? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮皱碘,結(jié)果婚禮上询一,老公的妹妹穿的比我還像新娘。我一直安慰自己癌椿,他們只是感情好健蕊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著踢俄,像睡著了一般缩功。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上都办,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天嫡锌,我揣著相機(jī)與錄音,去河邊找鬼脆丁。 笑死世舰,一個(gè)胖子當(dāng)著我的面吹牛动雹,可吹牛的內(nèi)容都是我干的槽卫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胰蝠,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼歼培!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起茸塞,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤躲庄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后钾虐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體噪窘,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年效扫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倔监。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片直砂。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖浩习,靈堂內(nèi)的尸體忽然破棺而出静暂,到底是詐尸還是另有隱情,我是刑警寧澤谱秽,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布洽蛀,位于F島的核電站,受9級(jí)特大地震影響疟赊,放射性物質(zhì)發(fā)生泄漏郊供。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一听绳、第九天 我趴在偏房一處隱蔽的房頂上張望颂碘。 院中可真熱鬧,春花似錦椅挣、人聲如沸头岔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峡竣。三九已至,卻和暖如春量九,著一層夾襖步出監(jiān)牢的瞬間适掰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工荠列, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留类浪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓肌似,卻偏偏與公主長(zhǎng)得像费就,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子川队,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容