探索使用 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