Implement micro-channel Laya game based on the game engine rankings

We all know that small and micro-channel game program currently full of thunder, many companies have gradually increased the related business lines to quickly promote their products and to seize the user groups. When it comes to micro-channel game, you have to mention rankings this function, the current gaming industry, it seems inseparable from the rankings this important feature, users are relying retained a large part of this seemingly insignificant module. So, micro-channel mini-games specifically how to implement the aid laya engine rankings this function? We first look at the final renderings:

image

According to the official micro letter saying, if we want to buddy relationship chain data of the official micro-channel use, we can not draw charts directly in the project, we need to draw charts by means of open fields:

image

If you want to display user data acquired by the chain of API, such as drawing charts and other business scenarios, we need to draw the chart sharedCanvason the primary domain and then the sharedCanvas rendered on screen. In simple terms, sharedCanvas open data is the primary domain and the domain can access a off-screen canvas. In an open call wx.getSharedCanvas data field () will return sharedCanvas. More details can go Tell me introduce network: https: //mp.weixin.qq.com/debug/wxagame/dev/tutorial/open-ability/open-data.html

Then we come to the actual hands-on about it.

Primary Domain Draw

The effect can be seen through it, on our list is a pop form displayed, since the open field is only responsible for drawing charts UI, so, other than UI and interaction we need to draw and processed in the primary domain. Thus, where the pop dialogneed to be drawn in the primary domain, then the corresponding position information and the length and width of chart displays require mapping into the open field, specific code as follows:


    /**
     * 显示排行榜数据
     */
    function onRankInfoLoad(){
        console.log("查看排行榜~");
        var dialog = new RankDialogUI();
        showShareCanvas();
        // 解决显示对象和鼠标错位而导致的排行榜滑动无效问题
        var globalPosition = dialog.ranking_list.localToGlobal(new Laya.Point());
        var originMatrix = Laya.stage._canvasTransform;
        var mat = new Laya.Matrix(originMatrix.a, 0, 0, originMatrix.d, globalPosition.x * originMatrix.a, globalPosition.y * originMatrix.d);
        wxPostMessage({
            command: 0,
            text: "设置开放域canvas大小",
            canvasData: {
                width: rankViewWidth * mat.a, height: rankViewHeight * mat.d, matrix: mat
            },
            isLoad: false
        }, null, function (message) {
            console.log("再次往开放域发请求");
            window['wx'].postMessage({
                command: 1,
                text: '开放域加载资源',
            });
        });
    
        Laya.stage.addChild(dialog);
        dialog.ranking_list.visible = false;
        dialog.popup();
         Laya.timer.once(400,this,function(){
            wxPostMessage({
                command: 3,
                text: "获取排行榜数据~"
            }, null, function (message) {
                console.log("获取排行榜的回调~");
            });
         });
        
    
        dialog.btn_rank_dialog_share.on(Laya.Event.CLICK, this, onGameRankShare);
        dialog.btn_rank_dialog_back.on(Laya.Event.CLICK, this, onDialogClose);
        function onDialogClose(){
            wxPostMessage({
                command: 4,
                text: "关闭排行榜~"
            }, null, function (message) {
                console.log("关闭排行榜的回调~");
            });
            dialog.close();
        }

        function onGameRankShare(){
            console.log("分享排行榜~");
            window['wx'].showShareMenu({
                withShareTicket:false,
                success:function(res){
                    console.log("开启转发成功~");
                },
                fail:function(res){
                    console.log("开启转发失败~");
                },
                complete:function(res){

                }
            });
            window['wx'].onShareAppMessage(function () {
                return {
                    title: '我在飞机大战游戏中排名又上升了,快来挑战我吧~'
                }
            })
            window['wx'].shareAppMessage({

                title: '我在飞机大战游戏中排名又上升了,快来挑战我吧~',
                imageUrl: canvas.toTempFilePathSync({
                    x: (screenWidth - rankViewWidth)/2 - 10,
                    y: (screenHeight - rankViewHeight)/2+80,
                    width: (rankViewWidth - 30)*4,
                    height: (rankViewHeight - 40)*4,
                    destWidth: 500,
                    destHeight: 600
                })
            });
        }
    }
    
    /**
     * 设置共享Canvas
     */
    function showShareCanvas(){
            window['sharedCanvas'].width = rankViewWidth;
            window['sharedCanvas'].height = rankViewHeight;
            //主域显示开放域内容???
            //window['sharedCanvas'].sharedCanvas = window['wx'].getOpenDataContext().canvas;
            Laya.timer.once(1000, this, function () {
                var sprite = new Laya.Sprite();
                sprite.zOrder = 1008;
                sprite.pos(0, 0);
                var texture = new Laya.Texture(window['sharedCanvas']);
                texture.bitmap.alwaysChange = true;//小程序使用,非常费
                sprite.graphics.drawTexture(texture, (screenWidth - rankViewWidth)/2, (screenHeight - rankViewHeight)/2, texture.width, texture.height);
                Laya.stage.addChild(sprite);
            });
    }

/**
     * 向开放域发送消息,并接收开放域返回过来的数据,
     * 可根据发送参数和接收数据在主域这边进行下步处理
     * @param message
     * @param caller
     * @param callback
     */
    function wxPostMessage(message, caller, callback){
        window['wx'].postMessage(message);
        Laya.timer.once(400, this, function (){
            //回调处理
            if (caller == null || caller == undefined) {
                callback(message);
            } else {
                caller.callback(message);
            }
        });
    }

Message sent by the main body side carries a command field, the function code for performing the different open field, here divided into: resource load command, initialize the charts Size command, acquires relationship chain (charts), and command data Close charts command, you can increase or decrease according to the specific needs of business properly.

Open Draw domain

根据官方的说明,开放数据域 是一个封闭、独立的 JavaScript 作用域。要让代码运行在开放数据域,需要在 game.json 中添加配置项 openDataContext 指定开放数据域的代码目录。添加该配置项表示小游戏启用了开放数据域,这将会导致一些 限制。这些限制主要包含:

  • 无法设置sharedCanvas的宽高
  • 只能使用有限的接口(如逐帧动画、Timer、触摸事件以及获取和设置关系链数据等接口)

下面我们一步步来在开放域绘制排行榜。

  1. 首先,需要新建一个项目作为开放域,这个项目目录是与主域项目平行的(主域就是未做排行榜之前的项目目录),比如我的项目目录是这样的:

    image

  2. 接着,我们需要在开放域中接收主域发送的消息并处理不同的功能命令,UI就不放了,看看具体代码吧:

    /**
         * 监听从主域发过来的消息
         */
        function wxOnMessage(){
            if(window['wx'] != undefined){
                window['wx'].onMessage(function (message){
                    dispatchMessage(message);
                });
            }else{
                console.log("微信接口无法使用~");
            }
        }
        /**
         * 处理消息
         * @param {*} message 
         */
        function dispatchMessage(message){
            switch(message.command){
                //设置开放域画布大小
                case 0:
                    sample.setCanvasSize(message.canvasData);
                    break;
                //加载资源
                case 1:
                    sample.loadResource();
                    break;
                //写入排行榜数据
                case 2:
                    sample.writeRankingData(message.rankingData);
                    break;
                //获取微信排行榜数据
                case 3:
                    sample.getRankingData();
                    break;
                //关闭排行榜
                case 4:
                    sample.closeRankingDialog();
                    break;
                default:
    
                    console.log(JSON.stringify(message));
            }
        }
        /**
         * 设置开放域画布大小
         * @param {*} size 
         */
         _proto.setCanvasSize = function(size){
            console.log("设置开放域canvas大小~");
            window['sharedCanvas'].width = size.width;
            window['sharedCanvas'].height = size.height;
            //Laya.stage.width = size.width;
            //Laya.stage.width = size.height;
            /**
             * 将主域的canvasTransform映射到开放域
             */
            if(size.matrix!=null){
                console.log("收到主域的同步canvasTransform了~");
            }
            var mainMatrix = size.matrix;
            var openMatrix = new Laya.Matrix();
            openMatrix.a = mainMatrix.a;
            openMatrix.b = mainMatrix.b;
            openMatrix.c = mainMatrix.c;
            openMatrix.d = mainMatrix.d;
            openMatrix.tx = mainMatrix.tx;
            openMatrix.ty = mainMatrix.ty;
            //重置矩阵
            Laya.stage._canvasTransform = openMatrix;
            //监听舞台的鼠标移动事件
            Laya.stage.mouseEnabled = true;
        }
    
        /**
         * 用户自己的排名
         */
        var myRanking = -1;
        /**
         * 获取微信排行榜数据
         */
        _proto.getRankingData = function(){
            window['wx'].getUserInfo({
                openIdList: ['selfOpenId'],
                success: (userRes) => {
                    console.log('success', userRes.data);
                    //索引代表各个好友0为自己
                    let userData = userRes.data[0];
                    console.log("取信息索引0" + userData.nickName);
                    //取出所有好友数据
                    window['wx'].getFriendCloudStorage({
                        keyList: [
                            //'击杀排行',
                            '第1关',
                            '第2关',
                            '第3关'
                        ],
                        success: res => {
                            console.log("wx.getFriendCloudStorage success", res);
                            let data = res.data;
                            /*data.sort((a, b) => {
                                if (a.KVDataList.length == 0 && b.KVDataList.length == 0) {
                                    return 0;
                                }
                                if (a.KVDataList.length == 0) {
                                    return 1;
                                }
                                if (b.KVDataList.length == 0) {
                                    return -1;
                                }
                                return b.KVDataList[0].value - a.KVDataList[0].value;
                            });*/
                            for (let i = 0; i < data.length; i++) {
                                var playerInfo = data[i];
                                var currentPlayer = res.data[i].nickname;
                                console.log("当前排行玩家昵称为=>"+res.data[i].nickname);
                                var kvList = playerInfo.KVDataList;
                                var scoreSum = 0;
                                if(kvList.length>0){
                                    for(var j = 0;j<kvList.length;j++){
                                        if(kvList[j].key != null){
                                            //将value转化为int再累加
                                            scoreSum+=Number(kvList[j].value);
                                        }
                                    }
                                }
    
                                if (data[i].avatarUrl == userData.avatarUrl) {
                                    //获取群好友的时候,没有自己的名字??
                                    data[i].nickName = userData.nickName;
                                    myRanking = i+1;
                                    console.log("此ID为自己,当前排名第"+myRanking);
    
                                }
                                //填充总分信息
                                sortData.push({
                                    nickName: currentPlayer, 
                                    avatarUrl: data[i].avatarUrl, 
                                    totalScore: scoreSum 
                                });
                            }
                            sortData.sort((a, b) => {
                                var score1 = Number(a.totalScore);
                                var score2 = Number(b.totalScore);
                                if (score1 > score2) {
                                    return -1;
                                }else if(score1 < score2){
                                    return 1;
                                }else{
                                    return 0;
                                }
                            });
                            showRankingDialog();
    
    
                        },
                        fail: res => {
                            console.log("拉取好友信息失败", res);
                        },
                    });
                },
                fail: (res) => {
                    console.log("拉取个人信息失败")
                }
            });
        }
        /**
         * 加载资源
         */
        _proto.loadResource = function(){
            Laya.loader.load(["comp/bg_line.png","comp/ranking1.png","comp/ranking2.png",
            "comp/ranking3.png","comp/userholder_img.png"], Laya.Handler.create(null,function(){
                console.log("开放域资源加载完毕~");
                sample.rankView = new RankingViewUI();
                Laya.stage.addChild(sample.rankView);
            }));
    
        }
    
        /**
         * 写入排行榜数据
         */
        _proto.writeRankingData = function(rankingData){
            console.log("写入排行榜数据~");
            //KVDataList代表排行数据,可以为多个,多个代表多个排行
            //key-排行类型,value-排行分数
            window['wx'].setUserCloudStorage({
                KVDataList: [
                    //{ key: '击杀排行', value: "" + 1 },
                    { key: '第'+rankingData.fightLevel+'关', value: rankingData.fightScore+"" },//需要改成动态的值
                ],
                success: function (res) {
                    console.log('setUserCloudStorage', 'success', res)
                },
                fail: function (res) {
                    console.log('setUserCloudStorage', 'fail')
                }
            });
        }
        var sortData = [];
        /**
         * 渲染排行榜列表
         */
        function showRankingDialog(){
            console.log("拿到好友排行榜信息", sortData);
            sample.rankView.ranking_list.vScrollBarSkin = "";
            sample.rankView.ranking_list.array = sortData;
            sample.rankView.ranking_list.renderHandler = new Laya.Handler(this, onRender);
            sample.rankView.ranking_list.selectHandler = new Laya.Handler(this, onSelect);
    
        }
    
        var lastRenderIndex = -1;
        function onRender(cell, index){
            if (index == lastRenderIndex) {
                return;
            }
            lastRenderIndex = index;
            //根据子节点的name获取子节点对象
            var name = cell.getChildByName("item_rank_name");
            var ranking = cell.getChildByName("item_rank_text");
            var userlogo = cell.getChildByName("item_rank_logo");
            var score = cell.getChildByName("item_rank_score");
         var rank_icon = cell.getChildByName("item_rank_icon");
    
            name.text = sortData[index].nickName;
            console.log("渲染排行榜当前的用户名为="+sortData[index].nickName+",渲染索引:"+lastRenderIndex);
            ranking.text = (index+1)+"";
            userlogo.skin = sortData[index].avatarUrl;
            score.text = sortData[index].totalScore+"分";
            if(lastRenderIndex === 0 || lastRenderIndex === 1 || lastRenderIndex === 2){
             ranking.visible = false;
             rank_icon.visible = true;
             rank_icon.skin = "comp/ranking"+(lastRenderIndex+1)+".png";
         }else{
             rank_icon.visible = false;
                ranking.visible = true;
            }
    
        }
    
        function onSelect(index){
            console.log("当前选择的索引是:"+index);
    
        }
    
        /**
         * 关闭排行榜
         */
        _proto.closeRankingDialog = function(){
            //dialog.close();
         console.log("关闭排行榜~");
            sortData = [];
            lastRenderIndex = -1;
            sample.rankView.removeChildren();
            sample.rankView = null;
    
        }
    
        _proto.start = function(){
            console.log("开始接收主域的消息~");
            wxOnMessage();
        }
    }
    

    可以看到,我们这里通过 wx.onMessage 方法来获取主域发送的数据,然后借助 dispatchMessage 方法作消息的分发处理。值得注意的是,我们在设置开放域canvas大小的时候,需要重置坐标矩阵,将主域的排行榜显示位置映射到开放域中来,否则会发生滑动无效的问题。我这里设置的排行榜数据有三条,大家可以根据具体需求来传入,获取到排行榜数据后,需要对它进行排序处理并展示,这里直接借助于laya中的 List 控件展示就可以了,对于它用法不熟悉的可以去laya官网了解一下:https://ldc.layabox.com/doc/?nav=zh-js-6-0-0

  3. 开放域图片加载问题:
    用过laya游戏引擎的都知道,我们一般用官方推荐的打包图集的方式来加载游戏中的图片资源,这种方式在主域中是可行的,然而,在开放域中却不能成功加载图片资源。因此,开放域中,我们不需要将图片资源打包成图集,只要像下面这样直接加载图片即可:
 /**
     * 加载资源
     */
    _proto.loadResource = function(){
        Laya.loader.load(["comp/bg_line.png","comp/ranking1.png","comp/ranking2.png",
        "comp/ranking3.png","comp/userholder_img.png"], Laya.Handler.create(null,function(){
            console.log("开放域资源加载完毕~");
            sample.rankView = new RankingViewUI();
            Laya.stage.addChild(sample.rankView);
        }));
    
    }

Then, we also need to correspond to the picture folder are copied to the wx_publish directory, otherwise they will be prompted to find picture resource.

The combined primary domain and the open domain

After the primary domain and the domain functional open source implementation, we need to be packaged into micro-channel game project. First, we need to first publish the primary domain project into micro-channel games, directly to the root directory of the project, as shown above release wx_publishdirectory. Then, create src / myOpenDataContext directory in the directory. Next, we need to be open to the micro-domain project also released a letter games, you can choose the desktop directory, named wx_openafter successfully posted, enter the directory, copy code.js, weapp-adapter.js and index.js files to wx_publish/src/myOpenDataContextthe directory and game.jsonincreasing the open domain mapping directory file:


{
  "deviceOrientation": "portrait",
  "showStatusBar": "false",
  "networkTimeout": {
    "request": 10000,
    "connectSocket": 10000,
    "uploadFile": 10000,
    "downloadFile": 10000
  },
  "openDataContext": "src/myOpenDataContext"
}

Here, micro-channel game leaderboards even if realized, in the end found, in fact, not difficult to implement, the difficulty is the lack of information, this article only be used to initiate any questions welcome.

Guess you like

Origin www.cnblogs.com/moosphon/p/11565820.html