高级 - LingFeng-bbben/MajdataPlay GitHub Wiki
此页用于记录Majdata Play部分实现细节
判定
Majdata Play每帧会对处于活动状态的Note进行判定,判定区间为半开半闭区间
请注意,Majdata Play内所有判定区间上界与下界单位都是ms
,特殊情况会额外进行说明
PlayerLoop流程简化图如下:
---------------
| PreUpdate |
---------------
|
MajTimeline.PreUpdate
|
InputManager.PreUpdate
|
INoteTimeProvider.PreUpdate
|
NoteManager.PreUpdate
|
NoteDrop.PreUpdate
|
------------
| Update |
------------
|
NoteDrop.Update
|
----------------
| LateUpdate |
----------------
|
NoteAudioManager.LateUpdate
|
NoteDrop.LateUpdate (if exists)
|
EachLineDrop.LateUpdate
Tap
Source: NoteDrop.cs#L165
总区间: [-150,150]
详情:
为方便查看,表格内使用帧数表示区间上界与下界
1f
表示60帧下的1帧间隔,换算成ms
为1f * 16.6666
等级 | 范围 | 累计 |
---|---|---|
TooFast | (-inf, -9f) |
None |
FastGood | [-9f, -6f) |
3f |
FastGreat 3rd | [-6f, -5f) |
1f |
FastGreat 2nd | [-5f, -4f) |
1f |
FastGteat 1st | [-4f, -3f) |
1f |
FastPerfect 3nd | [-3f, -2f) |
1f |
FastPerfect 2nd | [-2f, -1f) |
1f |
Perfect | [-1f, 1f] |
2f |
LatePerfect 2nd | (1f, 2f] |
1f |
LatePerfect 3nd | (2f, 3f] |
1f |
LateGteat 1st | (3f, 4f] |
1f |
LateGreat 2nd | (4f, 5f] |
1f |
LateGreat 3rd | (5f, 6f] |
1f |
LateGood | (6f, 9f] |
3f |
Miss | (9f, inf) |
None |
Hold
Head
参见 Tap
Body
Source: HoldDrop.cs#L449
Majdata Play会忽略Hold的开头6f与结尾12f,并且会根据头部判定对Hold时值进行修正,详情参见Hold 尾判判定
当累计释放时长大于2f
,也就是33.3333ms
时,才会认为Hold被释放,并累计释放时长
Tail
Source
- Deluxe: NoteLongDrop.cs#L30
- FiNALE: NoteLongDrop.cs#L221
Deluxe
当判定误差(_judgeDiff)
为Fast(_judgeDiff < 0)
时,不对Hold时值进行修正
当判定误差为Late时,会从Length
减去_judgeDiff
再进行尾判
如果Hold修正后的时值小于等于0.3s
,不会进行尾判,最终判定等级为头部判定等级
以下是尾判修正的详细说明:
Tip: 为方便表述,下面将使用p
表示“Hold完成比例”
- p >= 1
- 如果头判为
Great 2nd/3rd
,向上修正为Great
- 如果头判为
Good
,向上修正为Great
- 如果头判为
Miss
,向上修正为Good
- 其他等级不进行任何修正
- 如果头判为
- p >= 0.67
- 如果头判为
Critical Perfect
, 向下修正为Perfect 2nd
- 如果头判为
Great 2nd/3rd
,向上修正为Great
- 如果头判为
Good
,向上修正为Great
- 如果头判为
Miss
,向上修正为Good
- 如果头判为
- p >= 0.33
- 如果头判等级比
Great
高,向下修正为Great
- 如果头判为
Great 2nd/3rd
,向上修正为Great
- 如果头判为
Good
,向上修正为Great
- 如果头判为
Miss
,向上修正为Good
- 如果头判等级比
- p >= 0.05
- 如果头判等级比
Good
高,向下修正为Good
- 如果头判为
Miss
,向上修正为Good
- 如果头判等级比
- p >= 0
- 如果头判等级比
Good
高,向下修正为Good
- 如果头判等级比
Slide
- Deluxe: SlideBase.cs#L182
- FiNALE: SlideBase.cs#L224
注意
Slide常数由内录/判定区图片叠加分析得出,数值可能不准确
Slide Deluxe判定实现参考自: maimai判定详解 - Moying
感谢软壳与热心mai友提供Great子区间
总区间: (-inf,600]
_lastWaitTime
为Slide在最后一个判定区的停留时间
_table.Const
/wifiConst
为Slide在最后一个判定区滞留时间与Slide时值的比例
Deluxe
Perfect区间不是静态的,此区间会根据_lastWaitTime
动态扩展,由基础区间+扩展区间组成
基础区间: [-14f, 14f]
扩展区间: ext = _lastWaitTime / 4
,最大为22f
扩展时,Perfect会挤占Great、Good区间,详情见图:
扩展前:
| <- Fast Great(15f) ->| <- Perfect(28f) -> | <- Late Great(15f) -> |
扩展后:
| <- Fast Great(10f) ->| <- Perfect(28 + 10f) -> | <- Late Great(10f) -> |
对比:
| <- Fast Great(15f) ->| <- Perfect(28f) -> | <- Late Great(15f) -> |
| <- Perfect(28 + 10f) -> |
为实现旧框体的严判,Majdata Play自行实现了Perfect子区间:
Perfect
: (基础区间+扩展区间) * 0.3333
Perfect 2nd
: (基础区间+扩展区间) * 0.6666
Perfect 3rd
: 基础区间+扩展区间
当严判被关闭时,Slide会自动将Perfect 2nd
和Perfect 3rd
修正为Perfect
详情:
等级 | 范围 | 累计 |
---|---|---|
FastGood | (-inf, -29f) |
None |
FastGreat 3rd | [-29f, -25f) |
4f |
FastGreat 2nd | [-25f, -21f) |
4f |
FastGteat 1st | [-21f, -14f) |
7f |
Perfect | [-14f, 14f] |
28f |
LateGteat 1st | (14f, 21f] |
7f |
LateGreat 2nd | (21f, 25f] |
4f |
LateGreat 3rd | (25f, 29f] |
4f |
LateGood | (36f, 29f] |
7f |
Miss | (36f, inf) |
None |
FiNALE
Warning
FiNALE Slide判定由手元、谱面确认、软壳经验分析而得,数据可能不准确
欢迎在issue提出任何提案
Finale的Perfect区间是静态的,不会根据Slide在最后一个判定区停留时长动态扩展
为兼容Deluxe的Break Slide,Majdata Play自行实现了FiNALE的Great子区间:
详情:
等级 | 范围 | 累计 |
---|---|---|
FastGood | (-inf, -27f) |
None |
FastGreat 3rd | [-27f, -21f) |
6f |
FastGreat 2nd | [-21f, -15f) |
6f |
FastGteat 1st | [-15f, -9f) |
6f |
FastPerfect 3nd | [-9f, -6f) |
3f |
FastPerfect 2nd | [-6f, -3f) |
3f |
Perfect | [-3f, 3f] |
6f |
LatePerfect 2nd | (3f, 6f] |
3f |
LatePerfect 3nd | (6f, 9f] |
3f |
LateGteat 1st | (9f, 15f] |
6f |
LateGreat 2nd | (15f, 21f] |
6f |
LateGreat 3rd | (21f, 27f] |
6f |
LateGood | (36f, 21f] |
15f |
Miss | (36f, inf) |
None |
Touch
Source: NoteDrop.cs#L177
总区间: [-150, 316.6666]
Touch不存在Fast子判定,当当前帧时间大于-150ms
时接受判定
为兼容Break Touch,Majdata Play自行实现了Perfect与Great的子区间:
Perfect子区间Step: (12f - 9f) / 2 = 1.5f
Great子区间Step: (15f - 12f) / 3 = 1f
因此,Perfect的子区间并不是完整的1帧
详情:
等级 | 范围 | 累计 |
---|---|---|
Perfect | [-9f, 9f] |
18f |
LatePerfect 2nd | (9f, 10.5f] |
1.5f |
LatePerfect 3nd | (10.5f, 12f] |
1.5f |
LateGteat 1st | (12f, 13f] |
1f |
LateGreat 2nd | (13f, 14f] |
1f |
LateGreat 3rd | (14f, 15f] |
1f |
LateGood | (15f, 18f] |
3f |
Miss | (38f, inf) |
None |