Music Shake 첫 박 시각 · 카운트다운 · 옛 일시 정지 판 정리
This commit is contained in:
@@ -150,7 +150,7 @@ typedef ShakeLive = ({
|
||||
/// Music Shake 구간 판정표 — `fn-quest-verify-music-shake` 가 받는 **증거**(원장 B-24).
|
||||
///
|
||||
/// 시각은 **영상 재생 시각**(0 = 영상 처음)이다 — 공식 YouTube 영상을 보며 흔드는 퀘스트라
|
||||
/// (PRD-04) 박은 영상에 붙는다. 곡의 박(`quests.bpm`)마다 한 구간이고, 흔들기는 가장 가까운 박
|
||||
/// (PRD-04) 박은 영상에 붙는다. 곡의 박(`quests.bpm`)마다 한 구간이고 첫 박은 `quests.firstBeatMs` 이며(판 길이 `totalSegments` 는 곡 전체를 덮도록 운영자가 정한다), 흔들기는 가장 가까운 박
|
||||
/// 하나에만 붙는다. 박과의 거리가 [ShakeWindows.perfect] 박 이내면 perfect, [ShakeWindows.good]
|
||||
/// 박 이내면 good, 없으면 miss. **성공 판정은 서버가 다시 한다** — 표가 스스로 모순되면(합 ≠ 구간
|
||||
/// 수) 서버가 끊는다.
|
||||
@@ -158,6 +158,7 @@ class ShakeJudge {
|
||||
ShakeJudge({
|
||||
required this.bpm,
|
||||
required this.segments,
|
||||
this.firstBeat = Duration.zero,
|
||||
this.windows = const ShakeWindows(),
|
||||
List<double> hits = const [],
|
||||
this.position = Duration.zero,
|
||||
@@ -170,6 +171,9 @@ class ShakeJudge {
|
||||
|
||||
final double bpm;
|
||||
final int segments;
|
||||
|
||||
/// `quests.firstBeatMs` — 영상에서 첫 박이 오는 시각. 박 i 는 `firstBeat + i * 60/bpm` 이다.
|
||||
final Duration firstBeat;
|
||||
final ShakeWindows windows;
|
||||
|
||||
/// 마지막으로 본 영상 시각 — 진행 화면을 나가면 「이어하기」의 시작점이 된다.
|
||||
@@ -184,13 +188,19 @@ class ShakeJudge {
|
||||
Duration get beat => Duration(microseconds: (60e6 / bpm).round());
|
||||
|
||||
/// 마지막 박의 판정 창이 닫히는 영상 시각.
|
||||
Duration get end => Duration(
|
||||
microseconds: (beat.inMicroseconds * (segments - 1 + windows.good)).round(),
|
||||
);
|
||||
Duration get end =>
|
||||
firstBeat +
|
||||
Duration(
|
||||
microseconds: (beat.inMicroseconds * (segments - 1 + windows.good)).round(),
|
||||
);
|
||||
|
||||
/// 영상 시각 [at] 이 첫 박에서 몇 박 떨어졌나.
|
||||
double _beats(Duration at) =>
|
||||
(at - firstBeat).inMicroseconds / beat.inMicroseconds;
|
||||
|
||||
/// 영상 시각 [at] 의 흔들기 한 번.
|
||||
void add(Duration at) {
|
||||
final pos = at.inMicroseconds / beat.inMicroseconds;
|
||||
final pos = _beats(at);
|
||||
final i = pos.round();
|
||||
if (i < 0 || i >= segments) return;
|
||||
final d = (pos - i).abs();
|
||||
@@ -203,7 +213,7 @@ class ShakeJudge {
|
||||
ShakeLive live(Duration now) {
|
||||
var perfect = 0, good = 0, miss = 0, combo = 0, maxCombo = 0, judged = 0;
|
||||
ShakeHit? last;
|
||||
final pos = now.inMicroseconds / beat.inMicroseconds;
|
||||
final pos = _beats(now);
|
||||
for (var i = 0; i < segments && i + windows.good <= pos; i++) {
|
||||
judged++;
|
||||
final d = _best[i];
|
||||
|
||||
Reference in New Issue
Block a user