From f0f11522677f7f5b1bda192db1b735674ac7fe8e Mon Sep 17 00:00:00 2001 From: firekann Date: Thu, 18 Apr 2024 18:29:09 +0900 Subject: [PATCH 1/4] feat: add calculate score from note accuracy --- game/src/game/display_result.rs | 3 +- game/src/game/game_player/game_result.rs | 1 + game/src/game/game_player/timing_judge.rs | 37 ++++++++++++++--------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/game/src/game/display_result.rs b/game/src/game/display_result.rs index a92338b..bee9e1e 100644 --- a/game/src/game/display_result.rs +++ b/game/src/game/display_result.rs @@ -30,7 +30,7 @@ fn render_game_result(canvas: &mut Canvas, result: &GameResult) { let texts = format!( - "{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}", + "{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}", "Overchaos", result.overchaos_count, "Perfect", result.perfect_count, "Great", result.great_count, @@ -38,6 +38,7 @@ fn render_game_result(canvas: &mut Canvas, result: &GameResult) { "Bad", result.bad_count, "Miss", result.miss_count, "Combo", result.combo, + "Score", result.score, ); for (idx, text) in texts.split("\n").enumerate() { diff --git a/game/src/game/game_player/game_result.rs b/game/src/game/game_player/game_result.rs index d1b3aae..27aa924 100644 --- a/game/src/game/game_player/game_result.rs +++ b/game/src/game/game_player/game_result.rs @@ -7,4 +7,5 @@ pub(crate) struct GameResult { pub bad_count: u64, pub miss_count: u64, pub combo: u64, + pub score: u64, } diff --git a/game/src/game/game_player/timing_judge.rs b/game/src/game/game_player/timing_judge.rs index 6e69a5f..731d913 100644 --- a/game/src/game/game_player/timing_judge.rs +++ b/game/src/game/game_player/timing_judge.rs @@ -46,6 +46,7 @@ pub(crate) struct TimingJudge { bad_count: u64, miss_count: u64, combo: u64, + score: u64, } pub(crate) struct JudgeResult { @@ -53,8 +54,7 @@ pub(crate) struct JudgeResult { pub note_id: u64, } -fn note_accuracy_from_time_difference(difference: i64) -> NoteAccuracy { - let difference_abs = difference.abs(); +fn note_accuracy_from_time_difference(difference_abs: i64) -> NoteAccuracy { if difference_abs <= OVERCHAOS_TIMING { NoteAccuracy::Overchaos } else if difference_abs <= PERFECT_TIMING { @@ -103,13 +103,14 @@ impl TimingJudge { return TimingJudge { notes: notes, - bad_count: 0, - combo: 0, - good_count: 0, - great_count: 0, - miss_count: 0, overchaos_count: 0, perfect_count: 0, + great_count: 0, + good_count: 0, + bad_count: 0, + miss_count: 0, + combo: 0, + score: 0, }; } @@ -158,8 +159,13 @@ impl TimingJudge { // if it's processable note, calculate accuracy if let Some(hit_timing) = i.hit_timing { - let note_accuracy = - note_accuracy_from_time_difference(hit_timing as i64 - precise_timing as i64); + let difference_abs = (hit_timing as i64 - precise_timing as i64).abs(); + + // calculte score by the accuracy + self.score += ((f64::abs(160.0 - difference_abs.clamp(10, 160) as f64) / 160.0) + * 1000.0) as u64; + + let note_accuracy = note_accuracy_from_time_difference(difference_abs); processed_index = Some(idx); result = Some(note_accuracy); @@ -190,7 +196,7 @@ impl TimingJudge { self.good_count += 1; } NoteAccuracy::Bad => { - self.combo += 1; + self.combo = 0; self.bad_count += 1; } NoteAccuracy::Miss => { @@ -213,13 +219,14 @@ impl TimingJudge { /// Creates game result pub fn get_game_result(&self) -> GameResult { return GameResult { - bad_count: self.bad_count, - combo: self.combo, - good_count: self.good_count, - great_count: self.great_count, - miss_count: self.miss_count, overchaos_count: self.overchaos_count, perfect_count: self.perfect_count, + great_count: self.great_count, + good_count: self.good_count, + bad_count: self.bad_count, + miss_count: self.miss_count, + combo: self.combo, + score: self.score, }; } } From 6abd02df8bdbb9d2c0b09872032223c8dc55c50c Mon Sep 17 00:00:00 2001 From: firekann Date: Thu, 18 Apr 2024 18:40:28 +0900 Subject: [PATCH 2/4] feat: add calculate health from note accuracy --- game/src/game/display_result.rs | 3 ++- game/src/game/game_player/game_result.rs | 2 ++ game/src/game/game_player/timing_judge.rs | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/game/src/game/display_result.rs b/game/src/game/display_result.rs index bee9e1e..790ce0b 100644 --- a/game/src/game/display_result.rs +++ b/game/src/game/display_result.rs @@ -30,7 +30,7 @@ fn render_game_result(canvas: &mut Canvas, result: &GameResult) { let texts = format!( - "{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}", + "{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{:<9} {:>4}\n{}/{}", "Overchaos", result.overchaos_count, "Perfect", result.perfect_count, "Great", result.great_count, @@ -39,6 +39,7 @@ fn render_game_result(canvas: &mut Canvas, result: &GameResult) { "Miss", result.miss_count, "Combo", result.combo, "Score", result.score, + result.health, result.max_health ); for (idx, text) in texts.split("\n").enumerate() { diff --git a/game/src/game/game_player/game_result.rs b/game/src/game/game_player/game_result.rs index 27aa924..4569885 100644 --- a/game/src/game/game_player/game_result.rs +++ b/game/src/game/game_player/game_result.rs @@ -8,4 +8,6 @@ pub(crate) struct GameResult { pub miss_count: u64, pub combo: u64, pub score: u64, + pub health: i64, + pub max_health: u64, } diff --git a/game/src/game/game_player/timing_judge.rs b/game/src/game/game_player/timing_judge.rs index 731d913..1cb6e9a 100644 --- a/game/src/game/game_player/timing_judge.rs +++ b/game/src/game/game_player/timing_judge.rs @@ -47,6 +47,8 @@ pub(crate) struct TimingJudge { miss_count: u64, combo: u64, score: u64, + health: i64, + max_health: u64, } pub(crate) struct JudgeResult { @@ -101,6 +103,9 @@ impl TimingJudge { .cmp(&b.note.timing_in_ms(b.bpm, b.delay)) }); + let all_note_count = chart.left_face.len() + chart.right_face.len(); + let max_health = all_note_count as u64 * 100; + return TimingJudge { notes: notes, overchaos_count: 0, @@ -111,6 +116,8 @@ impl TimingJudge { miss_count: 0, combo: 0, score: 0, + health: max_health as i64, + max_health: max_health, }; } @@ -182,14 +189,17 @@ impl TimingJudge { NoteAccuracy::Overchaos => { self.combo += 1; self.overchaos_count += 1; + self.health += 400; } NoteAccuracy::Perfect => { self.combo += 1; self.perfect_count += 1; + self.health += 200; } NoteAccuracy::Great => { self.combo += 1; self.great_count += 1; + self.health += 100; } NoteAccuracy::Good => { self.combo += 1; @@ -198,14 +208,19 @@ impl TimingJudge { NoteAccuracy::Bad => { self.combo = 0; self.bad_count += 1; + self.health -= 100; } NoteAccuracy::Miss => { // miss breaks the combo self.combo = 0; self.miss_count += 1; + self.health -= 200; } } + // clamp the health between 0 and max_health + self.health = self.health.clamp(0, self.max_health as i64); + return Some(JudgeResult { accuracy: processed_accuracy.clone(), note_id: processed_note_id, @@ -227,6 +242,8 @@ impl TimingJudge { miss_count: self.miss_count, combo: self.combo, score: self.score, + health: self.health, + max_health: self.max_health, }; } } From 5f6da051a3cd84d42e7755cc5488dbb9d1a9010a Mon Sep 17 00:00:00 2001 From: firekann Date: Tue, 30 Apr 2024 17:32:10 +0900 Subject: [PATCH 3/4] fix: max value of f64::abs(160.0 - difference_abs.clamp(10, 160) is 150. So div by 150 --- game/src/game/game_player/timing_judge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/src/game/game_player/timing_judge.rs b/game/src/game/game_player/timing_judge.rs index 1cb6e9a..0ecacab 100644 --- a/game/src/game/game_player/timing_judge.rs +++ b/game/src/game/game_player/timing_judge.rs @@ -169,7 +169,7 @@ impl TimingJudge { let difference_abs = (hit_timing as i64 - precise_timing as i64).abs(); // calculte score by the accuracy - self.score += ((f64::abs(160.0 - difference_abs.clamp(10, 160) as f64) / 160.0) + self.score += ((f64::abs(160.0 - difference_abs.clamp(10, 160) as f64) / 150.0) * 1000.0) as u64; let note_accuracy = note_accuracy_from_time_difference(difference_abs); From 78cb769cce7b3c8b80f5d220778e050219fbeecb Mon Sep 17 00:00:00 2001 From: firekann Date: Tue, 30 Apr 2024 18:07:36 +0900 Subject: [PATCH 4/4] feat: Prevent health increase when health is 0 or less before --- game/src/game/game_player/timing_judge.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/game/src/game/game_player/timing_judge.rs b/game/src/game/game_player/timing_judge.rs index 0ecacab..7a37f58 100644 --- a/game/src/game/game_player/timing_judge.rs +++ b/game/src/game/game_player/timing_judge.rs @@ -169,7 +169,9 @@ impl TimingJudge { let difference_abs = (hit_timing as i64 - precise_timing as i64).abs(); // calculte score by the accuracy - self.score += ((f64::abs(160.0 - difference_abs.clamp(10, 160) as f64) / 150.0) + self.score += ((f64::abs( + BAD_TIMING as f64 - difference_abs.clamp(OVERCHAOS_TIMING, BAD_TIMING) as f64, + ) / (BAD_TIMING - OVERCHAOS_TIMING) as f64) * 1000.0) as u64; let note_accuracy = note_accuracy_from_time_difference(difference_abs); @@ -184,6 +186,8 @@ impl TimingJudge { if let Some(processed_accuracy) = &result { let processed_note_id = self.notes.get(processed_index.unwrap()).unwrap().id; self.notes.remove(processed_index.unwrap()); + // check if the health is zero -> already died + let is_health_zero = self.health == 0; // increase or set combo and count match processed_accuracy { NoteAccuracy::Overchaos => { @@ -218,9 +222,13 @@ impl TimingJudge { } } - // clamp the health between 0 and max_health - self.health = self.health.clamp(0, self.max_health as i64); - + // check if the health is zero -> already died + if is_health_zero { + self.health = 0; + } else { + // clamp the health between 0 and max_health + self.health = self.health.clamp(0, self.max_health as i64); + } return Some(JudgeResult { accuracy: processed_accuracy.clone(), note_id: processed_note_id,