把 Flash 游戏搬到网页上
把 Flash 游戏搬到网页上
游戏区放了 28 款老 Flash 游戏,涵盖 Submachine、Daymare Town、Trollface Quest 这些经典系列。技术上主要靠 Ruffle——一个用 Rust 写的 Flash 模拟器,能编译成 WebAssembly 在浏览器里跑。
资源整理
手头有一批从 Flashpoint Archive 导出的 .swf 文件。这些文件的命名和路径本来就比较混乱——有些直接以 UUID 命名,有些嵌在多层文件夹里。我写了个脚本把每个游戏的 .swf 提取出来,按游戏 ID 重新组织到 public/games/swf/ 下,方便前端引用。
但有些游戏的 .swf 依赖外部资源文件(比如 Windosill 有单独的 sound 和 class 文件),单纯的 .swf 文件跑不起来。Ruffle 的网络请求走的是 fetch API,所以需要在本地搭建对应的文件路径映射。
Ruffle 的集成方式
Ruffle 提供两种集成方式:一种是直接把 ruflle 作为 script 加载,自动替换页面上的 flash 元素;另一种是通过 iframe 加载 play.html。
我用的是 iframe 方案,把 Ruffle 的 runtime 放在 /games/ruffle/ 目录下,游戏页面通过 iframe 加载 play.html?swf=xxx.swf。这样游戏和主站的样式完全隔离,不会互相影响。
ChunkLoadingError
部署后遇到的一个问题是 Ruffle 的 core 文件会报 ChunkLoadError。原因是 Ruffle 的 .wasm 和 .js 文件是按需拆分的,部署到子目录后,chunk 的加载路径不对。
排查后发现 Ruffle 在初始化时通过相对路径加载 core.ruffle.xxx.js,但由于 iframe 的 src 是 /games/play.html,chunk 的加载路径变成了 /games/core.ruffle.xxx.js,而实际文件在 /games/ruffle/core.ruffle.xxx.js。
解决方案是在 play.html 里显式指定 RufflePlayer.config.base = "/games/ruffle/",让 Ruffle 知道去哪找运行时文件。
手机端的控制方案
Flash 游戏主要依赖键盘输入,手机上不好处理。目前在游戏页面加了一个虚拟 D-Pad 面板,包含方向键和 Space/Enter,通过 postMessage 把按键事件发送到 iframe 里的游戏。
这个方案体验上只能算"能用",打 Submachine 这种点解谜游戏还行,但 Trollface Quest 那种需要精确定位的就不太友好。后续考虑加一个可拖拽的虚拟鼠标。