回到首页

心流与动态难度

让游戏自己判断玩家是焦虑、投入还是无聊,再去调难度,让人多待在心流里。做了一个浏览器里能玩的 demo。

TYPE
游戏里的自适应难度,业余项目
STATUS
demo 能玩,没做过玩家测试
DEMO
vampire-survivors-ai-dda.vercel.app(放在 Vercel 上,国内直连打不开,要走代理)
WHEN
2025 至今。这一页写的是 2026 年 1 月的版本,在线 demo 是 5 月的版本
BUILT WITH
TypeScript、React、Canvas,控制器是手写的,没用现成的库
WHO
和一位合作者一起做的

这是什么

一个类似 Vampire Survivors 的小游戏,在浏览器里跑。玩家只管移动,武器自动开火,杀敌掉经验、金币和回血,一局 15 分钟。

特别的地方在后台。常见的做法是按时间表加难度,过一分钟敌人多一成。这一版不这么做,后台有一个控制器,大约每秒看一次战况,估计玩家现在是焦虑、心流还是无聊,然后决定要不要多放点敌人、多掉点回血。

控制回路控制器玩家移动,选升级战况血量、敌人位置、击杀三个信号,各自分档血量 5 档 · 包围 4 档 · 连杀 5 档信念焦虑、心流、无聊,三个概率给 7 个动作打分,抽一个预期的观测离想看到的有多远三个旋钮刷怪间隔 · 回血掉落 · 掉落物寿命刷怪和掉落每 60 次更新走一圈,大约一秒

FIG. 1 · 控制回路

虚线框里是控制器。它只读战况,只动三个参数。

它看什么

控制器只看三样东西,都是游戏里现成的数。

没有摄像头,没有心率,也不问玩家。所以“焦虑、心流、无聊”只是模型里三个状态的名字,它们和玩家真实的感受对不对得上,没有验证过。

怎么从信号读出状态

控制器里有三张表(图 2),写的是“如果玩家正处在某个状态,看到某一档信号的可能性有多大”。比如玩家焦虑的时候,血量危急的可能性是 0.6,心流的时候只有 0.05。这些数是手填的假设,没有拿玩家数据统计过。

三个信号在三种状态下各有多大可能血量当前血量 / 上限焦虑心流无聊危急<20%.60.05低20–40%.30.15中40–60%.10.60.10偏高60–80%.20.30高≥80%.60包围8 个方向里几个有敌人焦虑心流无聊围死7–8.70.10有缺口5–6.30.70.10松散3–4.20.40空旷0–2.50连杀上次挨打之后杀了几个焦虑心流无聊0–2.50.403–5.30.10.106–10.10.30.1011–15.10.40.10≥16.20.30控制器最想看到的那一档≤.10≤.20≤.35≤.55>.55

FIG. 2 · 三张表

每一格是“处在这一列的状态时,看到这一行的信号”的概率,每一列加起来是 1,颜色越深概率越大。数字照抄自代码。

每一圈,控制器把上一圈的估计往前推一步,乘上这三张表里对应的数,再归一化,得到三个加起来等于 1 的概率。开局的估计是焦虑 0.1、心流 0.8、无聊 0.1。

图 3 是按这些表算出来的六个例子,从开局的估计出发,只看一次观测。它是算出来的,没有对局记录在里面。

六种战况各被读成什么焦虑心流无聊血量危急,被围死,连杀 0–21.00 / 0.00 / 0.00血量低,被围死,连杀 6–100.37 / 0.63 / 0.00血量低,有缺口,连杀 3–50.24 / 0.76 / 0.00血量中,有缺口,连杀 11–150.00 / 1.00 / 0.00血量偏高,松散,连杀 16 以上0.00 / 0.64 / 0.36血量高,四周空旷,连杀 0–20.00 / 0.00 / 1.00

FIG. 3 · 六种战况各被读成什么

右边三个数依次是焦虑、心流、无聊的概率。

怎么调

控制器手里有七个动作,三个参数各往上或往下调一格,再加一个“不动”(图 4)。它不直接改敌人的血量、速度和伤害。

选哪个动作,用的是 active inference(主动推断)里的预期自由能。大意是,对每个动作,先预测做了之后会看到什么样的战况,再算两样东西,一是预测的战况离“想看到的战况”有多远,二是预测本身有多含糊。两样加起来越小,这个动作被选中的概率越大。最后按概率抽一个,不直接取最好的。

“想看到的战况”也是写死的,血量在中间那一档,被围着但有缺口,连杀在 11 以上(图 2 里带三角的那几行)。

控制器能动的三个参数刷怪间隔隔多少次更新出一个敌人5100起始 60← 动作 0:减 5,敌人更密动作 1:加 5 →回血掉落击杀后掉回血的概率0.010.80起始 0.05← 动作 3:减 0.05动作 2:加 0.05 →掉落物寿命掉在地上的东西留多久10 秒60 秒起始 30 秒← 动作 5:减 5 秒动作 4:加 5 秒 →动作 6:这一圈什么都不改。

FIG. 4 · 三个参数,七个动作

横线是参数能取的范围,黑块是开局的值,每一小格是一个动作调的幅度。时间按每秒 60 次更新折算。

做到哪了

下面说的是 2026 年 1 月那一版。在线 demo 是 5 月的版本,控制器后来改过,这一页还没跟上。

另一个版本

还有一版是文字互动叙事,机制不一样,按回合走,每一轮决定加不加挑战、把文字停在哪儿把选择交还给玩家。这一版的材料我还没整理,先不展开。