Appearance
星数(Star rating)
⫻Under Construxion⫻
本部分仍在施工中……
osu!mania的难度算法像一个装满了虫子的罐头,让人连打开它看看的勇气都没有。
——摘自osu!官网论坛
其实事情也没有这么糟啦[1]。现在我们就打开看看里面到底都有啥。
计算方式
note难度计算
计算谱面难度时会先计算每个note的难度。首先将所有note按开始时间从小到大排序。同一开始时间的note的相互顺序不会影响计算。
从第一个note开始,每个note具有以下值:
- IndividualStrain:按轨道区分的一系列值,代表每个轨道的难度;
- OverallStrain:单个值,代表总体的难度;
- HeldUntil(滑条结束时间):当前note开始时间时,其他轨道存在的上一个滑条的结束时间。
这些值会受到上一个note处的值(见下文)和当前note的情况影响。第一个note的IndividualStrain所有值均为0,OverallStrain为1。
影响note难度的还包括以下值:
HoldFactor:默认时为1,如果当前note的结束时间小于任意轨道的滑条结束时间(也就是目前note是和其它滑条一同存在)的话,则为1.25。因此点面或面海这样的排列会有更高的难度。
HoldAddition:如果当前note的开始时间小于滑条结束时间,结束时间大于滑条结束时间,则:
该函数图像如图所示[2]。多个轨道上都有滑条时,以满足以上条件的滑条中最后一个结束的为准。因此,类似下图所示[3]的滑条之间相互重叠的排列会有更高的难度,而且两个滑条的结束时间需要有一定的距离,才会有比较高的HoldAddition[4]。
IndividualStrain
IndividualStrain的计算方式为:
时间差即当前note距离上一个note的时间。当前note对应轨道的IndividualStrain会加上。
OverallStrain
OverallStrain的计算方式为:
HeldUntil
初始时等于上一个note的HeldUntil,但当前note对应轨道的HeldUntil会变为当前note的结束时间(普通note的结束时间和开始时间相同)。
提示
由于第二个note才开始计算这些参数,这导致一个神奇的现象:如果第一个note就是滑条的话,它的结束时间并不会被记录到HeldUntil中,之后的note也不会受到由这个滑条带来的难度值计算变化。怎么看这都是一个bug。
note的难度可以理解为这样的结构:IndividualStrain和OverallStrain沿着谱面向下传递,其中IndividualStrain沿着当前轨道传递,OverallStrain沿着整个谱面传递。如下图所示。同一时间的note之间的传递顺序没有特殊意义。

note的IndividualStrain和OverallStrain在传递过程中会衰减,叠加到后面note的IndividualStrain和OverallStrain上。谱面密度越高,则之前note的IndividualStrain和OverallStrain在传递到这个note时衰减的就越少,难度就会越高。
在这两个参数中,OverallStrain占难度的大多数,IndividualStrain比例较小,只是为叠/纵连这样的排列增加一定比例的难度[5]。
谱面难度计算
谱面从时间戳为0开始,间隔400毫秒分为许多区间。
提示
注意这里出现的不是第一个note的时间,也不是第一个BPM区间开始的时间,而是谱面开始的时间(即音频文件开始的时间)。所以用Audition之类的软件修改音频文件,note的时间也随之改变,有可能影响难度。油管上甚至有这方面的教程。
每个区间的默认难度值计算方式如下:
- 若该区间之前没有note,则默认难度值为0。
- 若该区间之前有note,则默认难度值为:
区间的最终难度值是默认难度值以及区间内部所有note难度值的最大值。
计算所有区间的难度值后,将所有区间按从大到小排序,排在第位的则难度值乘以,然后相加,即为最终谱面的难度值[6]。
将难度值乘以0.018,即为谱面的星数。
其实我之前提出了一些能够改进mania难度算法的想法,结果写完这篇文章才发现其中有一半以上在现有的难度算法中已经有了。再怎么说Tom94也是苏黎世理工的高材生。 ↩︎
熟悉机器学习的同学一定能看出来,这是一个Sigmoid函数。 ↩︎
等等,这张图为什么看起来意外的好看……可以当什么软件的图标吧。 ↩︎
别问我是怎么知道的——之前我写计算难度的代码的时候,最后算出来的星数只有正确星数的0.8~0.9倍,而且不同谱面比例还不一样。反复debug也没有找到哪里有问题。最后发现是在计算时把IndividualStrains写成IndividualStrain了——就这一个“s”的问题。这说明即使没有IndividualStrains,最终谱面的难度也不会降低太多。 ↩︎
和总pp的计算方法一样。 ↩︎