制作一个Decentraland 的象棋场景 PART 3 多人连线

in #cn4 years ago (edited)


上回说到用 Decentraland SDK 制作一个象棋棋盘的场景

还没看之前的帖子的, 可以回去看 Part 0, Part 1 和 Part2

image.png

Part 0 : 尝试使用 Decentraland SDK 

Part 1:用Decentraland SDK 建模

Part 2:用xiangqi.js 执行象棋逻辑


上回说过 , Decentraland SDK 里, 人物是自动multiplayer 了, 只要两人同时开同一个网页,就可以看到对方,包挂对方所做的各种动作。这是因为 dcl start 里头跑了 websocket server , 打开chrome developer tool 就能看到这个页面是有用 websocket 交流的。

image.png

不过,如果你用 dcl export 场景, 然后把场景upload 在一个static host 时例如github 或 vercel, 就没有跑dcl start 了, 所以就没有 multiplayer 的部分了。 这个叫做preview mode 。 以后我再分享如何让preview mode 也能有websocket 和multiplayer。

上回也说过可以透过 message bus 来传讯息给其它在场的人 , 所以基本上 , 当你下了一步棋子, 就可以把那个move 给emit 出去。 这里有两个选择, 比如说 你的move 是 "a0a1" 把车移上一格, 你可以把"a0a1" 这个讯息 emit 出去 , 或者, emit 一整个 FEN 的字串 ,例如 "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/R8/1NBAKABNR b - - 1 1" , 各有好坏, 所以我选择了两者兼施。

用"a0a1" 的好处是简短,而且对方有move 的history。 这个history 可以用来判断是否有长抓或长将的现象。

image.png

FEN 却有完整性, 比如说可能有旁观者错过了一两个move, 它就可以直接reset 到最current 的棋局。 所以我的 emit 的payload 是包含两者。

这个messagebus , emit 和 receive 代码很容易实现的, 可以自己到我的git repo 去看 .


上回也有说过, 这个message bus 是给在场的所有人即时交流用的 , 如果你emit 了一个讯息, 然后1 秒后 有个新人才刚刚进入这个场景, 那他是不会收到你一秒前emit 的讯息。

也就是说, 这个新人进入场景,看到的棋盘是没动过的状态。

这个时候你就可以用另一个方式, 那就是你可以准备一个memcached server,如果你有自己的伺服 ,可以跑redis 或 memcached类似的东西 ,如果没有,就用免费的吧。

因为懒惰maintenance 又不想花钱, 我也是用了一个免费的叫

https://keyvalue.immanuel.co/ 基本上就是一个网上的 keyvalue 库。

然后用ajax 的方式 存入/读取。 为了以后可以扩展成更多棋盘, 我的 key 有包含 <table id>,fen ,

value 则是棋盘的 FEN string. 参考了document , 只需要用最普通的 ajax fetch / http post 就搞定了。

所以每个到场的人物先来个 ajax http get 去拿table 的 FEN , 然后在把这个字串load 进 xiangqi.ts .然后让棋子根据 xiangqi.ts 的state 呈现就完成了 。 然后玩家每下一步棋就把该state 的FEN post 去那个 keyvalue store 就完成了 。

这个连preview mode 也可以用哦, 因为跟websocket 没有任何关系。

把这个实现后, 你的multiplayer 的部分基本上就完成了。


好的,那今天就分享到此。

下次有空我会再分享如何实现让那些物件变成可以 clickable 然后会有 interact 的显示 , 以及如何让棋子的位置反映出xiangqi.ts 里的state

image.png

谢谢阅读。