整理中文文档结构与索引
This commit is contained in:
588
doc/archive/config/配置设计方案.md
Normal file
588
doc/archive/config/配置设计方案.md
Normal file
@@ -0,0 +1,588 @@
|
||||
# 游戏配置文件设计方案(阶段讨论稿)
|
||||
|
||||
本文档用于整理当前阶段推荐的配置文件设计方案,供后端、客户端和后台管理设计参考。
|
||||
目标是让配置真正成为游戏的驱动入口,同时兼顾后续多玩法、多资源、多活动复用。
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
配置文件系统需要解决以下问题:
|
||||
|
||||
- 驱动地图、玩法、资源、调试开关
|
||||
- 支持顺序赛、积分赛以及后续更多玩法
|
||||
- 支持将来后台管理系统的内容编排
|
||||
- 保证地图空间信息与玩法语义分层
|
||||
- 保证当前阶段可平滑迁移,不推翻已有实现
|
||||
|
||||
当前推荐原则:
|
||||
|
||||
- 配置只描述,不执行逻辑
|
||||
- 地图、空间对象、玩法规则、资源包分层
|
||||
- KML 负责空间底稿,不负责复杂玩法语义
|
||||
- 主配置先保持单文件,后续再升级为 manifest 组合
|
||||
|
||||
---
|
||||
|
||||
## 2. 顶层配置结构
|
||||
|
||||
当前推荐主入口配置结构如下:
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1",
|
||||
"version": "2026.03.25",
|
||||
"app": {},
|
||||
"map": {},
|
||||
"playfield": {},
|
||||
"game": {},
|
||||
"resources": {},
|
||||
"debug": {}
|
||||
}
|
||||
```
|
||||
|
||||
各层职责如下:
|
||||
|
||||
- `app`
|
||||
活动级或应用级基础信息
|
||||
- `map`
|
||||
地图底图和空间底座
|
||||
- `playfield`
|
||||
当前玩法使用的空间对象定义
|
||||
- `game`
|
||||
当前玩法规则配置
|
||||
- `resources`
|
||||
资源包与 profile
|
||||
- `debug`
|
||||
调试与开发开关
|
||||
|
||||
---
|
||||
|
||||
## 3. 为什么不再以 course 作为总抽象
|
||||
|
||||
在定向语义里,`course` 是准确术语,表示路线。
|
||||
但从系统长期扩展看,`course` 并不是所有玩法的上位概念。
|
||||
|
||||
例如:
|
||||
|
||||
- 顺序赛有明显的 `course`
|
||||
- 积分赛更像一组控制点与分数
|
||||
- 金币赛更像可收集点集合
|
||||
- 幽灵赛可能包含危险区、隐身点、追逐者
|
||||
- 迷雾赛可能包含 reveal 点、扫描点、区域
|
||||
|
||||
因此推荐:
|
||||
|
||||
- 将上位内容模型提升为 `playfield`
|
||||
- `course` 只作为 `playfield.kind` 的一种
|
||||
|
||||
例如:
|
||||
|
||||
```json
|
||||
{
|
||||
"playfield": {
|
||||
"kind": "course"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
或:
|
||||
|
||||
```json
|
||||
{
|
||||
"playfield": {
|
||||
"kind": "control-set"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. KML 与配置的边界
|
||||
|
||||
当前推荐边界非常明确:
|
||||
|
||||
### 4.1 KML 负责空间底稿
|
||||
|
||||
KML 适合描述:
|
||||
|
||||
- 点坐标
|
||||
- 起点 / 检查点 / 终点
|
||||
- 顺序号
|
||||
- 点位名称
|
||||
- 腿线几何
|
||||
|
||||
### 4.2 配置负责玩法解释
|
||||
|
||||
配置负责描述:
|
||||
|
||||
- 点位分值
|
||||
- 打点规则
|
||||
- 显隐规则
|
||||
- 动态积分
|
||||
- 道具能力
|
||||
- 迷雾规则
|
||||
- 占领规则
|
||||
- 特殊玩法语义
|
||||
|
||||
一句话总结:
|
||||
|
||||
**KML 描述空间事实,配置描述玩法解释。**
|
||||
|
||||
---
|
||||
|
||||
## 5. 推荐的字段结构
|
||||
|
||||
### 5.1 `app`
|
||||
|
||||
用于活动级基础信息。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"id": "lxcb-001",
|
||||
"title": "雪熊领秀城区定向赛",
|
||||
"locale": "zh-CN"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 `map`
|
||||
|
||||
用于地图底图与空间底座。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"map": {
|
||||
"tiles": "lxcb-001/tiles/",
|
||||
"mapmeta": "lxcb-001/tiles/meta.json",
|
||||
"declination": 6.91,
|
||||
"initialView": {
|
||||
"zoom": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 `playfield`
|
||||
|
||||
用于描述当前玩法使用的空间对象及其来源。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"playfield": {
|
||||
"kind": "course",
|
||||
"source": {
|
||||
"type": "kml",
|
||||
"url": "lxcb-001/course/c01.kml"
|
||||
},
|
||||
"CPRadius": 6,
|
||||
"controlOverrides": {},
|
||||
"metadata": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
建议后续逐步支持的对象包括:
|
||||
|
||||
- `controls`
|
||||
- `collectibles`
|
||||
- `zones`
|
||||
- `hazards`
|
||||
- `links`
|
||||
- `spawnPoints`
|
||||
|
||||
### 5.4 `game`
|
||||
|
||||
用于描述玩法规则。
|
||||
|
||||
推荐统一结构如下:
|
||||
|
||||
```json
|
||||
{
|
||||
"game": {
|
||||
"mode": "",
|
||||
"rulesVersion": "1",
|
||||
"session": {},
|
||||
"punch": {},
|
||||
"scoring": {},
|
||||
"guidance": {},
|
||||
"visibility": {},
|
||||
"finish": {},
|
||||
"telemetry": {},
|
||||
"feedback": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `session`
|
||||
|
||||
控制一局游戏的流程参数:
|
||||
|
||||
- 是否手动开始
|
||||
- 是否必须打开始点
|
||||
- 是否必须打结束点
|
||||
- 是否允许自动结束
|
||||
- 最大时长
|
||||
|
||||
#### `punch`
|
||||
|
||||
控制打点规则:
|
||||
|
||||
- 打点策略
|
||||
- 打点半径
|
||||
- 是否必须选中后打卡
|
||||
|
||||
#### `scoring`
|
||||
|
||||
控制积分与结算:
|
||||
|
||||
- 完成型
|
||||
- 固定分
|
||||
- 动态分
|
||||
|
||||
#### `guidance`
|
||||
|
||||
控制引导方式:
|
||||
|
||||
- 是否显示腿线
|
||||
- 是否显示腿线动画
|
||||
- 是否允许 focus 选择
|
||||
|
||||
#### `visibility`
|
||||
|
||||
控制显隐逻辑:
|
||||
|
||||
- 是否开始后显示全图
|
||||
- 是否采用迷雾
|
||||
|
||||
#### `finish`
|
||||
|
||||
控制结束规则:
|
||||
|
||||
- 是否必须打终点
|
||||
- 是否允许随时结束
|
||||
|
||||
#### `telemetry`
|
||||
|
||||
控制通用运动信息参数:
|
||||
|
||||
- 年龄
|
||||
- 静息心率
|
||||
- 体重
|
||||
|
||||
#### `feedback`
|
||||
|
||||
控制反馈 profile:
|
||||
|
||||
- 音频
|
||||
- 震动
|
||||
- UI 动效
|
||||
|
||||
### 5.5 `resources`
|
||||
|
||||
用于描述资源 profile。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"resources": {
|
||||
"audioProfile": "default",
|
||||
"contentProfile": "default",
|
||||
"themeProfile": "default-race"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当前阶段建议先保持轻量,后续再逐步拆成资源包 manifest。
|
||||
|
||||
### 5.6 `debug`
|
||||
|
||||
用于开发和调试相关开关。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"debug": {
|
||||
"allowModeSwitch": false,
|
||||
"allowMockInput": false,
|
||||
"allowSimulator": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 顺序赛示例配置
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1",
|
||||
"version": "2026.03.25",
|
||||
"app": {
|
||||
"id": "lxcb-001",
|
||||
"title": "雪熊领秀城区顺序赛"
|
||||
},
|
||||
"map": {
|
||||
"tiles": "lxcb-001/tiles/",
|
||||
"mapmeta": "lxcb-001/tiles/meta.json",
|
||||
"declination": 6.91
|
||||
},
|
||||
"playfield": {
|
||||
"kind": "course",
|
||||
"source": {
|
||||
"type": "kml",
|
||||
"url": "lxcb-001/course/c01.kml"
|
||||
},
|
||||
"CPRadius": 6
|
||||
},
|
||||
"game": {
|
||||
"mode": "classic-sequential",
|
||||
"rulesVersion": "1",
|
||||
"session": {
|
||||
"requiresStartPunch": true,
|
||||
"requiresFinishPunch": true,
|
||||
"autoFinishOnLastControl": false,
|
||||
"startManually": true
|
||||
},
|
||||
"punch": {
|
||||
"policy": "enter-confirm",
|
||||
"radiusMeters": 10
|
||||
},
|
||||
"guidance": {
|
||||
"showLegs": true,
|
||||
"legAnimation": true,
|
||||
"allowFocusSelection": false
|
||||
},
|
||||
"visibility": {
|
||||
"revealFullPlayfieldAfterStartPunch": true
|
||||
},
|
||||
"telemetry": {
|
||||
"heartRate": {
|
||||
"age": 30,
|
||||
"restingHeartRateBpm": 62,
|
||||
"userWeightKg": 65
|
||||
}
|
||||
},
|
||||
"feedback": {
|
||||
"audioProfile": "default",
|
||||
"hapticsProfile": "default",
|
||||
"uiEffectsProfile": "default"
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"audioProfile": "default",
|
||||
"contentProfile": "default"
|
||||
},
|
||||
"debug": {
|
||||
"allowModeSwitch": false,
|
||||
"allowMockInput": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 积分赛示例配置
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1",
|
||||
"version": "2026.03.25",
|
||||
"app": {
|
||||
"id": "lxcb-001",
|
||||
"title": "雪熊领秀城区积分赛"
|
||||
},
|
||||
"map": {
|
||||
"tiles": "lxcb-001/tiles/",
|
||||
"mapmeta": "lxcb-001/tiles/meta.json",
|
||||
"declination": 6.91
|
||||
},
|
||||
"playfield": {
|
||||
"kind": "control-set",
|
||||
"source": {
|
||||
"type": "kml",
|
||||
"url": "lxcb-001/course/c01.kml"
|
||||
},
|
||||
"CPRadius": 6,
|
||||
"controlOverrides": {
|
||||
"control-1": { "score": 10 },
|
||||
"control-2": { "score": 20 },
|
||||
"control-3": { "score": 30 }
|
||||
}
|
||||
},
|
||||
"game": {
|
||||
"mode": "score-o",
|
||||
"rulesVersion": "1",
|
||||
"session": {
|
||||
"requiresStartPunch": true,
|
||||
"requiresFinishPunch": false,
|
||||
"startManually": true
|
||||
},
|
||||
"punch": {
|
||||
"policy": "enter-confirm",
|
||||
"radiusMeters": 10,
|
||||
"requiresFocusSelection": true
|
||||
},
|
||||
"guidance": {
|
||||
"showLegs": false,
|
||||
"legAnimation": false,
|
||||
"allowFocusSelection": true
|
||||
},
|
||||
"scoring": {
|
||||
"type": "score"
|
||||
},
|
||||
"finish": {
|
||||
"finishControlAlwaysSelectable": true
|
||||
},
|
||||
"telemetry": {
|
||||
"heartRate": {
|
||||
"age": 30,
|
||||
"restingHeartRateBpm": 62,
|
||||
"userWeightKg": 65
|
||||
}
|
||||
},
|
||||
"feedback": {
|
||||
"audioProfile": "default",
|
||||
"hapticsProfile": "default",
|
||||
"uiEffectsProfile": "default"
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"audioProfile": "default",
|
||||
"contentProfile": "default"
|
||||
},
|
||||
"debug": {
|
||||
"allowModeSwitch": false,
|
||||
"allowMockInput": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 当前老字段到新结构的迁移建议
|
||||
|
||||
### 地图层
|
||||
|
||||
- `map` -> `map.tiles`
|
||||
- `mapmeta` -> `map.mapmeta`
|
||||
- `declination` -> `map.declination`
|
||||
|
||||
### 路线层
|
||||
|
||||
- `course` -> `playfield.source.url`
|
||||
- `CPRadius` -> `playfield.CPRadius`
|
||||
|
||||
### 玩法层
|
||||
|
||||
- `game.mode` -> `game.mode`
|
||||
- `game.punchPolicy` -> `game.punch.policy`
|
||||
- `PunchRadius` -> `game.punch.radiusMeters`
|
||||
- `game.autoFinishOnLastControl` -> `game.session.autoFinishOnLastControl`
|
||||
|
||||
### telemetry 层
|
||||
|
||||
- `game.telemetry.age` -> `game.telemetry.heartRate.age`
|
||||
- `game.telemetry.restingHeartRateBpm` -> `game.telemetry.heartRate.restingHeartRateBpm`
|
||||
- `game.telemetry.userWeightKg` -> `game.telemetry.heartRate.userWeightKg`
|
||||
|
||||
### feedback 层
|
||||
|
||||
- `game.audio` -> `game.feedback.audio` 或 `resources.audioProfiles`
|
||||
- `game.haptics` -> `game.feedback.haptics` 或 `resources.hapticsProfiles`
|
||||
- `game.uiEffects` -> `game.feedback.uiEffects` 或 `resources.uiEffectsProfiles`
|
||||
|
||||
当前建议迁移策略:
|
||||
|
||||
- 第一阶段:代码同时兼容老字段和新结构
|
||||
- 第二阶段:线上配置逐步切换
|
||||
- 第三阶段:再清理旧字段兼容逻辑
|
||||
|
||||
---
|
||||
|
||||
## 9. 未来推荐的 manifest 方向
|
||||
|
||||
当前阶段主配置建议先保持单文件。
|
||||
但未来配置规模变大时,推荐升级成多 manifest 组合:
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "1",
|
||||
"version": "2026.03.25",
|
||||
"map": {
|
||||
"manifest": "maps/lxcb-001/map.json"
|
||||
},
|
||||
"playfield": {
|
||||
"manifest": "playfields/lxcb-001/c01.json"
|
||||
},
|
||||
"game": {
|
||||
"manifest": "modes/score-o/default.json"
|
||||
},
|
||||
"resources": {
|
||||
"manifest": "packs/spring-2026/resources.json"
|
||||
},
|
||||
"debug": {}
|
||||
}
|
||||
```
|
||||
|
||||
这样可以支持:
|
||||
|
||||
- 一张地图挂多种玩法
|
||||
- 一条 playfield 挂多种规则
|
||||
- 一种玩法切换不同资源包
|
||||
- 后台管理做拼装式发布
|
||||
|
||||
---
|
||||
|
||||
## 10. 服务端和后台管理的推荐核心对象
|
||||
|
||||
后续从服务端和后台管理的复用角度,建议围绕以下核心对象建模:
|
||||
|
||||
- `Map`
|
||||
- `Playfield`
|
||||
- `GameMode`
|
||||
- `ResourcePack`
|
||||
- `Event`
|
||||
|
||||
其中:
|
||||
|
||||
- `Map`
|
||||
地图底图与空间底座
|
||||
- `Playfield`
|
||||
当前玩法场景中的空间对象定义
|
||||
- `GameMode`
|
||||
玩法规则模板
|
||||
- `ResourcePack`
|
||||
资源包与 profile
|
||||
- `Event`
|
||||
一次实际发布的活动实例
|
||||
|
||||
推荐关系可以理解为:
|
||||
|
||||
`Event = Map + Playfield + GameMode + ResourcePack + 发布参数`
|
||||
|
||||
---
|
||||
|
||||
## 11. 当前阶段推荐结论
|
||||
|
||||
当前阶段最推荐的方案是:
|
||||
|
||||
- 先保留单个 `game.json`
|
||||
- 结构升级为 `app / map / playfield / game / resources / debug`
|
||||
- 保留 KML 作为空间底稿来源
|
||||
- 不再让 `course` 成为总抽象,而是提升为更通用的 `playfield`
|
||||
- 让代码先双兼容,再逐步迁移线上配置
|
||||
|
||||
一句话总结:
|
||||
|
||||
**KML 描述空间事实,配置描述玩法解释;主配置按 `map / playfield / game / resources / debug` 分层,后续再升级成 manifest 组合。**
|
||||
|
||||
Reference in New Issue
Block a user