Some bug fixes and feature additions (#5)
* fixed difficulty display in results screen * added script to build release easier * fixed some result screen issues and added judgement breakdown * updated release script to use O2 and no debugging * fixed judgement breakdown * Implemented proper handling of hold note releases * fixed hold notes * removed early/late * added easy build script for linux * fixed density graph bug where goods were treated like combo breaks * fixed typo * reverted removal of judgement breakdown * Update src/Data/GradedNote.cpp Co-authored-by: Stepland <16676308+Stepland@users.noreply.github.com> * Update src/Screens/Results/Results.cpp Co-authored-by: Stepland <16676308+Stepland@users.noreply.github.com> * Update src/Data/GradedNote.hpp Co-authored-by: Stepland <16676308+Stepland@users.noreply.github.com> * Update src/Drawables/GradedDensityGraph.cpp Co-authored-by: Stepland <16676308+Stepland@users.noreply.github.com> * Update src/Screens/Gameplay/Gameplay.cpp Co-authored-by: Stepland <16676308+Stepland@users.noreply.github.com> * fixed compile error * uses copy_dependencies python script now for making a release archive Co-authored-by: Seth Erfurt <serfurt@cs.utexas.edu> Co-authored-by: Seth <seth@ske.moe> Co-authored-by: Stepland <16676308+Stepland@users.noreply.github.com>
This commit is contained in:
parent
fd42ea7957
commit
0ae02b54fb
7
build_linux.sh
Normal file
7
build_linux.sh
Normal file
@ -0,0 +1,7 @@
|
||||
rm -rf build
|
||||
mkdir build
|
||||
meson build
|
||||
meson configure build -Ddebug=false -Doptimization=2
|
||||
cd build
|
||||
ninja
|
||||
cp ../assets assets -r
|
14
make_release.sh
Normal file
14
make_release.sh
Normal file
@ -0,0 +1,14 @@
|
||||
rm -rf build
|
||||
mkdir build
|
||||
meson build
|
||||
meson configure build -Ddebug=false -Doptimization=2
|
||||
cd build
|
||||
ninja
|
||||
cp ../assets assets -r
|
||||
../utils/copy_dependencies.py -f jujube.exe
|
||||
|
||||
rm -rf jujube@exe meson* build.ninja .ninja* compile_commands.json test
|
||||
|
||||
cd ..
|
||||
zip jujube.zip -r build
|
||||
mv -t build jujube.zip
|
@ -35,11 +35,11 @@ namespace Data {
|
||||
if (delta_abs < sf::Time::Zero) {
|
||||
delta_abs = -delta_abs;
|
||||
}
|
||||
if (delta_abs < sf::milliseconds(42)) {
|
||||
if (delta_abs < sf::milliseconds(40)) {
|
||||
return Judgement::Perfect;
|
||||
} else if (delta_abs < sf::milliseconds(82)) {
|
||||
} else if (delta_abs < sf::milliseconds(80)) {
|
||||
return Judgement::Great;
|
||||
} else if (delta_abs < sf::milliseconds(162)) {
|
||||
} else if (delta_abs < sf::milliseconds(160)) {
|
||||
return Judgement::Good;
|
||||
} else if (delta_abs < sf::milliseconds(533)) {
|
||||
return Judgement::Poor;
|
||||
@ -47,4 +47,33 @@ namespace Data {
|
||||
return Judgement::Miss;
|
||||
}
|
||||
}
|
||||
// implement the strange way in which jubeat judges hold note releases
|
||||
Judgement release_to_judgement(const sf::Time& duration_held, const sf::Time& note_duration, const int tail_length) {
|
||||
// if we implement hard mode we'll need a cleaner implementation of this since this would be 30. works for now though
|
||||
int error_margin = 60;
|
||||
// take the length of the note in ticks on a 300 hz clock and divide by length of tail in pixels
|
||||
// logic taken from reversing the game's timing code
|
||||
double milliseconds_to_300hz = 0.3;
|
||||
auto note_duration_300hz = static_cast<double>(note_duration.asMilliseconds()) * milliseconds_to_300hz;
|
||||
auto adjusted_note_duration = static_cast<int>(
|
||||
note_duration_300hz * (1 - (static_cast<double>(error_margin) / (tail_length*195)))
|
||||
);
|
||||
|
||||
// held for longer than duration : done
|
||||
if((duration_held.asMilliseconds() * milliseconds_to_300hz) >= adjusted_note_duration) {
|
||||
return Judgement::Perfect;
|
||||
}
|
||||
|
||||
auto percentage_held = static_cast<int>(
|
||||
duration_held.asMilliseconds() * milliseconds_to_300hz / adjusted_note_duration * 100
|
||||
);
|
||||
|
||||
if (percentage_held < 100 and percentage_held >= 81) {
|
||||
return Judgement::Great;
|
||||
} else if (percentage_held < 80 and percentage_held >= 51) {
|
||||
return Judgement::Good;
|
||||
} else {
|
||||
return Judgement::Poor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,21 @@ namespace Data {
|
||||
Resources::MarkerAnimation judgement_to_animation(Judgement j);
|
||||
|
||||
Judgement delta_to_judgement(const sf::Time& delta);
|
||||
Judgement release_to_judgement(const sf::Time& duration_held, const sf::Time& note_duration, const int tail_length);
|
||||
|
||||
struct TimedJudgement {
|
||||
TimedJudgement() : delta(sf::Time::Zero), judgement(Judgement::Miss) {};
|
||||
TimedJudgement(const sf::Time& d, const Judgement& j) : delta(d), judgement(j) {};
|
||||
explicit TimedJudgement(const sf::Time& t) : delta(t), judgement(delta_to_judgement(t)) {};
|
||||
explicit TimedJudgement(
|
||||
const sf::Time& duration_held,
|
||||
const sf::Time& t,
|
||||
const sf::Time& duration,
|
||||
const int tail_length
|
||||
) :
|
||||
delta(t),
|
||||
judgement(release_to_judgement(duration_held, duration, tail_length))
|
||||
{};
|
||||
sf::Time delta = sf::Time::Zero;
|
||||
Judgement judgement = Judgement::Miss;
|
||||
};
|
||||
@ -38,4 +48,4 @@ namespace Data {
|
||||
std::optional<TimedJudgement> tap_judgement = {};
|
||||
std::optional<TimedJudgement> long_release = {};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,10 @@ namespace Data {
|
||||
return shutter;
|
||||
}
|
||||
|
||||
int ClassicScore::get_judgement_counts(Judgement j) const {
|
||||
return judgement_counts.at(j);
|
||||
}
|
||||
|
||||
int ClassicScore::get_final_score() const {
|
||||
return get_score() + shutter*100000/1024;
|
||||
}
|
||||
@ -93,6 +97,8 @@ namespace Data {
|
||||
case Judgement::Miss:
|
||||
shutter_delta = shutter_decrement_4x;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
shutter = std::clamp(shutter+shutter_delta, 0, 1024);
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ namespace Data {
|
||||
virtual Rating get_rating() const = 0;
|
||||
// Update score according to the recieved judgement
|
||||
virtual void update(Judgement j) = 0;
|
||||
// Get judgments
|
||||
virtual int get_judgement_counts(Judgement j) const = 0;
|
||||
};
|
||||
|
||||
std::size_t count_classic_scoring_events(const std::set<Note>& notes);
|
||||
@ -64,6 +66,7 @@ namespace Data {
|
||||
int get_score() const override;
|
||||
Rating get_rating() const override;
|
||||
void update(Judgement j) override;
|
||||
int get_judgement_counts(Judgement j) const;
|
||||
private:
|
||||
int shutter = 0;
|
||||
int shutter_incerment_2x;
|
||||
@ -71,7 +74,6 @@ namespace Data {
|
||||
int shutter_decrement_4x;
|
||||
const std::size_t tap_event_count;
|
||||
std::unordered_map<Judgement, std::size_t> judgement_counts;
|
||||
|
||||
friend class Gameplay::Screen;
|
||||
};
|
||||
}
|
@ -12,6 +12,7 @@ namespace Drawables {
|
||||
case Data::Judgement::Perfect:
|
||||
return DensityLineGrade::Perfect;
|
||||
case Data::Judgement::Great:
|
||||
case Data::Judgement::Good:
|
||||
return DensityLineGrade::Great;
|
||||
default:
|
||||
return DensityLineGrade::ComboBreak;
|
||||
|
@ -611,7 +611,12 @@ namespace Gameplay {
|
||||
if (note.long_release) {
|
||||
continue;
|
||||
}
|
||||
auto timed_judgement = Data::TimedJudgement{music_time-note.timing-note.duration};
|
||||
auto timed_judgement = Data::TimedJudgement{
|
||||
music_time-note.timing,
|
||||
music_time-note.timing-note.duration,
|
||||
note.duration,
|
||||
note.get_tail_length()
|
||||
};
|
||||
note.long_release = timed_judgement;
|
||||
score.update(timed_judgement.judgement);
|
||||
graded_density_graph.update_grades(timed_judgement.judgement, note.timing+note.duration);
|
||||
|
@ -25,6 +25,7 @@ namespace Results {
|
||||
sf::Clock imgui_clock;
|
||||
auto final_score = score.get_final_score();
|
||||
auto final_rating = score.get_rating();
|
||||
|
||||
while ((not should_exit) and window.isOpen()) {
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event)) {
|
||||
@ -54,6 +55,23 @@ namespace Results {
|
||||
ImGui::SFML::Update(window, imgui_clock.restart());
|
||||
window.clear(sf::Color(7, 23, 53));
|
||||
|
||||
|
||||
// Draw song info
|
||||
// Cover is 40x40 @ (384,20)
|
||||
if (song_selection.song.cover) {
|
||||
auto cover = shared.covers.get(*song_selection.song.full_cover_path());
|
||||
if (cover) {
|
||||
sf::Sprite cover_sprite{*cover->texture};
|
||||
auto cover_size = 40.f/768.f*get_screen_width();
|
||||
Toolkit::set_size_from_local_bounds(cover_sprite, cover_size, cover_size);
|
||||
cover_sprite.setPosition(
|
||||
384.f/768.f*get_screen_width(),
|
||||
20.f/768.f*get_screen_width()
|
||||
);
|
||||
window.draw(cover_sprite);
|
||||
}
|
||||
}
|
||||
|
||||
// White line under the density graph
|
||||
sf::RectangleShape line{{get_screen_width()*1.1f,2.f/768.f*get_screen_width()}};
|
||||
Toolkit::set_origin_normalized(line, 0.5f, 0.5f);
|
||||
@ -93,6 +111,27 @@ namespace Results {
|
||||
);
|
||||
window.draw(rating_text);
|
||||
|
||||
// Draw Judgement Breakdown
|
||||
sf::Text judgements;
|
||||
judgements.setFont(shared.fallback_font.black);
|
||||
judgements.setFillColor(sf::Color(29, 98, 226));
|
||||
std::string judgement_to_string = (
|
||||
"Perfect: " + std::to_string(score.get_judgement_counts(Data::Judgement::Perfect)) + "\n" +
|
||||
"Great: " + std::to_string(score.get_judgement_counts(Data::Judgement::Great)) + "\n" +
|
||||
"Good: " + std::to_string(score.get_judgement_counts(Data::Judgement::Good)) + "\n" +
|
||||
"Poor: " + std::to_string(score.get_judgement_counts(Data::Judgement::Poor)) + "\n" +
|
||||
"Miss: " + std::to_string(score.get_judgement_counts(Data::Judgement::Miss))
|
||||
);
|
||||
judgements.setString(judgement_to_string);
|
||||
judgements.setCharacterSize(static_cast<unsigned int>(0.1f*get_panel_size()));
|
||||
Toolkit::set_local_origin_normalized(judgements, 0.5f, 0.5f);
|
||||
judgements.setPosition(
|
||||
get_ribbon_x()+0.f*get_panel_step()+0.5*get_panel_size(),
|
||||
get_ribbon_y()+2.f*get_panel_step()+0.5*get_panel_size()
|
||||
);
|
||||
window.draw(judgements);
|
||||
|
||||
|
||||
// Draw song info
|
||||
auto song_title = song_selection.song.title;
|
||||
if (not song_title.empty()) {
|
||||
|
@ -25,7 +25,7 @@ namespace Results {
|
||||
private:
|
||||
Drawables::GradedDensityGraph graded_density_graph;
|
||||
const Data::SongDifficulty& song_selection;
|
||||
const Data::Chart& chart;
|
||||
const Data::Chart chart;
|
||||
const Data::AbstractScore& score;
|
||||
bool should_exit = false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user