1
0
mirror of synced 2024-11-13 18:20:53 +01:00

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:
Subject38 2020-07-22 07:47:04 -05:00 committed by GitHub
parent fd42ea7957
commit 0ae02b54fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 120 additions and 7 deletions

7
build_linux.sh Normal file
View 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
View 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

View File

@ -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;
}
}
}

View File

@ -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 = {};
};
}
}

View File

@ -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);
}

View File

@ -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;
};
}

View File

@ -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;

View File

@ -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);

View File

@ -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()) {

View File

@ -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;