当前位置:首页>游戏攻略>我把一块开发板变成了离线游戏服务器:手机连上热点就开玩

我把一块开发板变成了离线游戏服务器:手机连上热点就开玩

  • 更新时间 2026-10-11 22:50:48
我把一块开发板变成了离线游戏服务器:手机连上热点就开玩
我桌上这块板子,平时是我打字用的键盘。这几天它多了个身份:一台不用联网的游戏服务器。

打开电源,它自己开一个 Wi-Fi 热点。手机连上去——不用输网址、不用装 App、不用扫码——浏览器自己弹出游戏页面,用板子上的实体键就能玩。整个过程没有互联网参与。

这篇写给想让"板子自己把内容送出去"的人。下面讲三件事:游戏到底跑在哪、"连上就弹页"是怎么做到的、以及我在真机上踩了哪些坑。

(配图 1:系统架构图|板子「热点 / HTTP / WebSocket / 按键」↔ 手机「浏览器:显示 + 触控」)

一、为什么非要做成这样

起因是一个很具体的问题:板子能不能把内容直接送到别人眼前?

我试过常规做法:板子起个网页,手机打开浏览器输 192.168.4.1。能用,但每次都要教人输地址,体验立刻掉一档。要是还得连外网、装 App,那这台"游戏机"就永远只属于我自己。

我要的效果就一句话:任何人拿起手机,连上热点,零操作开始玩。

二、先把分工定下来:游戏跑在哪

这是这个项目里我最纠结的一步。

摆在我面前的有三种:全部跑在手机上,板子只当手柄;全部跑在板子上,手机只当屏幕;或者两边分担。

我最后选的是:板子负责服务器和按键,手机只当显示器和观众屏。

理由很实际:板子有热点、有存储、有实体键,但它没有屏幕;手机有屏幕、有浏览器,但它不该承担"把游戏发给别人"这件事。分工定下来,后面每一步就都顺了。

三、板子怎么当服务器

板子开一个叫 Hakimi-Game 的热点,地址 192.168.4.1,无密码,最多 8 台设备同时连。

游戏网页和音效一共约 23KB,全部存在板载 Flash 里——我从 16MB 里划了 8MB 做存储分区(当时还剩约 11MB 空闲)。所以它不需要互联网,你的手机也不用联网。

板子上跑着一个 HTTP 服务器(把网页发给手机)和一个 WebSocket 服务器(把按键事件推给手机),按键轮询单独一个模块。

四、怎么做到"连上就弹页"

(配图 2:三步弹页原理图|四格箭头:连热点 → DNS 全指回板子 → 系统探测 → 302 自动弹页)

我用的机制叫「强制门户」(Captive Portal)——就是你在酒店、机场连 Wi-Fi 时自动弹出的那个登录页。我想把"打开游戏"这件事交给系统自己完成。

三步:

①板子里跑一个极简 DNS 服务器,把所有域名都解析回它自己;

②手机连上 Wi-Fi 后,系统会主动请求一个固定地址,判断"这个网络能不能上网"——这个请求打到了板子上;

③板子对探测路径返回302 重定向到/,系统判定"这是个需要登录的网络",自动弹出浏览器。

手机上看到的就是:连上热点,一两秒后游戏页面自己跳出来。

五、实体键

(配图 3:游戏画面 + 板上 S1/S2/S7/S8 的位置标注)

8 颗实体键全部接进了游戏,常用的是四颗:S1 左移、S2 右移、S7 跳跃、S8 开始/暂停。

按键轮询在固件里单独一个模块,读到按下就通过 WebSocket 发给控制设备。实体键和触屏完全是两种手感——尤其跳跃,手指按下去那一下,比在屏幕上点准得多。

顺带解决了一个我一开始没想到的问题:多台设备同时连怎么办?规则是"先到先得"——第一台打开页面的设备是控制设备,其他设备同屏观看;控制设备断开,控制权自动转移给下一台。

想复刻的话,工程侧是这样:硬件 EasyInput V2.0(ESP32-S3,16MB Flash + 8MB PSRAM),开发框架 ESP-IDF v5.5.5;我没有动原来的键盘固件,而是新建了一个独立工程,固件编出来 874KB,分区还剩 72%。

六、跑通之后是什么样

真机上逐项验收通过:

  • ✅ 热点连接后自动弹出游戏页
  • ✅ 实体键控制正常(左 / 右 / 跳 / 开始)
  • ✅ 多设备:第一台控制、第二台观众、断开自动转移
  • ✅ 音效有(首次触摸屏幕解锁音频后,按键都有声音)
  • ✅ 完整关卡可玩:金币、敌人、终点旗杆一条链路走通

现在的日常是:板子放桌上,朋友来直接连热点就能玩,不用我讲怎么操作。

后来又加了三个"少插一次电脑"的东西:

  • 板载关卡编辑器:不用电脑,在手机上就能画关卡,一共 12 种元素;
  • BGM 编排器:15 个音高 × 16 个节拍,BPM 40–240,点格子编一段音乐;
  • 免烧录保存:改完的关卡通过 WebSocket 直接存进板子 Flash,重开游戏就加载,不用重新烧固件。

七、踩过的三个坑

坑 1:HTTP 服务器根本起不来。

代码逻辑没问题,板子就是起不来。最后发现是 max_open_sockets = 8 超过了 LWIP 的上限——LWIP 是板子上的轻量网络协议栈,能同时开的连接数有上限。保持默认值 7 就好了。

教训:默认值不是随便能改的,尤其在资源受限的嵌入式里。

坑 2:手机连上了,但不弹页面。

热点正常、DHCP 正常、网页手输地址也能打开——就是系统不弹。原因是板子对探测路径返回了204,系统把它理解成"这个网络可用",于是什么都不做。改成302 重定向到/之后,自动弹页立刻生效。

同一个机制,返回码不同,行为完全相反。

坑 3:一切正常,就是没有声音。

页面能玩、按键有反应,就是静音。查了半天不是代码问题——是华为平板浏览器把 AudioContext 一直挂在 suspended 状态,而且不是 HTTPS 的限制,纯粹是平台行为。最后改用 HTML5 Audio + data URI 播放音效(data URI 就是把音频直接编码进网页,不额外请求文件);又发现方波音色太刺耳、连按还会卡,就换成正弦波、音量压到 45%、加了播放节流。

还有一个小的:一开始左右键都只能前进。原因是网页里按键的 case 值和固件里的枚举错位了,改成按固件枚举重写映射才对上。这类"看起来全都对、就是一个值错"的问题,只有真机能暴露。

八、下一步

我想要的下一步是多人对战:不同设备控制不同角色,而不是一台玩、其他人看。再往后想把默认关卡和角色都换成更"哈基米"的东西。

代码和完整文档我放在这里了:

https://gitee.com/weak0001/easy-game-server

如果你也在玩开发板,留言告诉我你更想看哪个:① 安装包和固件 ② 我画的关卡文件 ③ 一步步的复刻步骤。哪个多我先整理哪个。

随机文章