⚡ OpsAILab.cc

不买 Switch,我用一个摄像头给儿子做了台体感游戏机

纯前端、零依赖、图像不上传。拆解摄像头体感跳跃游戏的原理:帧差法动作检测、跳跃判定、误触发抑制,以及为什么它对儿童视力更友好。

· 3 分钟阅读 · 数海独航
#体感游戏#Canvas#前端实战#亲子

儿子五岁,迷上了商场里的体感游戏机。一台 Switch 加两个手柄两千多,而真正的问题不是钱——是他已经每天盯着屏幕的时间够长了。

于是我换了个思路:屏幕里的角色,由他自己的身体来操控。站着、蹲下、跳起来,屏幕里的小人跟着动。做完之后他每天主动去客厅”蹦”十分钟,出一身汗,比任何护眼提醒都管用。

而且整个过程没有装任何 SDK、没有上传一帧图像——纯浏览器 API,二十来分钟跑通。

一、效果:摄像头就是手柄

打开页面、允许摄像头、退后 1.5 米,然后:

  • 跳起来 → 角色跳起,越过迎面而来的障碍
  • 不动 → 角色站着,障碍继续逼近
  • 撞到障碍 → 游戏结束,最高分存在本地

你现在就可以在这里玩:极客实验室 · 体感跳跃

二、为什么不用现成的姿态识别库

主流的姿态识别方案有两种:调用云端 API,或者本地加载 MediaPipe / TensorFlow.js 模型。

  • 云端 API:每一帧画面都要上传,孩子的影像数据离开家庭网络。直接否决。
  • 本地模型:隐私没问题,但首次加载 3~10 MB 模型文件,老旧笔记本和低端平板上会卡,而且依赖 CDN 可用性。

最后选择最原始但最稳的方案:帧差法(Frame Differencing)。它不需要任何模型,几十行代码,5 年前的笔记本也能跑 60 帧。

三、原理:三行核心逻辑

把摄像头画面缩到很小的灰度图,逐像素和上一帧比较,得到”哪里在动”:

// 160x120 灰度帧差
const diff = new Uint8Array(W * H);
for (let i = 0; i < W * H; i++) {
  diff[i] = Math.abs(curr[i] - prev[i]) > 25 ? 255 : 0;
}

动起来的像素在画面上半部分明显增多,说明身体向上运动——这就是”跳”。

完整判定逻辑还要处理三件事:

  1. 能量阈值:统计上半屏的”运动像素占比”,超过 12% 认为是一次有效动作,避免风吹窗帘误触发。
  2. 冷却时间:一次跳跃后 400ms 内不再判定,防止连跳。
  3. 基线校准:游戏开始时先采集 30 帧静默画面,作为”没人动”的基准,适应不同房间的光线。

四、实现步骤

1. 拿到视频流

const stream = await navigator.mediaDevices.getUserMedia({
  video: { width: 640, height: 480, facingMode: 'user' },
  audio: false,
});
video.srcObject = stream;

注意两点:必须是 HTTPS 或 localhost,否则浏览器直接拒绝;手机端要限制分辨率,否则帧差计算会吃掉 CPU。

2. 降采样 + 灰度化

把 640×480 的画面缩到 160×120,逐像素取加权灰度。降采样这一步把计算量降到 1/16,是能跑满 60 帧的关键。

3. 分区判定

只统计画面上半部分(约 55% 高度)的运动能量:人要跳起来,头部和上半身必然进入这块区域。限定区域的好处是可以忽略地面的杂物移动和镜头边缘的干扰,比做全身姿态估计简单得多,也足够玩一个跳跃游戏。

4. 游戏循环

用 requestAnimationFrame 驱动固定的游戏状态机:障碍物生成 → 位移 → 碰撞检测 → 计分。渲染层是 Canvas 2D,不使用任何图片资源,障碍物和角色都是几何图形。

五、隐私与性能,两个容易被忽略的点

  • 隐私:video 元素只做内部预览,画面不经过任何网络请求。你可以在浏览器开发者工具的网络面板里确认——除了页面本身的资源,没有任何请求携带图像数据。
  • 性能:帧差在 160×120 下每帧不到 2 万次像素运算,普通轻薄本占用不到 5% CPU。真正吃性能的是 getUserMedia 的高分辨率解码,所以要主动限制 width/height。

六、局限与它的下一步

帧差法的短板很明显:它只知道”画面在动”,不知道”是身体的哪个部位在动”。所以:

  • 光线剧烈变化(开灯、有人走过镜头)会误触发;
  • 背景杂乱时,检测区域需要收窄;
  • 做不了精细动作(挥手、踢腿方向)识别。

如果要再进一步,方案是本地加载轻量姿态模型,取关键点(肩、髋、膝)的移动向量做动作分类。这属于下一个版本的事——先把”跳”做好,比一次做十个动作更靠谱。

七、这套东西还能用来做什么

同一套帧差逻辑可以直接改成:

  • 儿童体感运动打卡:记录每天蹦跳次数,替代”再看十分钟”的拉锯战
  • 久坐提醒:摄像头检测到你 45 分钟没站起来,弹窗让你去倒水
  • 展厅互动:走过屏幕触发动画,成本比红外感应器低得多

游戏页就在本站的极客实验室,直接打开就能玩,也可以按 F12 看实现。如果你想要带教学注释的完整源码,或者想把它改成公司展厅的互动装置,加我微信聊。