探索使用 Golang 和 Webassembly 构建一个多人游戏服务器

https://www.youtube.com/watch?v=ZyGw1yLNO9E(原创整理)
什么是 WebAssembly?由 Google、Microsoft、Mozilla、Apple 等发起的 WebAssembly 是一种新的字节码格式,主流浏览器都已经支持 WebAssembly。和 JS 需要解释执行不同,WebAssembly 字节码和底层机器码很相似可快速装载运行,因此性能相对于 JS 解释执行大大提升。WebAssembly 并不是一门编程语言,而是一份字节码标准,需要用高级编程语言编译出字节码放到 WebAssembly 虚拟机中才能运行。
Panzr.io 简介
基于开源技术的游戏
使用
Web作为发行平台轻巧快速
探索基本的多人游戏技术
扩展
Go技术知识
Panzr.io 架构

Panzr.io 部署架构

Triebwerk 简介
项目源码:
https://github.com/awdng/triebwerk
项目 Status:
Triebwerk是一个开源的多人游戏服务器使用
Go语言编写目前仅是基础原型
游戏是如何运行的?

服务器权威架构
仅通过服务器进行通讯
客户端将所有输入发送到服务器
服务器有权进行模拟
防止作弊并引入延迟

客户端预测和服务器协调
最早由
QuakeWorld推广本地模拟运动
不断与服务器状态同步
根据服务器状态更正本地状态

客户端插值
网络更新(
Updates) < 每秒帧数(Frames)过去状态之间的插值
保守算法
没有推断

定义边界
限制:
所有游戏逻辑仅在
2D空间中均匀表面
仅通过键盘进行输入控制
限制地图尺寸
缓慢移动的车辆
没有物理引擎

服务器实现

玩家移动

碰撞检测

二进制数据传输
最小化资源使用
防止数据包分段
最小化丢包的影响

WebAssembly 模块
游戏逻辑(Game logic):Server -> Client
文件大小 > 2MB
服务器和客户端根据相同的逻辑计算状态
通过二进制类型进行数据传输
编译:
GOOS=js GOARCH=wasm go build -o tanks.wasm cmd/wasm/tanks.go
Client:
<script src="/game/wass_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(featch("/game/tanks.wass"), go.importObject).then(result => {
    go.run(result.instance);
});
</script>
Server:
js.Global().Set("updateNetworkPlayer", js.FuncOf(updateNetworkPlayer))
在 Go 中编码 state
posX := float32(30.457777)
posY := float32(10.336666)
buf := make([]byte, 8)
binary.LittleEndian.PutUint32(buf[0:], math.Float32bits(posX))
binary.LittleEndian.PutUint32(buf[4:], math.Float32bits(posY))
var uint8Array = js.Global().Get("Uint8Array")
dst := uint8Array.New(len(buf))
js.CopyBytesToJS(dst, buf)
在 Javascript 中解码 state
let dv = new DataView(state.buffer)
let posX = dv.getFloat32(0, true)
let posY = dv.getFloat32(4, true)
在线试玩
http://panzr.io
Refs
https://www.youtube.com/watch?v=ZyGw1yLNO9E
https://github.com/awdng/triebwerk
http://panzr.io
