首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >探索使用 Golang 和 Webassembly 构建一个多人游戏服务器

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

作者头像
为少
发布2021-05-27 18:40:40
发布2021-05-27 18:40:40
1.2K00
代码可运行
举报
文章被收录于专栏:黑客下午茶黑客下午茶
运行总次数:0
代码可运行

https://www.youtube.com/watch?v=ZyGw1yLNO9E(原创整理)

什么是 WebAssembly?由 GoogleMicrosoftMozillaApple 等发起的 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
  • 服务器和客户端根据相同的逻辑计算状态
  • 通过二进制类型进行数据传输

编译:

代码语言:javascript
代码运行次数:0
运行
复制
GOOS=js GOARCH=wasm go build -o tanks.wasm cmd/wasm/tanks.go

Client:

代码语言:javascript
代码运行次数:0
运行
复制
<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:

代码语言:javascript
代码运行次数:0
运行
复制
js.Global().Set("updateNetworkPlayer", js.FuncOf(updateNetworkPlayer))

在 Go 中编码 state

代码语言:javascript
代码运行次数:0
运行
复制
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

代码语言:javascript
代码运行次数:0
运行
复制
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
代码语言:javascript
代码运行次数:0
运行
复制
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 黑客下午茶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Panzr.io 简介
  • Panzr.io 架构
  • Panzr.io 部署架构
  • Triebwerk 简介
  • 游戏是如何运行的?
  • 服务器权威架构
  • 客户端预测和服务器协调
  • 客户端插值
  • 定义边界
  • 服务器实现
  • 玩家移动
  • 碰撞检测
  • 二进制数据传输
  • WebAssembly 模块
    • 在 Go 中编码 state
    • 在 Javascript 中解码 state
  • 在线试玩
  • Refs
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档