背景: 后端 C#/.NET,近 18 年专业经验,如果把早年瞎折腾也算上,接触 C# 有 24 年了。
说实话,JavaScript 一直是我被迫才用的语言,从来不是真正掌握的那种。所以我挑了一个自己能端到端交付的最小游戏,逼着自己用正确的方式把它做出来。

结果就是做了个叫 Sunbird 的单点街机飞行游戏(没错,山寨 Flappy Bird)。纯 HTML5 Canvas,没用引擎和框架,用 Capacitor 打包成 iOS 和 Android 版本。

为什么选这个项目:
- Canvas 游戏循环会立刻惩罚马虎的 JS:60fps 下,每一次随意分配或懒惰闭包都能感受到。
- 不用引擎意味着得自己写物理、碰撞、状态机、持久化和音频。所有声音都用 Web Audio 振荡器合成。
- 我想在工作时保持同样的准则:SOLID、DRY、SoC、YAGNI。在没有编译器提醒的情况下,做到这些更难。
- 往两个商店发布让我体验了那些不光彩的部分:平台抽象、版本化存档迁移、带发布闸门的 CI、无头测试。

对过去的自己说两句话:
- 确定性并非免费。所有人都从同一个种子获得每日关卡。我曾引入一个 bug:障碍物间隙根据视口高度生成,导致不同设备得到不同关卡——这悄然破坏了共享排行榜的意义。修复方法是将间隙锚定到地面,使用固定偏移。
- 一个能自动玩游戏的无头自动驾驶脚本胜过手动测试。用 jsdom 加模拟飞行器跑关卡,能抓住我手工永远发现不了的回归问题。

游戏已上线,欢迎体验:
https://play.google.com/store/apps/details?id=com.sunbird.game

真正有用的反馈:
- 在你设备上点击手感对吗?有没有输入延迟?
- 前三局里难度曲线合理吗?还是纯粹让人觉得不公平?
- 代码相关部分(Capacitor 桥接、存档迁移、音频方案)里,哪些你会换种做法?

我不是在求安装量,而是希望有人告诉我哪里弱。