中文网页版瘟疫传播策略游戏。你扮演一种完全虚构的病原,在一张原创的虚构世界地图上选择起点、悄悄扩散、积攒进化点数、购买升级,赶在全球解药问世之前达成你的结局。
本作的世界地图、地区、病原、事件与全部数值均为原创虚构创作,仅服务于游戏平衡,与现实世界的地区、疾病或数据无关。
选择起始地区 → 随人口与交通线扩散 → 感染/死亡里程碑 + 每日被动收入积攒点数
→ 购买升级强化病原 → 全球警戒升级、地区防护、路线关闭、解药研究步步紧逼 → 达成结局
四种结局:
| 结局 | 条件 |
|---|---|
| 胜利·全球肃清 | 30 个地区全部曾感染,且累计死亡 ≥ 初始人口的 85% |
| 失败·解药问世 | 全球研究进度达到 100% |
| 失败·传播断绝 | 全球感染人数归零且无法再燃 |
| 失败·超出时限 | 1000 日内未分胜负 |
核心机制:
- SIRD 四仓室模拟:每个地区按 健康S / 感染I / 康复R / 死亡D 逐日演化,人口全程守恒;「免疫逃逸」升级可让康复者失去免疫再次感染。
- 30 地区 · 6 大陆组:东陆、西洲、北境、南环、岛链、群礁,各有温带/热带/干旱/严寒/湿热/海岛环境、经济与医疗等级、陆/海/空交通条件。
- 26 项升级 · 三系树:扩散(传播效率与路线)、表现(症状/致死/警戒增速)、适应(环境、反医疗、反防护、迟滞研究),带等级、费用与前置条件。
- 全球响应:警戒值驱动地区防护 1–3 级,依次关闭机场、港口、陆路边境;警戒 40 启动联合研究,「抗药屏障」等升级可反制。
- 16 类随机事件:义诊周、抗药菌种、边境走私、疫苗曙光……带权重与触发条件,全部有正向与负向博弈。
- 三档难度 + 种子:相同种子 + 相同操作 = 完全相同的推演,便于分享与复盘。
npm install # 安装依赖
npm run dev # 开发模式(默认 http://localhost:5173)
npm run build # 类型检查 + 生产构建(输出 dist/)
npm run preview # 本地预览生产构建打开浏览器即可游玩,无需后端。
npm test # 单元测试(Vitest):引擎不变量、确定性、存档、平衡性
npm run test:e2e # E2E 测试(Playwright):主流程、键盘、多分辨率(需先 npm run build)
npm run typecheck # TypeScript 类型检查首次运行 E2E 需安装浏览器:npx playwright install chromium。
测试覆盖:
- 引擎单元测试(66 例):PRNG 统计与种子稳定性、地区人口守恒、同种子同操作结果逐位一致、结局判定(四种)、升级/事件/路线数据自洽、存档导出导入往返、多难度平衡推演(简单可胜、困难可败、1000 日内出结果)。
- E2E 测试(26 例):标题→设置→选点完整开局、播放/倍速/空格快捷键、升级购买、地图选区与键盘可达(Tab + Enter)、侧栏标签与方向键导航、模态框焦点陷阱与 Escape 关闭、自动存档刷新恢复、结局重开与损坏存档导入、3D 地球选点与视图偏好、主题切换/持久化/玻璃视觉截图、1920/1366/820/390 四档分辨率布局与横向溢出检查。
src/
├── types/game.ts # 全部核心类型与枚举
├── data/
│ ├── regions.ts # 30 地区定义(共享顶点多边形、属性、邻接)
│ ├── routes.ts # 陆/海/空路线(陆路由邻接推导)
│ ├── upgrades.ts # 26 项升级(效果、费用、前置、等级)
│ ├── events.ts # 16 类随机事件
│ └── balance.ts # 平衡参数与难度表
├── engine/ # 纯函数引擎(无 React 依赖,可独立测试)
│ ├── random.ts # 可复现 PRNG(mulberry32)
│ ├── derived.ts # 升级/难度 → 派生属性
│ ├── step.ts # 单日推演:本地传播、路线输入、响应、研究
│ ├── actions.ts # 玩家动作归约(开始/暂停/变速/购买/跳转)
│ ├── endings.ts # 结局判定与文案
│ └── selectors.ts # 状态查询(全球汇总、路线状态等)
├── storage/
│ ├── save.ts # localStorage 自动存档、JSON 导入导出
│ └── validate.ts # 存档结构与不变量校验(失败拒绝加载)
├── ui/ # React 组件(原生 CSS,无 UI 库)
│ ├── TitleScreen / SetupScreen / GameScreen / EndingScreen
│ ├── WorldMap(SVG 地图)/ Globe3D(Three.js 地球)/ RegionCard / TopBar
│ ├── UpgradePanel / StatsPanel / LogPanel
│ ├── HelpModal / MenuModal / Toast / useModalA11y
│ └── mapColors.ts # 2D/3D 共用着色逻辑
├── App.tsx # 阶段路由、游戏循环、自动存档、全局快捷键
├── index.css # 暗色主题全局样式(响应式 + reduced-motion)
└── main.tsx
tests/
├── engine/ # Vitest 单元测试(9 文件 66 例)
└── e2e/ # Playwright E2E(4 文件 22 例)
地图右上角按钮可在 2D 平面地图 / 3D 地球 间切换,偏好自动记忆。
- 虚构世界地图作为等距圆柱投影贴图渲染到 Three.js 球体,配大气辉光与星空背景
- 拖动旋转、滚轮 / 双指缩放;悬停显示地区状态,点击选择地区(与 2D 完全等效,含开局选点)
- 交通路线以弧线呈现:陆路贴地、海运低弧、航空高弧,路线关闭时变暗
- 着色与 2D 地图共用同一逻辑(感染热度、死亡暗化、选中高亮)
- 3D 组件按需加载(React.lazy):只用 2D 视图时不会下载 Three.js
- 无 WebGL 环境自动降级提示,可切回 2D 继续游玩;键盘操作请使用 2D 视图
标题画面右上角与对局顶栏的主题按钮可在 暗色 / 液态玻璃 间切换,偏好写入 localStorage,刷新后保持。
- 暗色(默认):深蓝夜幕底、金色点缀的疫潮风
- 液态玻璃:白底蓝色科技风 —— 半透明玻璃面板(背景模糊 + 高光描边 + 柔和投影)、浅蓝海洋、淡雅星空与大气辉光
- 2D 地图、3D 地球(海洋 / 大气 / 星空 / 起始标记)与全部 UI 控件同步换装
- 主题切换带 420ms 颜色过渡动画;偏好减少动效的用户自动跳过
| 操作 | 方式 |
|---|---|
| 暂停 / 继续 | 空格,或顶栏播放按钮 |
| 切换倍速 1× / 2× / 5× | 数字键 1 / 2 / 3,或顶栏按钮 |
| 查看地区详情 | 点击地图地区;Tab 聚焦后 Enter |
| 切换侧栏标签 | 点击,或 ← → 方向键 |
| 关闭弹窗 | Esc,或点击遮罩 / 关闭按钮 |
- 对局每 5 日自动存档到浏览器 localStorage;开局与结束时也会存档;关闭/切换页面时兜底存档。
- 菜单中可导出 JSON 存档文件,在任意设备导入继续。
- 导入的存档会经过 schema、版本与不变量校验,失败则拒绝加载,不影响当前对局。
- 确定性引擎:整个推演由
(种子, 玩家操作序列)唯一决定,PRNG 状态序列化进存档,读取存档后继续推演与原路径完全一致。 - 纯函数架构:
engine/不依赖 React 与 DOM,状态为不可变对象,UI 只是状态的映射,便于测试与回放。 - 可访问性:模态框焦点陷阱与焦点恢复、地图地区可 Tab + Enter 操作、tablist 方向键导航、aria 标签、
prefers-reduced-motion适配。 - 响应式:桌面横排布局,≤860px 切换为纵向布局,地图与侧栏均可收起,移动端无横向溢出。
React 18 · TypeScript 5 · Vite 5 · Three.js(3D 地球,按需加载)· 原生 CSS · Vitest · Playwright
本游戏所有名称、地图、病原、症状、数值与机制均为虚构创作,仅用于娱乐,不构成任何现实医学、生物学建议或描述。
MIT — 可自由使用、修改与分发,仅需保留版权声明。