返回
玩法拆解 · 代码 · Demo
行进 / 跑酷躲避

Stream Runner:把难度写进速度曲线,把界面砍到只剩两个按钮

极简自动跑酷案例拆解:分数=距离、一种障碍对应一个按钮的二分映射,以及 0.6 秒躲避窗口如何保证高速下的可读性。

0

玩法拆解

规则骨架
  • 自动前进:基础速度 10 单位/秒,每秒 +0.5 线性爬升
  • 地面障碍点 SLIDE、低空障碍点 JUMP,躲避窗口 0.6 秒
  • 分数=距离(1 单位 1 分,结算取整),3 条命撞完出局
  • 结算时与历史最高分比较更新,Play Again 直接重开
行为循环
  • menu 点 Start Game → 数据清零 → core/runner.start
  • 自动滚动中读障碍类型 → 按对应按钮 → 躲过或扣 1 命
  • runner.finish → 写回得分/距离 → result 展示得分与最高分
  • 实测一局约 6 秒、60 多分,十秒一回合的超短循环
实现要点
  • core/runner 承载全部玩法:start/jump/slide/setSpeed/reset 五个 action + runner.crash/finish 事件
  • 障碍间隔 2 秒起步、每秒再缩 0.05、下限 0.8 秒,与速度曲线叠加成压力曲线
  • 参数全部走数据键(runnerSpeed/obstacleInterval/jumpDuration 等),调参不改代码
  • 已知限制:皮肤文本 {{key}} 占位当前按字面量渲染,HUD 数字不跳动

关键代码

速度曲线与障碍调度(core/runner)
js· 16 行
玩法行为:本文属于「行进 / 跑酷」母型持续前进中处理路径、障碍与节奏;核心是可读性与选择成本。
查看母型详解

Demo

点 Start Game 开跑:地面障碍点 SLIDE、低空障碍点 JUMP,三条命撞完结算,跑多远就得多少分。

Stream Runner:把难度写进速度曲线,把界面砍到只剩两个按钮 Demo
游戏加载中…

文章

Stream Runner:把难度写进速度曲线,把界面砍到只剩两个按钮

一句话本质

Stream Runner 是一款极简自动跑酷:角色自动向前滚动,玩家只有 JUMP / SLIDE 两个操作来躲避随机出现的低空与地面障碍,跑多远就得多少分,撞满三次出局。它的难度完全由一条线性速度曲线驱动,可读性靠"一种障碍对应一个按钮"的二分映射保证。

行为循环

  1. 开始:菜单点 Start Game,分数与状态清零,core/runner 模块 start。
  2. 自动前进:速度从 10 单位/秒起步,每秒 +0.5 线性递增;分数与距离同步累计(1 单位 = 1 分)。
  3. 读障碍:障碍随机生成,地面与低空两种类型各占 50%。
  4. 做反应:地面障碍点 SLIDE,低空障碍点 JUMP;动作开启 0.6 秒的对应躲避窗口。
  5. 承担后果:窗口内没躲过就扣 1 条命(共 3 条),并广播 runner.crash 事件。
  6. 结算:三条命撞完进入 result,展示本局得分并与历史最高分比较更新;点 Play Again 直接再来一局。

实测一局(不做任何操作)约 6 秒、得分 65 上下——典型的"十秒一回合"超短循环。文末 demo 可直接试玩验证。

原语标注

  • AutoMove(speed(t)) – 持续前进,速度随时间线性爬升
  • SpawnObstacle(interval(t)) – 按递减间隔生成障碍
  • Jump(window) / Slide(window) – 开启 0.6 秒对应类型的躲避窗口
  • Crash(type, lives) – 未躲避成功,扣生命并广播事件
  • Finish(reason) – 生命耗尽(或达到时长上限)触发结算
  • UpdateHighScore() – 结算时比较并写回最高分

参数速查表

| 参数 | 说明 | 实际生效值 | 单位 | |------|------|-----------|------| | runnerSpeed | 基础速度 | 10 | 单位/秒 | | 速度爬升 | 每秒加速度 | +0.5 | 单位/秒² | | obstacleInterval | 障碍初始间隔 | 2 | 秒 | | 间隔收缩 | 每秒缩短 | 0.05 | 秒 | | 间隔下限 | 最小生成间隔 | 0.8 | 秒 | | jumpDuration / slideDuration | 躲避窗口 | 0.6 | 秒 | | runnerLives | 生命数 | 3 | 条 | | gameDuration | 时长上限(兜底,实际很难活到) | 60 | 秒 |

设计取舍

  1. 砍掉收集经济:原作是 Three.js 3D 溪流滚球,设有水滴(+10)与星星(+50)双档收集品;重建版全部砍掉,只留躲避。收益是分数=距离、不用解释,速度曲线成为唯一难度旋钮——调一个数就调了全局难度。
  2. 二分决策映射:地面→SLIDE、低空→JUMP,一种障碍对应唯一按钮,按钮文字就是动作名。零教学成本,且失败归因清晰——撞了就是按错或没按,玩家认账。
  3. 窗口 0.6s < 间隔下限 0.8s:即使在速度极限、障碍最密时,每次也只需处理一个障碍,不会出现"无解弹幕"。这是高速下可读性的硬保证。
  4. 双曲线叠加:速度线性爬升(+0.5/s)压缩反应时间预算,障碍间隔递减(-0.05/s,下限 0.8s)提高操作密度;两条曲线共同拧紧压力,但斜率都很缓,前几秒近似教学段。
  5. 三条命:前两次撞击是免费教学,第三次才结算——用失败宽容度制造"差一点点"的遗憾,驱动再来一局。

实现要点

  • 模块分工:common-ui 负责皮肤按钮的事件绑定与转发;core/runner 承载全部玩法逻辑(前进/生成/碰撞/计分),对外暴露 start / jump / slide / setSpeed / reset 五个 action 与 runner.crash、runner.finish 事件。
  • LogicGraph 编排:gameplay 状态 onEnter 清零数据并调用 runner.start;player.jump / player.slide 事件直接转发到模块 action;runner.finish 写回 score/distance、置 gameOver 并 emit game.over 迁移到 result。
  • 时间单位换算:v2-kernel 的 update 回调传入毫秒,模块内部统一除以 1000 转成秒后再积分速度与距离。
  • 参数全部数据键化:runnerSpeed / obstacleInterval / jumpDuration / slideDuration / gameDuration / runnerLives 均经 ctx.data 读取,运营调参不改代码。
  • 表现层:750×1334 竖屏画布,PIXI 渲染皮肤层;顶部 HUD 一行三个文本位(Score / Dist / Lives),底部两个 320×100 大按钮落在拇指区。
  • 当前构建的已知限制:皮肤文本的 {{key}} 占位符由渲染器按字面量输出,HUD 数字不跳动,数值绑定有待内核能力补齐;蓝图 dataGraph 中声明的初值(如 runnerSpeed=30)目前不会注入运行时,实际生效为模块兜底值(10)。

以上取舍让 Stream Runner 成为观察"速度曲线 + 可读性"设计的最小样本:机制少到一个表格能写完,但每条参数都直接参与手感。文末 demo 点 Start Game 即可开跑,看看三条命能跑出多少分。