Egret制作打砖块微信小游戏

使用Egret制作微信小游戏打砖块-包括好友排行榜

  • 项目创建与配置
  • 项目逻辑代码
  • 项目发布
  • 微信小游戏的开发
  • 项目所有代码

项目创建与配置

  1. 创建一个Egret EUI项目,默认库即可;
  2. 导入素材,在resource文件夹下创建一个文件夹skins,在skins中创建 游戏场景的EXML文件 和 砖块的EXML文件;创建的皮肤文件
    然后在 resource目录下的default.thm.json中,在exmls和skins节点下添加创建的皮肤文件:
    exmls中添加代码:
	"resource/skins/GameRect.exml",
	"resource/skins/MainScene.exml"

skins中添加代码:

	"MainScene": "resource/skins/MainScene.exml",
	"GameRect": "resource/skins/GameRect.exml"

这样,就可以通过在src代码文件夹中创建与皮肤同名的类来控制皮肤中对应的图片了。
具体方法如下:
    在MainScene.exml中给对应的元件添加id属性,那么在新建的MainScene.ts中,定义与id同名同类型的变量,就能调用到这个元件了。
Egret制作打砖块微信小游戏_第1张图片Egret制作打砖块微信小游戏_第2张图片

项目逻辑代码

1、游戏逻辑
    参考链接: Egret制作打砖块小游戏项目实战.
2、排行榜
        由于排行榜是通过微信的开放域来实现的,所以它的初始化需要手动来处理,这里可以写入游戏的初始化函数里:

        //初始化开放域
        var platform = window.platform;
        platform.openDataContext.postMessage({
            command: "loadRes"
        });

        我是在每次游戏结束后弹出排行榜的,所以写在了游戏结束的函数里:

		//添加排行榜
		var plathform = window.platform;
        //处理遮罩,避免开放域数据影响主域
        this.rankingListMask = new egret.Shape();
        this.rankingListMask.graphics.beginFill(0x000000,1);
        this.rankingListMask.graphics.drawRect(0,0,this.stage.width,this.stage.height);
        this.rankingListMask.graphics.endFill();
        this.rankingListMask.alpha = 0.4;
        //设置为true,以免触摸到下面的按钮
        this.rankingListMask.touchEnabled = true;
        this.addChildAt(this.rankingListMask,999);
        //显示开放域数据
        this.bitmap = plathform.openDataContext.createDisplayObject(null,this.stage.stageWidth, this.stage.stageHeight);
        this.addChild(this.bitmap);
        //主域向子域发送数据
        plathform.openDataContext.postMessage({
            isRanking: this.isRankClick,
            curScore: this.config.score,
            text: "egret",
            year: (new Date()).getFullYear(),
            command: "open"
        });
        //添加关闭排行榜按钮
        var rankBtn = new eui.Button();
        rankBtn.icon = RES.getRes("closeBtn");
        rankBtn.width = rankBtn.height = 50;
        rankBtn.x = this.stage.stageWidth * 9 / 10 - rankBtn.width;
        rankBtn.y = this.stage.stageHeight * 1 / 10;
        this.addChild(rankBtn);
        rankBtn.addEventListener(egret.TouchEvent.TOUCH_TAP, function (e) {
            plathform.openDataContext.postMessage({
                year: (new Date()).getFullYear(),
                command: "close"
            });
            this.removeChild(rankBtn);
            this.removeChild(this.rankingListMask);
            this.removeChild(this.bitmap);
        }, this);

        写完之后会发现,有错误,因为platform中没有openDataContext这个属性,我们可以在 Platform.ts 中添加(以下是部分Platform.ts的代码,仅粘贴了填写openDataContext的部分):

declare interface Platform {
    getUserInfo(): Promise<any>;
    login(): Promise<any>;
    openDataContext: any;
}

class DebugPlatform implements Platform {
    async getUserInfo() {
        return { nickName: "username" }
    }
    async login() {
    }
    openDataContext: any;
}

项目发布

  1. 更改egretProperties.json中的"target",令target的current属性改为"wxgame";
    "target": { "current": "wxgame" },
  2. 打开Egret Laugh,选择当前的项目,点击发布按钮:
    Egret制作打砖块微信小游戏_第3张图片
            点击发布后可以看见,弹出的界面中有可以选择的各种发布类型,勾选微信小游戏,如果未下载相应环境,需要先点击下载,之后再为自己的微信项目命名,然后点确定发布:
    Egret制作打砖块微信小游戏_第4张图片

微信小游戏的开发

发布之后,打开微信开发者工具,开始调试微信小游戏。

  1. 第一步,设置登录信息:
            在 platform.js 中,在login方法处进行登录授权的处理,在Egret的Main.ts中,通过调用Platform的login方法,会在发布微信小游戏后,调用到这里。
            以下代码都可以在微信授权里找到对应得使用方法,此处不再描述。
//授权处理函数
applyJurisdiction() {
   wx.getSetting({	//得到用户的当前设置
        success: (res) => {
            var status = res.authSetting;
            if (!status['scope.userInfo'])//如果用户信息没有被授权获取
            {
                wx.authorize({
                    scope: 'scope.userInfo',
                    success: (res) => {
                        //授权成功后执行的内容
                    }, fail: (res) => {
                        wx.showModal({
                            title: '是否授权用户信息',
                            content: '需要获取您的用户信息,请确认授权,否则排行榜功能将无法使用',
                            success: function (tip) {
                                if (tip.confirm) {
                                    wx.openSetting({
                                    success: (res) => {
                                        if (res.authSetting["scope.userInfo"]) {
                                            wx.showToast({
                                            title: '授权成功!',
                                            icon: 'success',
                                            duration: 1000
                                            });
                                            //授权成功后打开排行榜
                                            console.log("打开排行榜");
                                        }
                                        else {
                                            wx.showToast({
                                                title: '授权失败!',
                                                icon: 'success',
                                                duration: 1000
                                            });
                                        }
                                    },
                                    });
                                }
                            }
                        });
                    }
                });
            }
        }, fail: (res) => {
            wx.showToast({
            title: '调用授权窗口失败!',
            icon: 'success',
            duration: 1000
            });
        }
    })
}

login() {
    this.applyJurisdiction();
    return new Promise((resolve, reject) => {
        wx.login({
            success: (res) => {
                resolve(res)
            }
        })
    })
}
//获得用户的信息
getUserInfo() {
    return new Promise((resolve, reject) => {
        wx.getUserInfo({	//需要注意的是,如果用户未授权,不会弹授权的窗口,需要主动去判断是否需要弹窗
            withCredentials: true,
            success: function (res) {
                var userInfo = res.userInfo	//微信号
                var nickName = userInfo.nickName	//微信用户名
                var avatarUrl = userInfo.avatarUrl	//头像链接
                var gender = userInfo.gender //性别 0:未知、1:男、2:女
                var province = userInfo.province	//省份
                var city = userInfo.city	//城市
                var country = userInfo.country	//国家
                resolve(userInfo);
            }
        })
    })
}
  1. 打开开放域
            在 game.json 中,添加 "openDataContext": "openDataContext", ,之后可以发现项目目录中多了一个名为"openDataContext"的文件夹,如下:
    Egret制作打砖块微信小游戏_第5张图片
            在openDataContext的目录下,有一个index.js的文件,我们可以在其中对开放域的内容进行编辑。
  2. 开放域的处理
            开放域文件夹中有两部分:
            一是名为"assets"文件夹,存放开放域使用的素材,添加的素材,在index.js中的 assetsUrl 里添加与修改,然后通过生成时已存在的函数直接加载进 assets里:
    Egret制作打砖块微信小游戏_第6张图片
            另一部分则是index.js,开放域的所有逻辑代码与变量全部在index.js中处理,所以当开放域监听到主域(小游戏运行的那块内存区域)发送的命令后,对数据处理即可。
    以打开排行榜为例:
    1、 在监听函数中,如果监听到是打开排行榜的命令,则获取好友的数据:
if (data.command == 'open') {
 curScore.score = ~~data.curScore;	//此处使用位取反是为了得到数字类型的值,下同
  wx.getUserCloudStorage({	//得到制定key的所有数据
    keyList: ["score"],
    success: function (callBackData) {
      //获取玩家数据成功
      let kvDataList = callBackData.KVDataList;
      let oldScore = ~~getKVValueByKey(kvDataList, "score");
      if (oldScore < curScore.score) {//破纪录
        curScore.isMax = true;
        wx.setUserCloudStorage({	//如果破纪录,重新在数据库修改分数
          KVDataList: [{
            key: "score",
            value: curScore.score.toString()
          }],
          success: handleFriends()
        })
      } else {
        curScore.isMax = false;
        handleFriends();
      }
    }
  })
}

2、获得好友的数据后,对数据进行处理

function handleFriends() {
  wx.getFriendCloudStorage({
    keyList: ["score"],
    success: function (callBackData) {
      userInfoList = [];
      let data = callBackData.data;
      //获取同玩数据成功
      for (let i = 0; i < data.length; i++) {
        let userData = data[i];
        let avatarUrl = userData.avatarUrl;
        let nickname = userData.nickname;
        let curScore = 0;
        let KVDataList = userData.KVDataList;
        for (let kvData of KVDataList) {
          if (kvData.key == "score") {
            curScore = ~~kvData.value;
          }
        }
        let playerData = {
          key: 0,
          name: "",
          url: assets.icon,
          scroes: 0
        }

        playerData.key = i + 1;
        playerData.name = nickname;
        playerData.url = avatarUrl;
        playerData.scroes = curScore;
        userInfoList.push(playerData);
      }

      let compare = function (a, b) {//比较函数
        if (a.scroes < b.scroes) {
          return 1;
        } else if (a.scroes > b.scroes) {
          return -1;
        } else {
          return 0;
        }
      }
      userInfoList.sort(compare);
      for (let i = 0; i < userInfoList.length; i++) {
        let userInfo = userInfoList[i];
        userInfo.key = i + 1;
      }
      //创建并初始化
      if (!hasCreateScene) {
        hasCreateScene = createScene();
      }
      requestAnimationFrameID = requestAnimationFrame(loop);

      context.clearRect(0, 0, sharedCanvas.width, sharedCanvas.height);
      drawRankPanel();
    }
  });
}

3、绘制每一项数据

/**
 * 根据绘制信息以及当前i绘制元素
 */
function drawByData(data, i) {
  let x = startX;
  let headX = startX + indexWidth + intervalX;
  //绘制序号
  context.fillStyle = "#888489";
  if (i == 0) {
    context.fillStyle = "#FC670A";
  } else if (i == 1) {
    context.fillStyle = "#FF004C";
  } else if (i == 2) {
    context.fillStyle = "#0019FF";
  }

  context.font = Math.floor(stageWidth / 25) + "px Microsoft YaHei";
  context.fillText(data.key + "", x, startY + i * preOffsetY + textOffsetY, 50);
  x += indexWidth + intervalX;
  //绘制头像
  let img = wx.createImage();
  img.src = data.url;
  img.onload = function () {
    context.save();
    context.beginPath(); //开始绘制
    context.arc(headX + (avatarSize / 2), startY + i * preOffsetY + (barHeight - avatarSize) / 2 + (avatarSize / 2), avatarSize / 2, 0, Math.PI * 2, false);
    context.clip();
    context.drawImage(img, headX, startY + i * preOffsetY + (barHeight - avatarSize) / 2, avatarSize, avatarSize);
    context.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
  }
  x += avatarSize + intervalX;
  //绘制名称
  context.fillStyle = "#888489";
  context.font = Math.floor(stageWidth / 28) + "px Arial";
  context.fillText(data.name + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize);
  x += textMaxSize + intervalX;
  //绘制分数
  context.fillStyle = "#09E0EF";
  context.font = Math.floor(stageWidth / 25) + "px Microsoft YaHei";
  context.fillText(data.scroes + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize);
}

项目所有代码

已传至gitbub的项目链接: 打砖块微信小游戏.
BlockCrusher文件夹储存的是Egret Wing编辑的内容
BlockCrusher_wxgame文件夹是发布微信小游戏后编辑的内容

你可能感兴趣的:(Egret)