当前位置: 首页 > 后端技术 > Node.js

如何使用哔哩哔哩弹幕控制游戏

时间:2023-04-03 20:13:26 Node.js

大家好,我是卡松。中秋节在家无聊,想找点乐子。想了想,还是决定做一个弹幕控制的坦克战。具体逻辑是:监听直播间水友的弹幕,提取弹幕中的有效指令,将指令转化为键盘按键,在坦克大战中输入直播坦克大战游戏画面,从而实现从操作到展示的完整逻辑,所有直播间的水友都可以参与游戏。下面是实际效果:让我们来看看技术细节。在监控水友弹幕这一步中,我使用puppeteer监控我直播间的DOMNodeInserted事件。当一个节点作为子节点插入另一个节点时,会触发DOMNodeInserted事件。触发时,根据类名过滤掉属于弹幕的节点。不得不说,B站的弹幕数据真的很容易抓取,全部存储在$('.chat-item.danmaku-item').dataset()中。命令识别抓取到弹幕内容后,还需要做一些额外的处理,例如:12345表示上下左右发射,需要识别这些数字的弹幕和奇数昵称的弹幕控制玩家1的坦克,连号控制玩家2的坦克应对多人同时发弹幕的情况。我的处理方式是:设置一个时间间隔(200ms),统计这段时间内收到的各种命令的数量。200毫秒后出现次数最多的命令是最终命令。接下来,我开始寻找开源坦克大战。这个存储库拥有最多的星星:battle-city。一开始我以为作者是用canvas来实现游戏的,但是当我看到这些文件名的时候,我就知道事情并没有那么简单。:整个游戏其实都是用React做的!子弹是React组件,场景切换是路由切换,状态管理是Redux-Saga。不得不说,Redux-Saga状态管理方案的作者写完这个项目想必都明白了。项目间通信为了将B站弹幕截图项目中识别出的指令实时传输到坦克大战中,需要用到websocket协议。这里我选择socket.io库。值得一提的是,需要在服务端(即弹幕抓取项目)的socket.io配置中设置cors:true,解决跨域问题。在坦克大战中,接收到的命令构造为键盘事件并发送:constfireKeyEvent=(evtType:string,keyChar:string)=>{varKeyboardEventInit={key:keyChar,code:keyChar,location:0,repeat:false,isComposing:false};varevtObj=newKeyboardEvent(evtType,KeyboardEventInit);document.dispatchEvent(evtObj);}整个过程总结起来没有技术难度。唯一坑的是:直播中有5秒左右的延迟,所以从弹幕到坦克操作有延迟。在延迟5秒的情况下,原本弱智的电脑简直就是神。为了减少玩家的挫败感,我决定让玩家互相对抗。这样大家就站在了同一起跑线上。终于,在一波接一波的弹幕中,度过了一个祥和的中秋之夜。直播间里不是在说水友,是在说我自己,真的很无聊……欢迎加入人类优质前端框架研究组,带头