# 哆啦A梦 · 立体铜锣烧大冒险 1-1

固定横版视角的 2.5D 网页游戏：移动、跳跃和碰撞在二维平面内完成，角色与场景由 Three.js 渲染为有厚度、光照和阴影的微缩玩具世界。

主角复用了工作区 `doraemon-threejs` 展柜里的同一套模型几何、材质与骨架：曲面白脸、眼睛、红鼻子、胡须、四次元口袋、金属铃铛、尾巴和可摆动的四肢均保留。模型代码独立保存到本文件夹，运行时不依赖展柜项目。

## 运行

直接用支持 WebGL 的现代浏览器打开 `index.html`。Three.js 0.160.0 已保存在 `vendor/`，无需安装依赖或联网。也可在本目录运行：

```sh
python3 -m http.server 8877 --bind 127.0.0.1
```

访问 <http://localhost:8877>。

## 操作

| 操作 | 按键 |
|---|---|
| 移动 | ← / → 或 A / D |
| 跳跃 | 空格 / ↑ / W |
| 下降 / 进入密室 | ↓ / S |
| 空气炮向前开炮 / 向后开炮 | 取得空气炮后 X / Z；未取得时隐藏按键 |
| 暂停 / 继续 | P / Esc |
| 重新开始 | R |

触屏使用方向与 A 跳跃。已取消手动加速，缩小道具与空气炮反冲仍可提高移动速度。取得空气炮后，画面内短暂显示 4 秒「Z 向后开炮 · X 向前开炮」，同时出现对应按钮。失去生命后提示与按钮一起隐藏。未持有空气炮时，不显示对应的操作提示。其他能力全部拾取即生效，不需要选择按键。

## 手机视野与在线榜单

手机默认放大 ×2；「放大」按钮仍可在 ×1、×1.5、×2 之间切换，并记住选择。

香港服务器版本提供访客统计和共享排行榜：首次通关后，可自愿留下 2–12 位英文字母代号，也可跳过。第二、三、四周目沿用已有选择，通关成绩自动更新。榜单展示最高累计分和已通关周目，打开时每 30 秒自动刷新，也可手动刷新。

服务器以浏览器匿名 Cookie 区分访客并记录访问次数，无法据此知道真实身份。清除浏览器数据或换设备可能重复计数；统计从新功能上线开始。原有个人纪录仍保存在当前浏览器。仅静态运行时可以正常玩游戏，但在线统计和榜单需要配套 API。

服务端记录、管理员查看命令和部署说明见 `server/README.md`。

## 随机限时道具

每周目开始时，将放大灯、缩小灯、空气炮、竹蜻蜓和 1UP 铃铛随机打乱，分配至五个普通补给点。普通补给点从尚未出现的道具中选择；原奖励不可用时改抽其他可用道具，池子耗尽则给铜锣烧。已装备空气炮时，所有奖励池排除空气炮，包含带着空气炮进入下一周目的情况。空气炮每周目仍最多掉落一次。重新开始整局会重新洗牌；损失生命不会重置掉落记录。

- **＋ 放大灯**：拾取后放大并免疫敌人伤害，持续 10 秒，强化的金色光圈表示生效；期间不受老鼠惊吓，不会尖叫、强制乱跑或触发惊吓高跳，表情保持正常。时间到恢复标准体型。深坑和超时仍会损失生命。
- **− 缩小灯**：拾取后缩小，移动速度提高至标准的 1.65 倍，持续 10 秒。时间到恢复标准体型。
- **空气炮**：拾取后可用 X 向前、Z 向后发射空气波，没有时间限制；失去生命立即丢失，复活后需要重新取得。通关进入下一周目时仍保留。
- **竹蜻蜓**：拾取后立即起飞，按起飞时实际体型确定本次时长：大体型 7 秒、标准 10 秒、迷你 13 秒。跳跃键上升、↓ 下降、松开悬停，到时恢复重力。没有启用按钮，飞行途中改变体型不会重置或改写本次倒计时。
- **铃铛**：1UP，增加一条生命，属于即时奖励。

限时能力的计时只在正常游戏时推进，暂停时冻结。放大灯与缩小灯互相覆盖，后拾取的一种重新计时 10 秒。失去生命会清除放大、缩小和飞行效果，同时丢失空气炮。恢复标准体型时会检查周围空间，避免卡入地形。

任意门通关依然包含旗杆高度奖励与剩余时间 × 50 分，结算展示最快用时、最高速度及组合使用次数。纪录保存在当前浏览器。游戏结束页保留历史最高分、到达的最高周目、历史最高速度和各周目的最快通关记录；重开与关闭页面时也保存当前最高分和速度。竹蜻蜓倒计时独立显示完整名称与秒数，手机上也不会与其他道具文字挤在同一行。

## 递增周目

通关结算后，点击「进入下一周目」或按 Enter / 空格继续同一关卡。每次递进以上一周目为基础：

| 周目 | 敌人总数量 | 敌人速度 | 得分倍率 |
|---|---|---|---|
| 1 | 17（×1） | ×1 | ×1 |
| 2 | 34（×2） | ×1.5 | ×1.5 |
| 3 | 68（×4） | ×2.25 | ×2.25 |
| 4 | 136（×8） | ×3.375 | ×3.375 |

后续依次递增。第二周目起，新增敌人交替从玩家后方和前方的安全距离分批进入；地形与角色基础速度保持原关卡设定，移动龟壳也按周目提高速度。

所有加分（包括铜锣烧、砖块、道具、踩怪连击、旗杆高度和剩余时间）乘以当前周目的得分倍率，结果四舍五入到整数。时间结算按已转换时间的整体分值取整。1UP 仍奖励一条生命。

进入下一周目保留累计分数、铜锣烧数量、剩余生命和已取得的空气炮；计时、临时能力、地形、敌人和随机掉落重新开始。最快通关时间与最高速度按周目分别记录，保留此前的第一周目纪录。R /「重新开始」以及 GAME OVER 后重开均回到第一周目。

## 踩怪与连击奖励

参考 NES《Super Mario Bros.》原版的分值表和连击方式，击败怪物时会在现场弹出分数，并计入总分：

- 连续不落地踩怪：100 → 200 → 400 → 500 → 800 → 1000 → 2000 → 4000 → 5000 → 8000 → 1UP；之后每次继续连踩都奖 1UP。落到地形上、损失生命或进入隧道后重新计数。
- 踩中背甲小鼠会将其变成静止龟壳，也有踩怪奖励。地面踢出静止龟壳另奖 400 分；空中连踩后踢壳的奖励会提高。
- 同一龟壳连续撞怪：500 → 800 → 1000 → 2000 → 4000 → 5000 → 8000 → 1UP，之后继续撞怪都奖 1UP。撞墙保留连击，停下再踢重新计算，每只怪物只结算一次。
- 空气炮击败普通小鼠 100 分，背甲小鼠 200 分。放大灯无敌撞怪也会显示奖励。

任意门内侧使用深蓝星空和微弱闪烁的星点。小鼠按最新反馈缩小为豆豆眼、圆团身体、大圆耳和一笔卷尾的抽象卡通造型，碰撞范围同步缩小，支持站立、奔跑、跃起；鼻尖沿移动方向，背甲版本对应龟壳玩法。

## 代码与素材

- `index.html` / `style.css`：页面、HUD 和控制界面。
- `level.js`：按 World 1-1 原场景整理的二维关卡碰撞数据。
- `engine.js`：移动、跳跃、敌人、道具、密室、计分与通关状态。
- `game.js`：键盘和触屏输入、声音与渲染循环。
- `world3d.js`：正交镜头、立体地形、道具、机械鼠、时光隧道、任意门、光照与阴影。
- `doraemon-model.js`：从既有 Three.js 展柜提取的哆啦A梦模型，包含原材质与关节。
- `vendor/three.min.js` / `vendor/THREE-LICENSE.txt`：Three.js 0.160.0 与 MIT 许可。
- `assets/`：保留原下载的 NES 图集与地图参考。当前画面使用三维几何体，不以原场景图作为背景。
- `theme.js`：保留的代码像素美术，当前立体版不加载。
- `preview.jpg`：立体版的浏览器实际画面。

## 检查

```sh
node --test engine.test.cjs model.test.cjs render-parts.test.cjs asset.test.cjs
```

现有检查覆盖原有玩法、角色尺寸变化、密室衔接、模型关键部件、尺寸适配、关节变换、空气炮套手与朝向、出膛位置和宽屏敌人激活，以及竹蜻蜓起飞、悬停、升降、10 秒到期、飞行碰撞、旗杆分档、任意门开关与进门顺序、时间转换和防重复加分，以及连续踩怪、龟壳连击、奖命、重新踢壳后的连击重置、飘分寿命和小鼠鼻尖与运动方向一致。最新玩法调整未运行自动化检查。

## 来源

关卡参考及原图集来自 [Mario Universe — Super Mario Bros. Sprite Sheets (NES)](https://www.mariouniverse.com/sprites-nes-smb/)。原角色动作图集署名 Ultram2003，其他图集包含 Zeon、Beam Luigi Yoshi 的署名。原作角色和画面版权归相应权利方。

哆啦A梦模型沿用本工作区既有 `doraemon-threejs/index.html` 的模型实现；其造型参考记录保存在原展柜的 `references/sources.md`。Three.js 采用 MIT 许可，许可全文随项目保存。

当前空气炮装在前方手臂的腕部，并随左右朝向切换，炮口与发射方向一致。小鼠采用更小的圆团与豆豆眼造型，带背甲的版本可踩成龟壳。模型造型可在 `tools/art-preview.html` 单独查看。浏览器已检查 390×844 竖屏及 844×390 横屏布局；尚未在实体手机上测量帧率。

计分参考：[任天堂原版说明书](https://www.nintendo.co.jp/clv/manuals/en/pdf/CLV-P-NAAAE.pdf)，以及 [NES 原程序反汇编](https://www.6502disassembly.com/nes-smb/SuperMarioBros.html) 中的 `ScoreUpdateData`、`StompChainCounter`、`ShellChainCounter` 和踢壳奖励逻辑。

## 独立 3D 资产

打开 [3D 资产查看器](assets3d/index.html) 可比较参考图、切换老鼠姿态和哆啦A梦的两种受惊表情。`assets3d/glb/` 保存带动作的老鼠、瞪眼受惊哆啦A梦、闭眼尖叫哆啦A梦三件 GLB；用法及动画名称见 [资产说明](assets3d/README.md)。表情使用真实嘴部、舌头、眼睛和汗滴网格，并已按附近活老鼠的距离接入游戏。

## 空气波、惊吓与探索

空气炮发出透明的扩散压力环，水平前进并消散，无弹芯、重力和地面反弹。命中砖块等同顶砖，可击碎砖块、顶出问号砖道具并正常计分。向前开炮产生向后反冲，向后开炮产生向前冲力；飞行期间反冲更强，缩小期间还会向上超级弹射。

老鼠保留短暂惊吓乱跑和高跳机制，高空隐藏砖仍可通过组合玩法探索。开屏只显示基础操作，不解释隐藏机制；平时仅显示必要计时、分数和持有空气炮后的 X / Z 按键。


## 手机 Safari

触屏保留左右移动、向下和跳跃；按住「▼」可进入可用的管道，使用竹蜻蜓时可下降。取得空气炮后，两个开炮按钮显示在右侧跳跃键旁。窄屏会调整方向键宽度，让三个方向键与右侧操作区同时显示。电脑键盘的 ↓ / S 同样可下降或进入隧道。游戏区域禁用文字选择、长按菜单和拖拽。

手机开始游戏时自动铺满可用窗口，支持的浏览器会请求系统全屏。iPhone Safari 普通标签页若不支持网页全屏，需要通过「分享 → 添加到主屏幕」打开网页应用，才能去掉地址栏。已附带网页应用清单、主屏幕图标与安全区适配。游戏旋转、地址栏变化后会随可用视口调整尺寸。

本次已完成脚本语法检查，尚未在实体 iPhone Safari 上验证。

手机竖屏默认将游戏视野放大 2 倍，顶部「放大」可切换 1 / 1.5 / 2 倍并记住选择。角色与镜头同步缩放，竖屏场景限制高度以减少空天空；放大后镜头会跟随高跳与飞行。手机 HUD、开始/继续和触屏按钮字号已放大。横竖屏布局按 Safari visualViewport 的真实宽高切换，暂停/重开并入顶部工具栏。


## 电脑版空气炮提示与终点保护

取得空气炮后，电脑版持续显示「空气炮 · Z 向后开炮 · X 向前开炮」，对应按钮也保留 X / Z 字样；缩短窗口或进入大屏仍能看到。失去空气炮后一起隐藏。手机仍只在拾取时短暂提示，操作按钮保留在跳跃键旁。

终点地面右缘向内 16 像素处增加全高度空气墙，阻止角色与空气炮反冲越出最后平台。飞越旗杆顶端后，在旗杆之后回到通关高度也可正常触发结算；终点判定优先于敌人伤害，触发后沿用旗杆、任意门和时间计分流程。


## 隐藏砖奖励

每块隐藏砖在首次顶开时独立随机：50% 直接获得铜锣烧，50% 掉落一个道具。抽中道具时，从放大灯、缩小灯、竹蜻蜓、铃铛及符合条件的空气炮中随机选择。隐藏砖允许再次获得已出现过的非空气炮道具，以保证道具分支不会因普通补给池耗尽而变成铜锣烧。已装备或本周目已掉落过空气炮时，隐藏砖也不会再掉空气炮。

每块隐藏砖只结算一次，空中秘藏的额外分数保持不变。普通问号砖、砖块预设的铜锣烧奖励不受 50/50 规则影响。
