当前位置: 首页 > news >正文

osu-droid难度算法实现剖析:Aim、Speed与Reading技能模型深度解析

osu-droid难度算法实现剖析:Aim、Speed与Reading技能模型深度解析

【免费下载链接】osu-droid项目地址: https://gitcode.com/gh_mirrors/os/osu-droid

osu-droid 是开源社区广受欢迎的 osu! Android 移植版,其自研的难度算法堪称评价谱面难度与玩家水平的"大脑":通过 Aim、Speed、Reading 等技能模型,把一张包含数百个音符的谱面,压缩成一个直观的星数与对应的 pp 值。这篇难度算法深度解析将从源码视角,一步步拆解这套技能模型的计算流程与设计思想。

一、难度算法整体架构:一条从谱面到星数的流水线

osu-droid 的难度计算入口是DroidDifficultyCalculator,它遵循经典的 osu! 难度算法三阶段流程:

  1. 预处理:把谱面物件包装成DroidDifficultyHitObject,归一化距离、计算时间间隔与角度。
  2. 技能建模:创建多套"技能"并行打分,每套技能独立评估谱面的某一维度负担。
  3. 汇总换算:把技能得分加权组合成 base performance,再开立方得到最终星数(Star Rating)

其中技能创建逻辑非常直观(createSkills):默认创建DroidAim(带滑条与不带滑条两份)、DroidRhythmDroidTap;开启 Flashlight 模组时追加DroidFlashlightDroidReading则始终参与计算。最终星数公式为:

starRating = cbrt(basePerformance * FINAL_MULTIPLIER)

其中basePerformance由 Aim、Tap、Cognition(Reading 与 Flashlight 的合成)通过范数(norm)加权得到。相关源码位于src/com/osudroid/difficulty/calculator/DroidDifficultyCalculator.kt

二、Aim技能模型:把"瞄准"拆成 Snap、Agility 与 Flow

Aim 技能(DroidAim)是整个难度算法中最复杂的模块,它继承自可感知滑条长度的VariableLengthStrainSkill,将"瞄准"拆成三个正交维度:

  • Snap(点按瞄准):评估相邻物件间的跳跃距离与角度,DroidSnapAimEvaluator会奖励锐角、广角与快速转向,并对重复角度做削弱处理。
  • Agility(敏捷):评估光标速度的突变率,衡量连续快速转向的负担。
  • Flow(顺滑):评估流线型连续滑动的难度,主要作用于串(stream)段落。

三个维度分别乘以 70.9、2.35、242 的权重后,再通过 logistic 函数计算"该音符更偏向 Snap 还是 Flow"的概率,加权求和得到当前物件的难度值。此外,Aim 还会记录每个滑条的速度(travelDistance / travelTime),用于统计"困难滑条"占比,这与结算面板上的滑条系数直接相关。

每个技能都有一套应变衰减模型,Aim 的衰减系数为0.2^(ms/1000),即 1 秒内难度记忆衰减到 20%;同时它会将前 4 秒内的最高应变按 20ms 分块削减,避免极端难度尖峰过度抬高整张谱面的星数。核心实现见src/com/osudroid/difficulty/skills/DroidAim.kt

三、Speed(Tap)技能模型:BPM、节奏与三指检测

Speed 技能在 osu-droid 中名为DroidTap,属于谐波求和类技能(HarmonicSkill),衡量玩家跟上击打速度的能力。其评估器DroidTapEvaluator的核心公式非常简洁:

strain = speedBonus * 1000 / strainTime
  • BPM 加成:当音符间隔对应的 BPM 超过 200 时(MIN_SPEED_BONUS = 200),通过误差函数逐步放大难度,200 BPM 以上每提速一点都极其"昂贵"。
  • 连点削权:利用doubletapness(连点程度)识别可以被"双指连打"糊过去的段落并降低其难度,这就是常说的反作弊(cheesability)设计。
  • 节奏调制:每个音符的 Tap 难度还会乘上DroidRhythm提供的节奏倍率,节奏越难(如变速、切分音)倍率越高。

值得一提的是,osu-droid 还内置了三指速段检测:当 Tap 应变连续超过阈值 175 且物件数不少于 5 个时,会标记为"可能三指速打"的段落(possibleThreeFingeredSections),这一信息会进入 pp 计算用于识别移动端特有的作弊手段。相关实现见src/com/osudroid/difficulty/skills/DroidTap.ktDroidTapEvaluator.kt

四、Reading技能模型:信息密度与 AR 的阅读负担

Reading 技能(DroidReading)是 osu-droid 相对原版 osu! 的特色模块,专门衡量"读图"难度,其评估器DroidReadingEvaluator在 3000ms 的"阅读窗口"内综合四类负担:

  • 音符密度:统计当前物件出现时与需要点击时可见的物件数量,密度越高越难读。
  • AR 预判:以 AR 9.66(500ms preempt)为起点,approach rate 越高、反应时间越短,preempt 难度呈 2.5 次方增长。
  • Hidden 加成:开启 Hidden 模组时按 0.28 系数放大阅读难度,并额外奖励"完美堆叠"(前一个音符点击时当前音符完全不可见)的段落。
  • 恒定角度削弱:检测相似角度的反复出现,连续同角度的物件会显著降低阅读难度(熟能生巧)。

此外,Reading 还模拟了人类"前几秒背谱"的行为:谱面前 60 秒内的音符难度会被按对数曲线削减(applyDifficultyTransformation),这与我们"第一遍打谱难、越打越简单"的直觉完全吻合。核心实现见src/com/osudroid/difficulty/evaluators/DroidReadingEvaluator.kt

五、汇总换算:技能值如何变成星数与 PP

当各技能完成打分后,DroidDifficultyAttributes会收集 Aim、Tap、Rhythm、Flashlight、Reading 五类难度值,以及"困难应变数""困难滑条数""可能三指段"等辅助统计量。随后:

  1. 难度 → 性能HarmonicSkill.difficultyToPerformance采用4 × difficulty³的换算(StrainSkill 类也有对应的换算函数),把技能值映射为性能值。
  2. 性能 → 认知合成:Reading 与 Flashlight 先合成cognition(光源对读图的影响按比例压缩)。
  3. 最终星数:Aim、Tap、Cognition 三者通过 norm 组合后再开立方,得到与玩家直觉高度一致的星数;这个星数连同难度属性一起喂给DroidPerformanceCalculator,最终算出 pp。

整套换算链条都封装在src/com/osudroid/difficulty/attributes/src/com/osudroid/difficulty/calculator/目录下,属性类与计算器分离的设计让二次开发十分清爽。

六、如何自行调试与二次开发这套难度算法

如果你也想动手研究这套难度算法,可以在本地克隆仓库后直接阅读与修改:

git clone https://gitcode.com/gh_mirrors/os/osu-droid

推荐三个探索入口:

  • 实时调试src/com/osudroid/debug/DebugPlaygroundScene.kt提供了难度计算的调试场景,可直观看到各类技能值的变化。
  • 批处理入口src/com/osudroid/beatmaps/DifficultyCalculationManager.kt负责对谱面库批量计算难度。
  • 单元测试tests/test/kotlin/com/osudroid/下保留了 83 个测试文件,覆盖了技能评估器与换算公式的边界情况,修改算法后跑一遍测试即可验证效果。

对于想给 osu-droid 贡献新模组难度加成、或复刻这套移动端难度算法的开发者来说,从 Aim 的 Snap/Flow 概率模型与 Reading 的密度窗口这两个最有"移动端特色"的部分入手,是最快理解整套设计精髓的路径。

结语

通过这次对 osu-droid 难度算法的剖析可以看到,它并非简单照搬桌面版 osu!,而是在 Aim 中引入 Snap/Agility/Flow 三维拆分、在 Speed 中加入三指检测、在 Reading 中构建信息密度窗口,处处体现着对"手指触屏操作"这一场景的针对性建模。理解这套技能模型,不仅能帮你读懂星数与 pp 背后的逻辑,更能为移动端音游的难度设计提供一份高质量的参考样本。

【免费下载链接】osu-droid项目地址: https://gitcode.com/gh_mirrors/os/osu-droid

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

http://www.cnnetsun.cn/news/4084840.html

相关文章:

  • 世毫九信息几何物理学框架下黎曼ζ函数非平凡零点的拓扑不动点本质
  • assert_instr测试机制深度解析:stdarch如何确保内建函数与机器指令一一对应
  • SideWaffle vs 其他VS模板扩展:为什么它是Web开发者的终极选择?
  • DDrawCompat 上手全攻略:让老 DirectX 游戏在现代 Windows 上重获新生
  • GitHub 成就解锁新手指南:零代码审查也能拿到的 Yolo 徽章
  • RTOS延时机制解析:从osDelay到阻塞延时的本质区别与应用
  • lainTSX 收集要素攻略:集齐 Polytan 熊全部 6 个部件的完整路线
  • 告别手忙脚乱:FF14钓鱼计时器“渔人的直感“咬钩识别与幻海流预警实战手册
  • 3步上手免登录微博图片批量下载:weiboPicDownloader从入门到进阶完整指南
  • OBS的NDI插件一装就报Runtime错误?DistroAV安装与排障一篇讲透
  • 炉石传说插件 HsMod 全攻略:8 大实用增强功能与最快上手方法
  • 单片机毕设选题推荐:基于 STM32/51 单片机的三轴姿态感知人体安全监测预警系统设计 基于 STM32/51 单片机的老年人远程跌倒短信报警硬件系统设计(021203)
  • 内联汇编与Naked函数:B语言编译器bext-lang/b的底层控制进阶教程
  • 数据采集卡从入门到精通(26):热电偶温度采集——塞贝克效应、冷端补偿与线性化
  • BMC PSL function(81)-get(“./hostname“)
  • Mac Mouse Fix 实测手记:普通鼠标在 Mac 上如何一步步变顺手
  • 炉石传说插件 HsMod 上手指南:55 项增强功能,从一键变速到自动开包讲透
  • 有访问量却无有效询盘?厦门杰赢网络拆解外贸独立站的转化流失根源
  • Mini-DSO 采样原理深度解析:STC8 单片机 ADC 如何实现 250kHz 高速采样
  • 多图一次看懂:North Micro Vision Instruct 多图像理解完整指南
  • 计算机毕业设计之基于Python的霍兰德职业倾向测试可视化系统
  • 计算机毕业设计之个性化推荐电商平台的设计与实现
  • 计算机毕业设计之基于Python的二手交易信息数据分析系统的设计与实现
  • 五秒把B站缓存视频转成MP4:m4s-converter 免费开源工具实测手记
  • uni-app云打包显示编译成功,但是一直没有进入打包队列,后面也一直没反应
  • auto-value-parcel处理@Nullable属性完全指南:null安全序列化的正确姿势
  • 在MCN做后期3年,我们团队12个剪辑师电脑里都装了同一款AI配音
  • COPE: Chain-Of-Thought Prediction Engine for Open-Source Large Language Model Based Stroke Outcom...
  • 重复受害视角下 Web3 恶意授权钓鱼攻击风险研究
  • BACnet/IP 报文视角下对象模型与事件服务安全研究