Skip to content

Repository files navigation

Lockstep Client — Bounce Physics Engine Ecosystem

基于 Bounce 确定性3D物理引擎的多人联机示例项目集合。Bounce 是一个纯 TypeScript(无 WebAssembly)编写的快速确定性物理库,专为多人锁步/回滚游戏设计。

项目布局

lockstop-client/
├── bounce/                              # 引擎源码 (MIT, v1.9.0, ~14K 行 TS)
│   ├── docs/documentation.md            # 完整 API 参考文档
│   ├── src/                             # 引擎源码
│   └── tests/                           # Vitest 测试套件
│
├── bounce-character-controller/         # npm: @perplexdotgg/bounce-character-controller (v0.3.0)
│   └── src/index.ts                     # 角色控制器实现
│
├── bounce-simple-example/               # 简单演示: 球 + 桌面 + Suzanne 模型
├── bounce-character-controller-example/ # 可玩演示: WASD 角色 + 楼梯
├── bounce-lockstep-example/             # 多人锁步演示: 匹配 + 帧同步
└── mecs-tower-defense-example/          # 高级: 使用 MECS ECS 的塔防游戏

快速开始

每个子项目独立运行:

# 安装依赖
npm install

# 启动 Vite 开发服务器
npm run dev

# 生产构建
npm run build

# 运行测试 (仅 bounce 和 bounce-character-controller)
npm run test

运行完整锁步演示

# 终端 1 — 中继服务器(克隆并启动)
git clone https://github.com/beijian128/lockstep-server
cd lockstep-server && go run main.go

# 终端 2 — 客户端开发服务器
cd bounce-lockstep-example && npm run dev

# 打开两个浏览器标签页访问 http://localhost:5173
# 在每个标签页中点击 "Start Matchmaking"

技术栈

  • 语言: TypeScript (strict),ESM 模块
  • 构建: Vite (v7–v8)
  • 物理: @perplexdotgg/bounce (纯 TS, v1.6–1.9)
  • 渲染: Three.js v0.182
  • 测试: Vitest
  • ECS: @perplexdotgg/mecs (仅塔防示例)

Bounce 核心概念

Bounce 是确定性的 — 在任何 IEEE 754 兼容平台上,相同输入产生相同结果。

主要 API 原语

  • World — 物理模拟容器。takeOneStep(dt) 用于确定性步进,advanceTime(dt) 用于可变帧率
  • Shape — 碰撞几何体。工厂方法: createSphere(), createBox(), createCapsule(), createCylinder(), createConvexHull(), createTriangleMesh(), createHeightMap(), createCompoundShape()
  • Body — 物理对象。三种类型: Dynamic(受力+碰撞), Kinematic(用户控制), Static(不可移动)
  • 约束PointConstraint, DistanceConstraint, FixedConstraint, HingeConstraint
  • 场景查询intersectShape(), castRay(), castShape()
  • 序列化world.toArray() / world.fromArray() 用于状态快照/回滚

确定性注意事项

  1. 所有客户端使用相同的 dt 调用 takeOneStep()
  2. 避免在物理相关逻辑中使用 Math.sin/cos/tan
  3. 保持操作顺序一致(浮点加法不可结合)
  4. 使用序列化进行快照/回滚

锁步示例架构

[客户端 A] ──MatchmakingRequest──▶        ┌─────────────────────┐
[客户端 B] ──MatchmakingRequest──▶        │   中继服务器 (Go)     │
                                          │   (:8080)            │
[客户端 A] ◀──MatchmakingStarted──        │   1Hz 匹配循环        │
[客户端 B] ◀──MatchmakingStarted──        │   30Hz tick 循环      │
                                          │   哈希校验            │
[双方]     ◀──JoinResponse───────         └─────────────────────┘
[双方]     ◀──GameStart──────────
[双方]     ◀══FrameInput (30Hz)══
[双方]     ──PlayerInput (按键变更时)──▶
[双方]     ──StateHash (每300 tick)──▶
  • 服务端驱动步进: 客户端仅在收到 FrameInput 时步进
  • 匹配队列: 点击按钮 → MatchmakingRequest → 服务器匹配 ≥2 名玩家 → GameStart
  • 相机相对输入: WASD 按键会按相机角度旋转后发送
  • 状态哈希: 每 300 tick 对所有玩家位置+速度做 FNV-1a 哈希,服务端校验

线协议

[4字节 小端长度][1字节 类型标签][JSON UTF-8]
标签 方向 消息 用途
2 C→S PlayerInput WASD + Jump
3 C→S StateHash 确定性校验
5 C→S MatchmakingRequest 进入匹配队列
1 S→C JoinResponse 分配 playerId
2 S→C GameStart 种子、玩家列表、倒计时
3 S→C FrameInput 30Hz 输入广播
4 S→C GameOver 胜利者信息
5 S→C PlayerEliminated 断线通知
6 S→C MatchmakingStarted 排队确认

相关链接

About

No description or website provided.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages