最近我把一个“专注力反应检测小游戏”完整做出来了也已经整理好材料准备投稿到豆包专属赛道。这个项目听起来不算大但真正动手后才发现它比普通的休闲小游戏要复杂得多——既要保证测量指标有心理学依据又要让玩家玩起来不觉得无聊还得在浏览器端稳定跑出毫秒级的时间精度。这篇文章我把整个项目从想法到落地、从机制设计到投稿复盘都拆开讲希望能给正在做类似轻量级工具型小游戏的朋友一些可参考的经验。我当时拿到的原始需求其实只有一句话做一个能测专注力和反应速度的小游戏。但“能测”两个字背后包含的东西非常多。你是测多快能点中目标还是测长时间保持注意力的稳定程度又或者是测在干扰环境下能不能正确判断这三种对应完全不同的玩法和算法。我最终选择了三个子任务来覆盖分别对应反应速度、注意稳定性和注意分配能力。为什么这么选下面会详细说。1. 项目背景与整体设计思路1.1 为什么选择“专注力反应检测”这个小众方向市面上反应类小游戏并不少但大部分只追求一个“快”字点得越快分数越高然后就没有然后了。专注力检测则不太一样它更关注玩家在持续任务中出现的错误率、波动趋势和异常反应而不只是平均反应时间。这种工具型定位有个天然优势可以给人一个相对可信的自我评估结果而不是游戏里一个无意义的排行榜分数。我考虑过做体感类的专注度检测比如通过摄像头追踪头部姿态、瞳孔变化但这需要引入比较重的算法库而且隐私和授权问题会让发布门槛变高。最终我决定走纯交互行为的路线用光标、触摸和按键事件来推断专注状态。这样既避免了复杂的环境依赖也能在浏览器里直接运行降低投稿和后续分发的门槛。另外提到“豆包专属赛道”我理解评审方更看重的是创意表达、完成度和可玩性的融合而不是堆砌复杂图形或酷炫特效。所以我在美术上选择了低饱和度的简洁风格让视觉焦点停留在任务本身避免干扰测试结果。1.2 核心需求拆解测什么、怎么测、怎么呈现我拆解出的核心需求是三个。第一玩家要能快速理解规则不需要教程难点在于用直觉化交互传达任务。第二系统要能记录每一个关键事件的时间戳、按键类型和正确性难点在于前端事件循环的不确定性。第三在游戏结束后要能生成一个普通人能看懂的专注力报告难点在于把统计学指标翻译成友好表述。这三个需求决定了项目的技术架构。我不会在一开始就追求复杂的服务端而是把全部计算放到本地。反应时间的记录使用performance.now()获取高精度时间戳游戏状态机则用时间戳差值来判断“是否超时”或“是否过早响应”。前端只需保存每次会话的结构化数据并用简单的评分模型输出结果。下面是需求-功能对照表我在项目计划时一直用它检查遗漏。需求对应功能模块关键参数快速上手引导动画 模拟任务10秒内可完成学习反应速度检测目标出现-点击响应记录刺激到响应的毫秒数注意稳定性持续追踪 随机干扰漂移误差、漏失率注意分配双任务并行切换代价与正确率报告生成本地评分模型标准分与语义描述1.3 方案选型原生JavaScript还是前端框架考虑投稿项目需要轻量、易评审、无特殊依赖我一开始就排除了重量级框架。如果只是为了几个游戏界面引入完整框架会带来不必要的负担。所以我选用了原生 JavaScript HTML5 Canvas配合 Web Worker 来做后台计时逻辑。Web Worker 在这里不是必需品但我还是象征性地用了一个 Worker 来避免主线程上的定时器被密集渲染阻塞这样能减少长时间的计时漂移。可能有人会问用setInterval或者requestAnimationFrame就够了为什么要搞 Worker其实是因为浏览器在多标签页后台时会节流setTimeout。而专注力任务一旦切后台继续跑就会拿到错误数据。我在 Web Worker 里维护一个相对独立的时钟主线程只负责发送信号和收集响应这样即便标签页进入后台计时逻辑也不会突然变慢。实测下来这个方案在处理“任务运行3分钟但玩家中途切走”的场景时数据可信度高了很多。2. 核心机制与检测指标详解2.1 反应时测试Go/No-Go任务的设计我做的第一个子任务叫 Go/No-Go 反应测试它和传统“看见就点”的简单反应时不同会随机出现两种目标绿色圆圈是需要点击的“Go 信号”红色圆圈是需要忍住不点的“No-Go 信号”。这个设计的心理学依据来自持续性操作测试它能同时测量速度与抑制控制能力。规则看起来简单但需要控制的参数很讲究。目标出现的时间间隔设置为 1500 到 3500ms 之间随机避免玩家形成节奏感。目标在屏幕上停留的最长时间设置为 1000ms超过这个时间没有响应就记为漏失。若在 No-Go 信号出现的 500ms 内点击了则记一次虚报。实际调试时我发现间隔太短会导致玩家紧张疲劳太长又会让人觉得无聊最终我选择了上述范围并在每轮 60 次试次中加入 18 个 No-Go 信号比例大约是30%。整个过程的反应时数据需要清洗。低于 150ms 的点击通常属于预判或误触我在记录后会标记为“过早响应”不参与最终平均值的计算。高于 1000ms 的点击因为目标已经消失也不会进入正常反应时统计。这些处理我都会在说明文档里标注出来而不是让玩家看到一个莫名其妙的数值。2.2 注意力稳定性测试持续视觉追踪与随机干扰第二个子任务是比较新颖的漂移追踪任务。屏幕上会有一个小球按照非常缓慢的随机路径移动玩家需要把鼠标指针保持在小球中心附近。注意这里不要求点击只需要持续悬停跟随。系统会记录每一帧里鼠标位置与目标中心的距离偏差。这个任务能直接反映长时间注意维持能力尤其适合检测注意力涣散。实现原理上我用 Canvas 在每帧绘制背景和目标同时保存目标的位置序列。随机路径不是纯随机乱跑而是叠加了多组低频正弦波这样运动轨迹平滑可控又不会显得过于机械。玩家指针与目标中心的距离会每 100ms 采样一次计算平均偏移和偏移方差。如果玩家在游戏中途习惯性放下鼠标偏移会瞬间变大并被标注为“看护中断事件”。为了模拟真实场景下的干扰我在屏幕四周偶尔弹出无关的图形和数字它们不要求响应只用于检验玩家是否会因为干扰而移动注意力。这种做法在测评类小游戏里不算常见但效果很好。测试完几个朋友后我收到的反馈是这个小球一卡顿就特别容易上手疲劳而这种疲劳本身就能反映真实注意力波动。2.3 注意分配测试双任务并行操作第三个子任务做的是双任务并行你一方面需要用鼠标点击在随机位置闪现的目标另一方面要监控屏幕角落的数字序列当数字出现某个特征时按空格键。这考察的是注意分配也就是大脑能不能同时处理两个通道的信息。这里最头疼的是交互冲突。如果两个任务都要求鼠标点击玩家会忙不过来所以我规定第一个任务用鼠标第二个任务用键盘。数字序列每隔 2 秒变化一次目标只会在某个固定时间窗内出现玩家需要自己分配时间片。在做界面时我画了一条明显的分割线把视觉区域划分为“点击区”和“监测区”帮助玩家形成任务图式减少学习成本。双任务的评分并不是简单相加而是看“协同损耗”。我会对比玩家在单任务中的表现基线然后计算双任务正确率相对基线的下降比例。如果下降比例超过 20%就认为注意分配能力偏弱。这个算法在心理学上叫双任务成本不过我在项目说明里用更直白的语言表达成“一心二用效率”。2.4 专注力评分怎么算从原始记录到友好报告收集到原始数据后评分逻辑是关键。我不会直接把反应时拿来比大小因为不同人群的基线差异很大。我的做法是把反应时、漏失率、虚报率、偏移方差、双任务成本五个指标分别映射到 0 到 100 的百分制分数再根据权重合成总专注力指数。权重分配为反应速度 25%、正确率 30%、稳定性 25%、双任务表现 20%。实际开发时我首先用几轮自测数据做了归一化测算。比如平均反应时 260ms 对应 80 分350ms 对应 60 分500ms 对应 40 分这个近似线性关系在 30 人的样本里有比较好的区分度。漏失率和虚报率则使用惩罚式计分如果漏失率超过 10%每多 1% 扣 2 分虚报率超过 5% 每多 1% 扣 3 分。偏移方差我用了相对基线比例而不是绝对像素值这样能缩放不同屏幕尺寸的影响。报告页里我并没有直接展示这些算法细节而是用雷达图展示五个维度的相对强弱再配合一句人话结论。比如“你的注意稳定性非常优秀但反应速度还有提升空间”。这种表达能避免测评带来的挫败感也更贴近普通人的理解习惯。3. 实操过程从零搭建完整实现3.1 页面结构与视觉设计整个项目只包含三个主要页面主页、游戏页、报告页。主页展示三个任务的入口和相关说明游戏页通过顶部步骤条切换三个子任务报告页则在完成最后一关后展示结果。因为不依赖外部资源我没有用图片文件所有图形都用 Canvas 和 CSS 绘制这样打包后体积非常小也很方便直接嵌入到投稿页面里。视觉方面我是刻意做了“减法”。背景用浅灰蓝#F0F3F7主交互元素用绿色系警示元素用红色系。字体选择系统默认字体栈避免加载自定义字体。为什么不用更鲜艳的颜色因为我发现高饱和度背景会让玩家分心弹出的方块如果太显眼会抢掉主任务视觉权重从而改变检测结果。页面顶部我放了进度提示条比如“任务 1/3 已完成”。这个提示条不仅仅是 UI 装饰它本身也算一个注意力锚点玩家能看到自己还能坚持多久就不会因为未知的时长而焦虑。实际测试中有提示条时玩家中途退出率下降了差不多 12%。3.2 游戏逻辑实现与计时精度控制游戏逻辑我用了简单的状态机READY → WAITING → RESPONDED → FEEDBACK每个任务独立维护当前状态。关键点在于不要在主循环里频繁读取Date.now()而是用performance.now()获取页面加载以来经过的高精度毫秒。每次新建目标时记录时间戳按键事件回调里再次记录时间戳两者相减就是反应时间。这里有个被很多人忽略的细节事件回调虽然记录的是触发时间但如果你在渲染线程里有很重的计算回调可能会被延迟执行。解决办法是使用event.timeStamp它表示事件创建时的时间而不是处理时的时间。我改用了event.timeStamp后偶尔出现的 5ms 级偏差基本消除。不过event.timeStamp在不同浏览器里可能相对于不同零点因此我会在游戏开始时记一个基准值再用差值计算。代码片段示意如下const startTime performance.now(); let lastEventBaseline 0; document.addEventListener(pointerdown, (e) { // 记录事件自身的时间戳避免回调排队导致延迟 const eventTime e.timeStamp; const delta eventTime - lastEventBaseline; // delta 就是相对于游戏开始的事件时间偏移 });这个写法的本质是不要再另外调用性能函数直接信任事件系统的时间戳。配合 Web Worker 里的定时信号整体精度可以做到 5ms 以内。对这类认知实验游戏来说已经足够。3.3 数据持久化与本地存储每次完整测试会产生一组数据包含三个任务的原始事件列表。我把它们压缩成一串 JSON 存入localStorage键名设计成按日期区分的格式例如focusgame_session_20250401_1530。同时最近十次会话会被展示在报告页的历史记录区方便玩家观察自己注意力的日常波动。存储时要注意性能问题。如果追踪任务每 100ms 采样一次三分钟就是 1800 条记录直接存储会有点占空间。我在写入前做了降采样普通采样保留每 100ms 的点但如果偏移连续五次都小于某个阈值就只保留每 300ms 一个点。这样既保留了趋势又减少约一半的数据量。做完这个优化后localStorage 单次占用从 200KB 缩减到了 80KB 以内对移动端也更友好。3.4 兼容性与性能调优这个项目的兼容性重点是移动端触摸和桌面端鼠标的差异。桌面端可以用pointermove和pointerdown移动端却容易出现多点触控干扰玩家手指放上去后可能会误触发其他元素。我在全局捕获阶段调用了e.preventDefault()阻止默认滚动行为但对输入框等组件做白名单避免影响正常使用。另外我还监听touchstart做了一次坐标转换因为触摸的坐标和鼠标事件提供的 offsetX 在不同设备上会不一致。性能上Canvas 绘制任务的小球和目标不该直接每帧调用clearRect后重绘那会导致移动端发热。我采用了两层 Canvas底层画静态背景只绘制一次上层只绘制动态元素。这样重绘量大幅下降实测在低端安卓机上也能稳定 60fps。这个优化对专注力测试很重要因为卡顿本身会破坏玩家的沉浸状态让数据失真。4. 投稿豆包专属赛道过程与复盘4.1 投稿前的准备打磨交互说明和文档项目做出来后摆在面前的一个现实问题是投稿到豆包专属赛道评审不一定有耐心把整个游戏玩完。所以我必须准备一份让人一眼就能看懂项目价值的说明。我把文档分成三个版本完整版给技术评审看包含机制说明和算法伪代码演示版给产品评审看重点展示三个任务玩起来的样子一句话版用于封面标题例如“用三分钟了解你的专注力剖面”。在打磨游戏内的引导动画时我花了很多时间。原来我打算用文字弹出描述规则后来发现大多数人看着看着就直接点“开始”根本没读完。最后我把规则变成一个 5 秒的交互教学关玩家必须按照提示完成一次点击后再进入正式任务如果操作错误就一直提示“请等绿色圆点出现再点击”。这个嵌入式教程的转化率明显好多了也减少了低级误操作对数据的污染。4.2 评审视角他们可能看重什么参与这类赛道我理解评审看的不是单纯技术难度而是“创意落地能力”。一个专注力检测游戏最容易让评审眼前一亮的地方是你是否有独特的检测维度。如果只是一个“看谁点得快”的游戏吸引力平平。但我加入了漂移追踪、双任务成本、抑制控制这些相对专业的认知维指标并最终用雷达图呈现这就和市面上常见的反应游戏拉开了距离。另外作品的完整度也很重要。很多提交者只到“能玩”就停了没有数据报告、没有历史记录、没有移动端适配。我把游戏、数据统计、本地存储、结果解读一起打包形成一个小闭环产品。这种完成度往往比单一玩法的新颖度更能打动评审。展示视频是我录制的一条 90 秒实机演示。我并没有用剪辑软件搞花哨特效而是直接录制屏幕配了少量文字说明重点展示任务流程和报告页的雷达图。我会在视频里明确说出一句核心表达“这不是一个考验手速的普通游戏而是一个使用认知任务来评估专注力的工具。”这种叙事闭环对非专业评审比较友好。4.3 投稿材料的高效组织我使用 Markdown 整理了一页项目说明内容包括项目背景、玩法截图、关键算法、性能数据、未来迭代方向。截图我统一用固定尺寸的浏览器窗口截了三张主流程图并在截图里用箭头标注了核心交互点。为什么不放大量代码因为评委大概率不关心你具体用了哪个 API更关心你解决问题时的思路。特别注意投稿文件命名我用“项目名_开发者代号_版本号”的格式避免出现乱七八糟的空格或日期残缺。有一次我差点把版本号写成“v2.0_最终版”后来还是改成了“v1.2”。另外投稿到平台前要先去读清楚平台对素材大小、格式、违禁内容的要求不要等到上传失败再紧急压缩。我自己的压缩策略是视频转成 MP4 并限制 1080P截图全部用 PNG确保细节不被压缩变色。5. 常见问题与排查技巧实录5.1 计时偏差为什么自己测试是准的别人玩就偏慢这个问题我踩过坑。我发现某些测试者反应时常特别低起初以为是他们手速慢后来检查代码发现问题出在他们使用了全局缩放浏览器页面。当页面被缩放到 90% 时鼠标坐标会按缩放比换算但事件时间戳不受影响。理论上这不影响时间可当画面比例变化时视觉目标的大小和位置都会移动导致玩家认为目标还没出现或已经消失从而产生额外等待。解决方法是锁定 Canvas 的逻辑尺寸不跟随浏览器缩放并使用 CSStransform来适配容器。另外Windows 笔记本触控板默认启用了“单击锁定”玩家在拖动鼠标后下一次点击可能被触控板判断成双击的一部分反应时被附加了几十毫秒。这个没法完全从代码端避免我会在任务开始时让玩家按一次空格输入设备没有额外延迟后再继续相当于一个简易自检。5.2 移动端触摸事件干扰移动端最开始的表现很糟糕。玩家点击屏幕时会触发touchstart、touchend和合成鼠标事件如果我把pointerdown和touchstart同时绑定一次点击可能被算两次。后来我把所有点击监听统一换成pointerdown然后在移动端上禁用touchend里的额外逻辑只保留一个入口。更隐蔽的问题是页面滚动。有些浏览器会在触摸长按时弹出文本选择器或手势菜单我通过给整个页面加touch-action: none以及设置user-select: none解决了。注意如果你做的是输入框之类的交互需要单独开启选择权限不能全局一刀切。5.3 沉浸感不足和数据波动试玩反馈中有人觉得任务太枯燥玩到一半就想退出。这其实是测评类工具的通病。我不能为了趣味性加太多强反馈比如爆炸特效或音效因为反馈本身会变成一种外部奖励机制干扰后续测量的纯粹性。我给折中方案在任务结束后提供一次完整的视觉效果回馈比如雷达图弹出动画、历史分数比较柱状图但在任务进行中只保留极其克制的微弱光标提示。数据波动大通常不是算法问题而是玩家没有进入状态。有的测试者第一次玩时会过度追求完美反而反应变慢。我为此在正式测试前加了一次低难度练习任务不计入分数让玩家熟悉流程。练习之后的数据波动明显下降标准差大约缩小了 18%。5.4 评分模型失真情况有一次我朋友测试完他明明反应很快但总专注力分数并不高。后来看数据才发现他在 No-Go 任务中虚报率特别高看到红色方块也忍不住点击。这说明他的冲动抑制能力偏弱虽然速度快但错误率高。评分模型此时给出的“控制力不足”是合理的。可另一个朋友则相反他在限定时间内没有漏掉目标但反应时偏慢分数反而中等。经过对比我发现年龄和设备差异对反应时有很大影响。于是我在评分模型中加入了一个动态基线调整先用前五个响应作为用户个人初测基线后续指标都和这个基线对比。这避免了跨年龄段直接对比的偏差。加入这个调整后报告页结论对个人更有参考价值而不是让人拿来和全世界比排名。6. 项目未来的迭代方向我已经把第一版玩法和数据闭环做完了但有几个方面后续还值得继续打磨。第一是增加多会话趋势分析不只显示历史记录还用折线图展示连续 30 天专注力变化曲线让用户能在时间维度上看到进步或退步。第二是加入语音提示的可选开关用语音同步播报每个任务的开始和结束不用让玩家一直盯着页面。第三是考虑把结果导出为 CSV 或 PDF方便有科研需求的用户进一步分析。现在技术圈里关注脑科学与认知训练的人越来越多这类轻量级工具其实有比较广泛的应用空间。比如学校可以拿来做注意力训练的课后小工具自我提升类社群也可以用它来组织每日打卡。不过做测评工具最需要把握的边界在于不能声称自己能诊断注意缺陷相关疾病。我在项目说明里也特意加了一句“本工具仅用于娱乐和自我参考不构成任何医疗诊断依据”这句话比在功能上堆料更重要。最后分享一个我在实际开发中的体会。做这种小游戏最容易翻车的往往不是复杂算法而是那些看起来不起眼的细节事件时间戳用错了、触摸多触了一次、屏幕缩放导致目标位置偏移。你花在数据准确性上的心思最后都会体现在报告的可信度上。如果你也在做类似的项目我建议先把“最核心的一次反应事件”做得毫秒级可靠再去考虑增加花哨功能。底层的数据采集可信了上面的分析才有意义。