下面是功能介绍:
小程序·云开发新增实时数据推送能力,可以实时监听数据库中的数据变更。该功能有效地解决了即时通信以及实时更新和推送数据的问题,极大地降低在此类场景下的开发成本。
基于是实时数据推送能力,在给定查询条件的情况下,每当数据库更新而导致查询条件对应的查询结果发生变更时,小程序可收到一个更新事件,其中可获取更新内容和更新后的查询结果快照。
许多对战类型的小游戏需要一个匹配玩家界面,下面就从制作一个匹配玩家界面入手,简单介绍一下云开发实时数据推送功能。
1.首先打开微信开发者工具里云开发,在数据库中新建一个集合,集合名称:rooms,权限设置:所有用户可读,仅创建者可读写。
2.我们用一个两人对战的例子,来介绍如何实现匹配玩家。当玩家进入匹配状态有两个情况,一是当前已经有队列玩家只需进入队列即可,二是当前没有队列玩家要创建队列。这里定义一下创建队列的人叫做newMen,加入队列的人叫做addMen。如何判定当前是否有队列,下面用一段代码说明下:
const db = wx.cloud.database(); const $ = db.command.aggregate; db.collection( 'rooms' ) .aggregate() .match({ people: $.eq(1) }) .sort({ createTimestamp: -1 }) .limit(1) .end().then(res =>{ console.log( '聚合查询结果rooms' ,res.list); this .initRoom(res.list); }) |
这里用的是聚合查询,对集合rooms进行查询,只要当前people字段值为1就说明已经队列,如果查询不到结果就是没有队列需要创建队列,下面就是initRoom()方法进行判断,代码如下:
initRoom(rooms){ if (!rooms.length) { this .createEmptyRoom(); } else { console.log( '进入队列成功' ); this .nowPlayer = 'addMen' ; this .docid = rooms[0]._id;
this.updatePeopleField(); }; } |
从上面代码可以看出,如果查询结果为空就要创建队列。不为空就进入队列,然后执行更新字段操作,后面会详细介绍。下面介绍创建队列createEmptyRoom()方法,代码如下:
createEmptyRoom(){ const db = wx.cloud.database(); const roomid = Date.now().toString();
let room = { roomid, createTimestamp: Date.now().toString(), people: 1, }; db.collection('rooms').add({ data: room }) .then(res =>{ this .nowPlayer = 'newMen' ; this .docid = res._id; this .roomid = roomid; this .waitJionGame(); })
}, |
这里向集合rooms添加一个新记录,即创建队列,当前玩家即nowPlayer为newMen。创建队列完成后,我们要监听是否有玩家进入队列,就是有没有addMen进来。这里就要用到上面说的云开发实时数据推送功能了,相关代码如下:
waitJionGame(){ let docid = this .docid; console.log('正在匹配对手...'); const db = wx.cloud.database(); this .player = db.collection('rooms') .where({ _id: docid }) .watch({ onChange: snapshot => { const docChange = snapshot.docChanges[0]; const doc = snapshot.docs[0]; console.log( '监听玩家进入' , snapshot); if (docChange.dataType === 'update' && doc.people === 2) { console.log('匹配成功'); this .player.close(); } }, onError: error => { console.log(error); } }) }, |
通过对刚才创建的记录进行监听,只要dataType === 'update'即记录有更新操作,并且doc.people === 2,就说明有玩家进入即addMen进入队列,此时就可以关闭监听,执行close()。这时队列创建者即newMen,匹配阶段所有工作都完成了。对于加入队列者即addMen还有一个工作,告诉newMen我已经进入队列了,很简单就是把记录里的people字段更新为2。相关代码如下:
wx.cloud.callFunction({ name: 'updateDoc' , data: { collection: 'rooms', docid: docid, people: 2, } }).then(res => { console.log( '更新人数成功' ,res); }). catch (err => { console.log(err); }) }, |
更新队列创建者newMen创建的记录里的字段是一个越权操作,所以要调用云函数。通过云函数更新完成字段后,addMen所有使命都已经完成了。
这就是整个匹配玩家阶段的流程,相关效果可以参考本人开发的游戏--圣兵棋盘。
圣兵棋盘
你好 我想问一下,这个如何进行调试才能够知道是两个人进入了匹配
假设多个人同时发起匹配请求,这个时候可能会发生匹配到一起的情况,因为数据库还没更新数据。这种情况要怎么处理?
如果上面这个情况听起来很极限的话..那假设两个用户匹配成功了,同时向数据库写入一条记录,这个记录是用户的openid。
逻辑是:openIdArr [ openIdArr.length ] = openid;
这个时候就会出现openIdArr中实际上只有一条数据,因为两个用户读到的数据库记录中openIdArr长度都是0。
这不就是1024吗。我玩了一局,为啥对面分数是undefined