Files
kidgo/.workbuddy/memory/2026-10-20.md
T
2026-10-20 22:21:26 +08:00

88 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-10-20
## 项目:IWBT C 同人平台跳跃游戏(网站)
从零搭建 `/Users/cancerai/tmp/iwanna`,纯前端无依赖(原生 ES modules + Canvas 2D),致敬 I Wanna Be The Guy / I Wanna Be The Creator。
### 架构
- `index.html` + `css/style.css` + `js/`
- `js/util.js` 常量(TILE=32,房间 800x608)
- `js/input.js` IWBT 键位(Shift/Space/Z 跳,X 射击,R 重开,Esc 暂停)
- `js/player.js` 手感物理:**重力 0.4、跳 8.5、二段跳 7.6、水平 3、最大下落 9、松手即停无惯性、松跳削减高度**
- `js/level.js` ASCII 网格解析 → tiles + 实体 + 事件系统(坑向触发器)
- `js/boss.js` 三阶段 BOSS(guy / mecha / devil),BOSS 贴地活动以保证站地平射可命中
- `js/camera.js` 跟随 / 锁定 / 缩放(「摄像头」道具效果)
- `js/levels/{tutorial,jump,endurance,boss,troll}.js` 共 **17 关**(教学2 + 跳刺5 + 耐久3 + BOSS3 + 坑向4)
- `js/editor.js` 自制关卡编辑器(localStorage 存档、导入导出 JSON)
- `js/save.js` localStorage 通关记录
### 关卡 ASCII 符号约定
`#@=M` 方块变体、`%` 冰、`~` 水、`-` 单向台、`V` 消失块、`*` 美味水果(即死)、
`^v<>` 四向刺、`S` 出生、`G` 存档、`X` 终点、`P` 手枪、`F` 苹果、`J` 跳刷新、`W` 传送门、
`T` 提示牌、`O` 炮台、`D` 掉落刺、`C` 摄像头区、`B` BOSS、`!` 事件触发器
### 关键设计约束(改关卡时必须遵守)
- 单次跳跃可上 **2 格(64px)**,二段跳可上 **3 格(96px)**,理论极限 ~5 格
- 平跳水平约 **4 格(128px)**,二段跳约 **6 格**
- 平台所在行 row R,玩家站立的台面高度 = `R * 32`
- 相邻平台垂直差 ≤ 96px、水平间隙 ≤ 96px 是安全设计区间
- 刺的碰撞盒比格子小(宽容判定)
### 测试工具(tools/)
- `check.mjs` 关卡格式校验(行宽/字符/S/X 数量/炮台·传送门·BOSS 配置数量一致)
- `smoke.mjs` 无头物理冒烟(构造全部关卡、模拟输入、死亡重生、BOSS 受伤、传送门)
- `dom-smoke.mjs` mock DOM 跑通 main.js 入口
- **`solve.mjs` 可达性求解器**:用真实物理常量做 BFS(走/落/跳×二段跳时机/空中转向),
验证终点与每个存档点可达。水当作可站立面、移动平台整条路径当桥(乐观)。
**改关卡后必跑**,否则很容易做出无法通关的图。
运行:`node tools/xxx.mjs`
### 第二轮改造(用户反馈后)
- 删除主菜单「开始游戏」按钮(点了没反应),只保留「关卡选择」进游戏
- 新增 `js/levels/kit.js`:`G(w,rows)` 自动补宽并把最后一列设为墙、`rep/E/plat/ent/flr` 辅助,
**写关卡不要再手工数点**,用这些函数拼行
- 关卡全面加长加大:跳刺 5→**10** 关(w 44~80、h 19~32),耐久 3→4 关(e1 100 格 / e4 120 格),
共 **23** 关;BOSS 血量上调(guy 72 / mecha 96 / devil 128,阶段按血量比例触发不受影响)
- `js/level.js` 掉落刺落地后 80 帧自动消失(否则会永久堵死落脚点)
### 第三轮:修存档点「没用」的 bug
根因:**R 键语义错**。IWBT 里 R = 自杀并回到最近存档点,但原实现把 R 绑成"整关重开"
(`startLevel` 重建 Level+Player,`savePoint` 清零)。玩家死了本能按 R → 存档进度全丢 → 存档点形同虚设。
修复与改动:
- `js/input.js`:`restart:['KeyR']` → `suicide:['KeyR']` + `restart:['Backspace']`
- `js/main.js`:新增 `suicide()`(调 `player.kill()`,死亡数+1,自动回存档点);暂停菜单按钮 = 整关重开
- 重生后 `cam.snapTo()` 立即对准(原来镜头慢慢 lerp,看着像没回去)
- `js/player.js`:存档点判定盒外扩 6px;激活时 toast「存档点 n/N 已激活」;respawn 加防卡墙顶出
- `js/level.js`:存档点编号 `e.no` + `totalSaves`;`js/ui.js` + HUD 新增 `存档 n/N` 指示
- `js/sprites.js`:未激活存档点加呼吸光环、颜色提亮(原来 `#5d4a72` 太暗看不清)
- `js/levels/jump.js` j2:存档点 (6,22) 悬空导致重生即坠落,移到 (15,22) 平台上
新增测试:`tools/save-test.mjs`(存档点激活+重生全关卡)、`tools/key-test.mjs`(R/Backspace 语义回归)、
`tools/save-diag.mjs`(存档点放置环境诊断)、`tools/bot.mjs`(真实物理机器人试玩)
### 第四轮:跳刺关全面加大加难 + 去掉存档点 toast
- 去掉「存档点 n/N 已激活」toast(user 要求);HUD 的 `存档 n/N` 指示保留
- `js/levels/kit.js` 新增 **`Grid` 网格构建器**(`.rect/.hline/.vline/.border/.out()`)和 `chain()`。
**大地图一律用 Grid 写,别再拼字符串**——104~150 宽的地图拼字符串必然错列
- 跳刺 10 关全部重写,尺寸 68×52 ~ 150×40(原来最大 80×32):
- j1 104×20 刺海长廊+竖井收尾 / j2 68×52 高塔 / j3 140×22 一格宽钢丝(顶刺)+竖井
- j4 130×24 冰面+冰柱+竖井 / j5 120×24 移动平台+炮台+竖井 / j6 132×34 双层层+竖井
- j7 72×52 掉落刺高塔 / j8 130×26 冰→塌陷浮桥→钢丝→单向台上行 / j9 128×34 三层+苹果
- j10 150×40 冰→钢丝→移动平台→竖井→钢丝
- 存档点压到 3~7 个(原 4~7 且关卡短一半),坑宽 4~6 格,落脚点 1~2 格
- 新增工具:`tools/reach-diag.mjs`(按行打印可达 x 范围,定位断连)、
`tools/jumpdist.mjs`(用真实 Player 测跳跃距离)、`tools/bot.mjs`、`tools/save-diag.mjs`
- `solve.mjs` 状态上限 6000→40000,并支持 `DJ=0,12,24` 环境变量收紧二段跳时机做鲁棒性检查
### 关键物理实测(真实引擎,tools/jumpdist.mjs)
单跳水平 **138px(4.3 格)**;二段跳随时机 156 / 183 / 207 / 225 / **237px(7.4 格)**。
求解器按 127 / 206 算,**比真实引擎更保守 → 求解器判可达即真人必可过**。
### 天花板刺摆放规则(踩过的坑)
- 平台行 P,天花板刺放 **P-5**:允许完整单跳、二段跳必死 → 该段坑宽只能 ≤ 4 格
- P-3 只允许 rise<65px 的小跳;P-7 以外基本无效
- 竖井/塔的入口、转向处**不能放侧壁刺**,否则跳跃弧线正好撞上(j3/j4 都栽过)
- 走廊尽头接竖井时,底座与走廊末块留 **3 格空隙、高差 2 行** 最稳
### 运行方式
ES modules 需要 HTTP:`python3 -m http.server 8123`(已提供 `启动游戏.command` 双击脚本)