https://metazero-terminal.pages.dev/travel-2d/rpg(线上实测 2026-07-27 HTTP 200,标题 🧭 环球旅行 · 探索发现)web/terminal/travel-2d/(rpg.html 799 行 + rpg.js 3056 行 + 5 个玩法模块 + 6 个数据文件,合计约 56 万字符代码 + 2.37 MB JSON)modules.json这不是一个"游戏",而是一套【真实世界数据 → 可玩体验】的转换管线,已经攒下 8 个大类 71 个零件。
最值钱的不是任何一条玩法,而是那 12 个免 key 的公开接口 + 2.37 MB 本地素材 —— 换一套组合就是一个新游戏,而不用重新采一次数据。
但代码里现在没有任何一处"开关总闸",做组合只能手工注释,所以第一件该补的事是抽一个 world.config.js(见第五章 GAP4)。
| 素材 | 规模 / 内容 | 来源 | 位置 |
|---|---|---|---|
| 卫星底图 | 全球,最高 18 级 | Esri World Imagery | rpg.js TILES.sat |
| 手绘底图 | 全球,最高 18 级 | CARTO Voyager | rpg.js TILES.street |
| 缩放阶梯 | 10 级(2/4/6/8/10/12/14/15/16/18) | 本地 | ZLV |
| 城市库 | 3689 座去重城市 = 深度 103 + 维基 1155 + 小城 2585 | 本地 JSON | data/cities_*.json |
| 城市真实摘要 | 1155 条(维基百科正文摘要,中文) | 维基 | cities_wiki.json.s |
| 三语城市名 | 中 / 英 / 日 | 本地 | 三库共有 |
| 世界遗产地 | 1864 处,覆盖 223 个国家地区,带 UNESCO 官网链接 | 本地 JSON | data/heritage.json 🔴 RPG 未加载 |
| 3D 地球贴图 | 昼夜图 / 云层 / 星空 / 法线 / 高光,含 8K | 本地 | travel-globe/assets/ 🟢 现成但停用 |
> 卫星图有一个已修的坑值得记:Esri 在偏远地区的超高倍瓦片不是 404,而是返回 200 + 恒定 2521 字节的"暂无数据"占位图(实测乍得/中非/刚果 z18),代码里已做体积探针自动降级。
| 素材 | 接口 | 规模 | 备注 |
|---|---|---|---|
| 玩家周边地标 | 维基 list=geosearch | 半径 8 km / 最多 25 个 | 15 级以上才在地图上列 |
| 城市地标库 | 维基 list=geosearch | 半径 10 km / 最多 50 个 | gsradius 硬上限就是 10000 米(实测填 20000 直接返回 0 条),要更大范围只能多点采样 |
| 地标简介 | 维基 rest_v1/page/summary | 三语 | 已做缓存 |
| 地标代表图 | 维基 prop=pageimages(900px) | 批量 50 | 人工挑选过,最准 |
| 实景照片 | Commons generator=geosearch | 半径 3 km / 每次 10 张 | 按坐标找,数量多但质量参差 |
这一层是整个项目的地基:演唱会场地、跑腿目的地、人生清单的"那个地标",全部从它长出来。
| 素材 | 来源 | 规模 | 逻辑 |
|---|---|---|---|
| 历史名人 | Wikidata SPARQL | 每城最多 4 位 | P19(出生地)=这座城 + 是人 + 维基站点链接数 > 12,按知名度降序 |
| 名人备胎 | 维基分类搜索 | 每城最多 4 位 | incategory:"People from X",专治 SPARQL 429 限流 |
| 名人照片 | 维基 pageimages / Commons | 若干 | 点开名人卡时拉 |
| 职业 NPC | 本地 8 种 | 美食家/背包客/商人/建筑师/历史学家/音乐人/艺术家/摄影师 | 每种绑一个内容维度 |
| 导游 | 本地生成 | 每城常驻 1 位 | 15 张面孔按城名稳定选,降落即主动搭话 |
| 音乐家 | Apple 榜单 | 每城池子 14 位,同时最多 5 场演出 | 上台门槛:≥10 首带试听源的歌 且 综合榜靠前 |
> 可玩性最高的一个旋钮:把 Wikidata 那句 P19 换成 P937(工作地)或 P20(逝世地),整座城的人就换了一批 —— 一行改动,完全不同的世界。
| 素材 | 接口 | 说明 |
|---|---|---|
| 各国每日热榜 | itunes.apple.com/{cc}/rss/topsongs | 官方榜,CORS 全开,每首带 30 秒试听源 |
| 曲库搜索 | itunes.apple.com/search | 配本土曲风关键词(fado / mbalax / 演歌 / klapa …) |
| 国家→曲风映射表 | 本地 LOC 表 | 覆盖上百国,每国配 2-4 个真实本土曲风词 |
| 5 种演出类型 | 本地 SHOW_KINDS | 大型演唱会 / 地下乐队 / Live House / 街头表演 / 音乐节,各带灯光配色 + 票价系数(0.35–1.9 倍) + 星星数 + 节拍速度 |
| 全曲外链 | Spotify / Apple Music / YouTube / B站 | 试听是 30 秒,想听全曲跳外站 |
诚实边界(代码里已明写):部分国家 Apple 无商店或榜单为空(中国大陆榜仅 1 条、伊朗古巴返回 400),此时自动降级到曲库搜索并在面板上明写来源,不假装是当地榜单。
| 素材 | 接口 | 说明 |
|---|---|---|
| 视频搜索 | YouTube Data API v3(内置公用 key) | 每次取 10 条,游戏内直接列表 |
| 内嵌播放 | youtube-nocookie embed | 装在"舞台"里,不打断游戏 |
| 搜索词库 | 本地 265 个话题词(7 维 × 37-38 条,中英对照) | 让每次聊天生成的搜索词都不一样 |
| 外链矩阵 | YouTube / Google / B站 / Wiki | 零配额兜底通道 |
| 城市图片集 | Commons + pageimages | 幻灯片播放,可收藏 |
gen 全球通用(按语言存)/ cul 文化特色(按国家存,因为西语各国各有各的说法)| 素材 | 规模 | 说明 |
|---|---|---|
| 人生必做清单 | 100 条 | 带 <地标> 占位符,运行时自动替换成真实地标名;47 条绑定职业角色;每条带报酬 |
| 各国礼物 | 24 国专属 + 16 通用 | 完成任务时给 |
| 三语俏皮话 | 3 套 | 纯氛围 |
| 深度城市策展 | 103 城 × 654 条 × 1916 条外链 | 六维(文学/政治/历史/艺术/美食/音乐/经济),每条=标题+解说+维基/YouTube/B站链接 🔴 RPG 未使用 |
`
┌──────────────────────────────────────┐
│ 顶栏 HUD:城市名 · 金币 · 🌐语言 ⚙️设置 │ 固定 44px
│ 🖼️图集 📒记录 🎞️视频 │
├──────────────────────────────────────┤
│ 🎬 多媒体舞台(可有可无,高度可拖) │ ← 关键设计
├──────────────────────────────────────┤
│ │
│ 地图 = 剩下的全部空间 │
│ 📍别针 🧑人 🎁宝箱 🎤音乐家 🏛️地标 │
│ │
│ 🔍缩放 ⭕按钮圈 │
│ 🧭小地图 (7+1) │
└──────────────────────────────────────┘
`
核心设计原则(owner 反复迭代得到的):多媒体不浮在游戏上面,而是切走屏幕上方一条,游戏用剩下的部分 —— 两者互不打断。
| # | 范式 | 触发 | 表现 | 代码 |
|---|---|---|---|---|
| ① | 走 | 左半屏按住 / 点一下 / WASD | 浮动摇杆 · 走过去 · 键盘 | startStick / tapAt / keyVec |
| ② | 点一个人 → 他周围开一圈 | 点地图上的人 | 6-9 颗药丸绕他转,每颗=图标+文字 | npcRing() |
| ③ | 点 ✨ → 中央菜单 | 右下角圈心 | 三组:跟人 / 玩起来 / 这座城的事 | actMenu() |
| ④ | 冒泡对话 | 打招呼 / 闲聊 | 头顶三行:当地文字 + 读法 + 中文意思 | popSay() |
| ⑤ | 箭头指路 | 问路 / 演出预告 | 目标在屏内标他头上,不在则贴屏幕边缘当箭头 | setWay() / paintWay() |
② 是最标准的可插拔位:npcRing() 里的 items 数组加一项,就多一个互动动词 —— 未来任何新玩法都可以只做成"环上多一颗"。
| 动词 | 花费 | 效果 |
|---|---|---|
| 👋 打招呼 | 免费 | 他用当地话回一句,底下给中文意思 |
| 💬 闲聊 | 免费 | 换一套话术,不与打招呼重复 |
| ☕ 请一杯 | 🪙80 | 直接冒字,不弹窗 |
| 💃 跳舞 | 免费 | 两人一起蹦,有专属台词 |
| 🚶 跟我走 | 免费 | 他贴身跟随,可随时说"不用跟了" |
| 🎬 看视频 | 免费(顺手解锁该维度) | 跟他专业相关的视频;名人则是关于他的 |
| 📷 看照片 | 免费(摄影师专属) | 解锁这座城的实景照片 |
| ⭐ 他是谁 | 免费 | 名人简介卡 |
| 🧭 导游台 | 免费 | 城市介绍 + 今晚演出 |
| 🎉 派对 | 🪙300 | 满屏霓虹 + 烟花 + 所有人跳舞 |
| 🎆 烟花 | 🪙50 | 纯 CSS 粒子,路人会欢呼 |
| 🎤 自己开演唱会 | 免费 | 你当街头艺人,路人围观打赏 |
| 📣 现场喊话 | 免费 | 只在离舞台 350 米内出现 |
npcBubble(头顶身份牌,不可点)/ sayBubble(当地话)/ reply(回应,同屏多人错开冒)/ wayArrow(粉色发光指路箭头).dlgScroll 的改三段式(头 + 可滚区 + 常驻底部按钮)—— 治手机上"滚不动"L3(中,英,日),加第四语言只需扩表`
开场页(讲清玩法 + 发 10 万启动金 + 选目的地或随机)
↓ 从香港起飞,2D 卫星图上看着大圆航线飞过去,情绪横幅报里程时长
降落 → 🧭 导游主动搭话("欢迎来到 XX,这城有三件事你别错过")
↓
在城里走(步行 🚶 / 自行车 🚴 / 开车 🚗 三档速度)
├─ 遇到 🧑 职业 NPC → 聊天 → 免费解锁他那一维的当地视频
├─ 遇到 ⭐ 历史名人 → 先出简介卡,再开互动圈
├─ 开 🎁 宝箱 → 一首当地歌 / 现金 / 补给
├─ 走到 🏛️ 地标(未点开过的会发绿光召唤)→ 真实简介 + 实景照片
├─ 接 📦 跑腿单 / 载客 → 送到另一个真实地标 → 按距离给钱
├─ 📜 人生清单:每座城固定一条(按城名哈希),走到 120 米内即完成
└─ 📣 演出预告 → 箭头指路 → 买票 🪙180 → 满屏灯光特效演 3 分钟 → 散场余韵 45 秒
↓
🛂 盖章 · 攒里程 · 攒歌单 · 攒学会的外语句子
↓
飞下一座城(机票要花钱:短途贵/公里,长途摊薄)
↓
📒 旅行记录 → canvas 生成一张可保存的分享图
`
| 循环 | 驱动力 | 产出 | 文件 |
|---|---|---|---|
| 🔓 解锁 | 想看这座城的视频/照片 | 两条路:找对的职业聊天(免费)或花钱(🪙60/120) | rpg.js |
| 📦 跑腿 | 唯一的主动赚钱路径 | 金币,距离越远越多 | rpg.js |
| 📜 人生清单 | 每城一件"非做不可的事" | 金币 + 写进旅行记录 | life.js |
| 🎪 演唱会 | 今晚谁在演 | 门票消费 + setlist 收藏 | gig.js |
| 🎓 语言 | 听懂路人说什么 | 6 级熟练度(还没开口 → 出师)+ 测验 | lang.js |
| 🎵 音乐 | 被动收集 | "我的世界歌单" | radio.js |
这六条都往同一个地方汇流:trip 计数器(公里/城市/宝箱/听歌/看片/时长)→ 最后生成旅行报告分享图。
这是最好的模块化接口:任何新玩法只要往 trip 里记一笔,就自动进报告,不用改报告代码。
| 项目 | 数值 | 作用 |
|---|---|---|
| 开局资金 | 🪙100,000 | 最简单的一个难度旋钮:调 0=硬核生存,调无限=纯观光 |
| 机票 | <1000km 贵/公里,长途摊薄 | 唯一的大额支出,决定"能不能随便乱飞" |
| 跑腿报酬 | 距离加权,载客加成 | 唯一的正现金流 |
| 内容解锁 | 视频 🪙60 / 照片 🪙120 | 免费路径永远存在(找对的人) |
| 门票 | 🪙180 × 演出类型系数(0.35–1.9) | 同一场只收一次 |
| 派对/请客/烟花 | 🪙300 / 80 / 50 | 把钱变成体验 |
存档:13 个独立的 localStorage 键,每个玩法一把。这是个现成的模块化优势 —— 拆掉任何一个模块,不会污染别人的存档。
三个让世界不像死图的机制,都值得复用:
1. 密度随缩放调度:高空只铺 1 类人,街景铺 7 类;curGap 保证任意两人最小间距;超过 220 个实体自动回收远处的;每次缩放全清重铺
2. 演出会散场:一场演出挂 12 分钟就没了,演满 3 分钟自动散,走出 400 米算你自己离场,在城里待够 100 秒自动播报下一场 —— 世界不等你,它自己在动
3. 未访问的会发光:没点开过的地标发绿光召唤,点过就恢复普通
| 层 | 大类 | 模块数 | 换掉它意味着 |
|---|---|---|---|
| A | 🗺️ 世界底座 | 8 | 换一个星球(底图/缩放/城市库/飞行转场) |
| B | 🌐 实时外部数据源 | 12 | 换"真实感"的来源(维基/Wikidata/YouTube/Apple) |
| C | 📦 本地静态素材库 | 10 | 换弹药(语言/任务/策展内容/遗产地) |
| D | 🧍 地图实体层 | 8 | 换地图上有什么(人/名人/音乐家/宝箱/地标) |
| E | ✨ 互动动词层 | 10 | 换你能做什么 |
| F | 🎮 玩法循环层 | 9 | 换你为什么一直玩 |
| G | 🪙 经济与解锁层 | 7 | 换节奏松紧 |
| H | 🖥️ 呈现与外壳层 | 7 | 换皮(与玩法完全正交) |
合计 71 个模块。 层与层之间基本正交 —— 这意味着可以像调音台一样推拉。
| 配方 | 开的模块 | 一句话 | 需要改代码吗 |
|---|---|---|---|
| 🧭 现状 | 67 | 全开,信息密度最高 | 否(对照组) |
| 🎪 世界音乐节之旅 | 39 | 只追演出满世界跑 | 否(纯做减法) |
| 🗣️ 语言沉浸之旅 | 33 | 所有人只跟你说当地话 | 否 |
| 🏛️ 世界遗产朝圣 | 33 | 1864 处 UNESCO 逐个走到盖章 | ✅ 要(接 heritage.json) |
| ⭐ 名人之城 · 大师课 | 44 | 出生在这里的人 + 为他策展的知识卡 | ✅ 要(接 cities_deep.dims) |
| 📦 城市跑腿模拟 | 33 | 赚够钱才飞下一座城 | 否(把开局资金改成 200) |
| 🎬 纪录片模式 | 24 | 零操作,舞台常开自动轮播 | 否 |
| 🧒 儿童 / 低干扰版 | 36 | 没钱没锁没任务,只有世界 | 否 |
红队观察(对现状的最强反对):现在六条循环并行,新玩家落地 30 秒内同时被给到导游搭话、宝箱、演出预告、人生清单、路人冒泡 —— 注意力被切碎,每条循环都没被玩深。上面七个配方本质上都是对现状做减法,而做减法比做加法更可能提升体验。这一条可证伪:任何一个减法配方,如果单次游玩时长不如现状,那这个判断就是错的。
| # | 级别 | 问题 | 怎么补 |
|---|---|---|---|
| GAP1 | 🔴 高价值 | cities_deep.json 的 654 条策展内容被丢弃:boot() 里只取了 sum 和 ja,dims 整块没进 CITIES。这批内容含 1916 条人工挑过的外链,是全仓库离"能用"最近的知识资产 | add() 时把 dims 带上,城市面板多一个"深度"标签页。约 20 行 |
| GAP2 | 🔴 高价值 | heritage.json 的 1864 处世界遗产完全没接进 RPG,只有同目录的 2D 地图版在用 | boot() 加一路 fetch,遗产地当第 7 种实体 spawn,复用现成的盖章墙与地标发光逻辑 |
| GAP3 | 🟡 结构 | 两套内容分类各自为政:RPG 的 7 维(景点/建筑/历史/文化/市集/音乐/美食)与 cities_deep 的 7 维(文学/政治/历史/艺术/美食/音乐/经济)只有 3 个重合 | 做映射表,或并成统一 9-10 维轴。否则 GAP1 接进来会出现两套标签 |
| GAP4 | 🟡 结构 | 没有开关总闸:要做一个配方,得手工注释 spawn 调用和按钮;没有任何一处能一眼看到"这个世界开了哪些模块" | 抽 world.config.js,各模块在自己的 spawn 与按钮渲染处读一次开关,支持 rpg.html?preset=xxx。这是让"多做几个组合"真跑起来的唯一前置 |
| GAP5 | 🟢 观察 | 3D 地球飞行是现成但停用的资产(flight.js 264 行 + 全套地球贴图都在仓库) | 恢复 rpg.html 里被注释的两行,常量改 '3d' |
| GAP6 | 🟢 观察 | 新闻模块代码在、入口已被撤 | 想要时恢复约 5 行 |
建议顺序:GAP4(总闸)→ GAP2(遗产,最快见效的新玩法)→ GAP1+GAP3(策展内容 + 分类合并)→ GAP5(3D 转场 A/B)。
| 断言 | 等级 | 凭据 |
|---|---|---|
| 线上可访问,标题为「🧭 环球旅行 · 探索发现」 | E1 | curl 实测 HTTP 200 + grep title(2026-07-27) |
| 3689 座城 / 1864 处遗产 / 4308 句 / 100 任务 / 654 策展条目 / 1916 外链 | E1 | 直接 json.load 逐个 count,非估算 |
| heritage.json 未被 RPG 加载 | E1 | grep -c heritage rpg.html = 0;rpg.js 的 5 处命中全是关键词字符串,非文件引用 |
| cities_deep.dims 被丢弃 | E1 | boot() 源码:deep.forEach(c=>add(...,{sum:c.sum,ja:c.ja})),dims 未传 |
| 各接口的规模上限(geosearch 8km/25 个、10km/50 个等) | E1 | 源码参数直读 |
| 模块组合实验台可用 | E1 | Playwright 实测:8 层 / 71 模块 / 9 配方 / 6 缺口全部渲染,切配方统计从 67 变 39 变 33,console 零报错,已截图 |
| "做减法比做加法更可能提升体验" | 推测 | 这是判断不是事实,已在 4.2 给出可证伪条件 |
反对:「把项目拆成 71 个模块,本身就是过度工程。真正的问题可能是玩法不够深,而不是不够可组合 —— 拆得再细,组合出来的也还是同一批浅玩法。」
回应:这条反对部分成立,我接受它的一半。拆解不会自动让玩法变深,这一点是对的。但两件事使拆解仍然值得做:
1. 拆解过程本身已经找出两块被浪费的高价值资产(654 条策展内容 + 1864 处遗产地),这是纯粹的净收益,与"要不要模块化"无关;
2. 主席的诉求明确是"未来做成模块化、多做组合看效果",拆解是这个诉求的直接交付物,不是我自己加的工程。
但我把这条反对写进结论:GAP4 的总闸做完后,建议先只做 1-2 个减法配方并真玩一次,验证"减法是否真的更好玩",再决定要不要继续扩配方 —— 而不是一口气把八个配方都实现。
world.config.js 时,某些模块可能需要合并或再拆| 产物 | 位置 |
|---|---|
| 🧩 模块组合实验台(可点、可切配方、可导出配置) | https://metazero-terminal.pages.dev/travel-2d/modules.html |
| 📋 机器可读模块注册表(唯一权威源) | web/terminal/travel-2d/modules.json |
| 📄 本报告 | reports/2026-07-27_travel2d-RPG-素材清单-互动模式-游戏方式-模块化拆解.md |
| 🎮 被研究的对象 | https://metazero-terminal.pages.dev/travel-2d/rpg |