渲染层笔记
渲染层笔记
核心文件:
include/lab/app/ClientRender.hsrc/app/ClientRender.cppapps/client_main.cpp
渲染层不是项目的同步核心,但它负责把预测世界展示出来,并把回滚、hash mismatch 等调试信息显示给开发者。
1. RenderCtx
RenderCtx 保存 SDL 渲染资源:
| 字段 | 作用 |
|---|---|
SDL_Window* window |
窗口 |
SDL_Renderer* renderer |
渲染器 |
TTF_Font* font |
HUD 字体 |
width、height |
窗口尺寸 |
初始化:
1 | InitRenderer() |
释放:
1 | ShutdownRenderer() |
注意:
SDL 资源要成对创建和释放。后续如果继续完善,可以把 window、renderer、font 封装成 RAII 对象。
2. RenderFrame 输入
渲染函数只接收:
1 | RenderFrame(renderCtx, worldSnapshot, rollbackCount, hashMismatchCount) |
这说明渲染层不直接修改世界。
它只读 WorldSnapshot,然后画:
- 迷宫墙体
- 玩家方块
- 子弹
- HUD 文本
这是一个很好的边界:
1 | 模拟层产出状态; |
3. 世界坐标到屏幕坐标
项目用简单的顶视角坐标转换:
1 | screenX = windowWidth / 2 + worldX * scale |
Y 方向取反,是因为屏幕坐标通常向下为正,而游戏世界里向上为正。
scale 根据迷宫尺寸和窗口大小计算:
1 | scale = min(width / mazeWidth, height / mazeHeight) * 0.8 |
这样不同迷宫尺寸都能大致居中显示。
4. HUD 调试信息
HUD 显示:
- 当前 tick
- rollback 次数
- hash mismatch 次数
- maze seed
- 每个玩家 HP
- 每个玩家 action
- stateTimer
这些信息是联机同步调试里很关键的观察点。
尤其是:
- rollback 次数持续上升,说明预测和权威经常偏离。
- hash mismatch 出现,说明状态还原或确定性有问题。
- tick/HP/action 可以帮助定位是哪一帧开始分叉。
5. 渲染和模拟的关系
客户端每个 tick 会先推进 worldPred,然后 RenderFrame 画当前预测快照。
收到服务端 State 后,客户端会:
1 | Restore(auth) |
所以屏幕上看到的是“经过本地预测和权威校正后的世界”。
注意:
渲染只展示预测结果。真正权威状态仍然在服务端。
6. 渲染层注意事项
- 渲染层不要保存会影响模拟的状态。
- 渲染层不要修改
WorldSnapshot。 - HUD 是调试工具,不应该参与同步逻辑。
- 如果增加插值/平滑,最好只做视觉层修正,不要改权威模拟状态。
- 字体路径当前写死为
/System/Library/Fonts/Menlo.ttc,跨平台需要改成配置项。 - 如果窗口卡顿,不应该让模拟用真实大 dt 推进,固定帧 accumulator 已经负责处理。
- 后续可以补充摄像机、缩放、玩家标识、命中反馈,但仍应保持渲染和模拟解耦。