之前很火的修勾蹦迪感觉很有意思,所以也想在Godot上也实现一下,Github上有很多开源的弹幕获取库,大多都是nodejs和python版本的,想要和Godot直接交互必须得做桥接,nodejs收发弹幕在发送给Godot再做逻辑处理,所以这里参考了NodeJs版本的弹幕获取方式实现了一份GDScript版本的弹幕姬!
本教程是基于WebSocket实现
插件地址:SakuyaCN/Godot-Danmuku: Godot 弹幕库插件 (github.com)
前提概要
Bilibili 直播弹幕 WebSocket 协议:
lovelyyoshino/Bilibili-Live-API: BILIBILI 直播/番剧 API (github.com)
bilibili大部分的API都在这里,不过版本是2年前的所以不保证全部能用,但是直播部分还是没啥大问题的。
调用地址
本教程使用SSL加密地址
数据包格式
发送和接收的包都是这种格式。
偏移 | 长度 | 类型 | 字节序 | 名称 | 说明 |
0 | 4 | int | Big Endian | Packet Length | 数据包长度 |
4 | 2 | int | Big Endian | Header Length | 数据包头部长度(固定为 16 ) |
6 | 2 | int | Big Endian | Protocol Version | 协议版本(见下文) |
8 | 4 | int | Big Endian | Operation | 操作类型(见下文) |
12 | 4 | int | Big Endian | Sequence Id | 数据包头部长度(固定为 1 ) |
16 | - | byte[] | - | Body | 数据内容 |
2020.6.4 现版本弹幕协议中数据包长度就是整个WebSocket Frame
的长度,而并非直播数据包
长度,因此已无法通过offset来切割相邻的直播数据包
。获得数据后也不能直接使用JSON.parse进行解析,需要将多条json数据切割。
2021.7.12 现版本协议增加brotli压缩信息
Godot在自带字节数字压缩解压操作所以在新版本的协议中不需要自己去编译native库实现解压缩操作
协议版本
值 | Body 格式 | 说明 |
0 | JSON | JSON纯文本,可以直接通过 JSON.stringify 解析 |
1 | Int 32 Big Endian | Body 内容为房间人气值 |
2 | Buffer | 压缩过的 Buffer,Body 内容需要用zlib.inflate解压出一个新的数据包,然后从数据包格式那一步重新操作一遍 |
3 | Buffer | 压缩信息,需要brotli解压,然后从数据包格式 那一步重新操作一遍 |
操作类型
值 | 发送者 | Body 格式 | 名称 | 说明 |
2 | 客户端 | (空) | 心跳 | 不发送心跳包,70 秒之后会断开连接,通常每 30 秒发送 1 次 |
3 | 服务器 | Int 32 Big Endian | 心跳回应 | Body 内容为房间人气值 |
5 | 服务器 | JSON | 通知 | 弹幕、广播等全部信息 |
7 | 客户端 | JSON | 进房 | WebSocket 连接成功后的发送的第一个数据包,发送要进入房间 ID |
8 | 服务器 | (空) | 进房回应 | |
关键地方实现过程
连接房间
websocket连接成功后发送数据包进行房间连接
func _connected(proto = ""):
var body = Constvalue.encode(to_json({"roomid": roomid }), 7)
_client.get_peer(1).put_packet(body)
encode函数实现:

websocket接受数据

decode函数实现

最后效果如下


剩下的就是根据弹幕或者接受到的礼物去实现一些游戏逻辑,例如修勾蹦迪那些!