From dd3a175b5513203f49b9f9e85eba1f6cd167a851 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Fri, 9 Apr 2021 16:28:45 +0300 Subject: [PATCH] Test implementation of drawing timeline --- application.cpp | 3 +- timeline.cpp | 96 +++++++++++++++++++++++++++++++++++++++---------- timeline.h | 24 +++++++++---- 3 files changed, 96 insertions(+), 27 deletions(-) diff --git a/application.cpp b/application.cpp index bf249b7..2a3fbd6 100644 --- a/application.cpp +++ b/application.cpp @@ -147,8 +147,6 @@ void Application::onTap(const Note::Arrow &arrow) if (arrow == Note::Arrow::NONE) return; - _debug.spawnGreenPulse(); - const auto music_offset = _music.getPlayingOffset().asMicroseconds(); const auto note = _timeline.fetchActiveNote(music_offset); @@ -178,6 +176,7 @@ void Application::update() void Application::draw() { _game_window.clear(); + _game_window.draw(_timeline); _game_window.draw(_debug); _game_window.draw(_grade); _game_window.display(); diff --git a/timeline.cpp b/timeline.cpp index c68eb49..700b9b9 100644 --- a/timeline.cpp +++ b/timeline.cpp @@ -1,6 +1,7 @@ #include "timeline.h" #include "note.h" +#include #include Timeline::Timeline() @@ -9,64 +10,123 @@ Timeline::Timeline() // Length is 1:14 // I calculated that the time between beats is about 1412162 microseconds + _timeline.reserve(1000); + microsec starting_beat_offset = 372162; int amount_of_beats = 209; - microsec time_between_beats = 1412162; + microsec interval = 1412162; microsec note_input_offset = 412162; - microsec interval = starting_beat_offset; - microsec AAAAAAAAENDBLYAT = starting_beat_offset + (time_between_beats * amount_of_beats); + microsec bpm_iterator = starting_beat_offset; + microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); + _visibility_offset = note_input_offset * 3; Note::resetPrecisionQualifier(note_input_offset / 3); - while (interval < AAAAAAAAENDBLYAT) + while (bpm_iterator < bpm_end) { - _timeline.emplace_back(new Note(interval, note_input_offset)); - interval += time_between_beats; + _timeline.emplace_back(new Note(bpm_iterator, note_input_offset)); + bpm_iterator += interval; } + _timeline[0]->setPosition({200, 200}); + _timeline[1]->setPosition({250, 200}); + _timeline[2]->setPosition({300, 200}); + _timeline[3]->setPosition({350, 200}); + _timeline[4]->setPosition({400, 200}); + _timeline[5]->setPosition({450, 200}); + _timeline[6]->setPosition({200, 300}); + _timeline[7]->setPosition({250, 300}); + _timeline[8]->setPosition({300, 300}); + _timeline[9]->setPosition({350, 300}); + _timeline[10]->setPosition({400, 300}); + _timeline[11]->setPosition({450, 300}); + _active_note = nullptr; + _last_visible_note = _timeline.end(); _top_note = _timeline.begin(); + + prepareNotesToDraw(0); +} + +void Timeline::prepareNotesToDraw(const microsec &music_offset) +{ + auto note_iterator = _top_note; + + while (((*note_iterator)->offset() - _visibility_offset) >= music_offset) + ++note_iterator; + + _last_visible_note = note_iterator; } Timeline::~Timeline() +{ + clear(); +} + +void Timeline::clear() { for (auto note : _timeline) delete note; _timeline.clear(); _top_note = _timeline.end(); + _last_visible_note = _timeline.end(); _active_note = nullptr; Note::resetPrecisionQualifier(); } -void Timeline::update(const microsec µseconds) -{ - checkCurrentActiveNote(microseconds); - checkForNextActiveNote(microseconds); +static sf::RectangleShape createNoteGlyph(const std::vector::const_iterator& note_to_draw) +{ // Temporary solution + sf::RectangleShape ret; + const auto position = (*note_to_draw)->position(); + ret.setPosition(position.x, position.y); + ret.setFillColor(sf::Color(255, 100, 0)); + ret.setSize({10.f, 10.f}); + return ret; } -void Timeline::checkCurrentActiveNote(const microsec µseconds) +void Timeline::draw(sf::RenderTarget& target, sf::RenderStates states) const // Temporary solution { - if (_active_note && !_active_note->isActive(microseconds)) + if (_last_visible_note == _timeline.end() || _top_note > _last_visible_note) + return; + + auto note_to_draw = _top_note; + while (note_to_draw != (_last_visible_note + 1)) + { + target.draw(createNoteGlyph(note_to_draw), states); + ++note_to_draw; + } +} + +void Timeline::update(const microsec &music_offset) +{ + checkCurrentActiveNote(music_offset); + checkForNextActiveNote(music_offset); + prepareNotesToDraw(music_offset); +} + +void Timeline::checkCurrentActiveNote(const microsec &music_offset) +{ + if (_active_note && !_active_note->isActive(music_offset)) { _active_note = nullptr; ++_top_note; } } -void Timeline::checkForNextActiveNote(const microsec µseconds) +void Timeline::checkForNextActiveNote(const microsec &music_offset) { - if (!_active_note && (*_top_note)->isActive(microseconds)) + if (!_active_note && (*_top_note)->isActive(music_offset)) { - std::cout << "New active note: " << microseconds << '\n'; + std::cout << "New active note: " << music_offset << '\n'; _active_note = *_top_note; } } -const Note* Timeline::fetchActiveNote(const microsec µseconds) noexcept +const Note* Timeline::fetchActiveNote(const microsec &music_offset) noexcept { - std::cout << "Clicked at: " << microseconds << '\n'; - update(microseconds); + std::cout << "Clicked at: " << music_offset << '\n'; + update(music_offset); return _active_note; } diff --git a/timeline.h b/timeline.h index af7c051..d7997c4 100644 --- a/timeline.h +++ b/timeline.h @@ -2,6 +2,7 @@ #define TIMELINE_H #include +#include #include #include @@ -9,22 +10,31 @@ using microsec = sf::Int64; class Note; -class Timeline +class Timeline : public sf::Drawable // Probably it's bad { public: explicit Timeline(); - ~Timeline(); + virtual ~Timeline(); - void update(const microsec& microseconds); - const Note* fetchActiveNote(const microsec µseconds) noexcept; + virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; + + void update(const microsec& music_offset); + const Note* fetchActiveNote(const microsec &music_offset) noexcept; + + /* void init(); */ + void clear(); private: std::vector _timeline; - std::vector::iterator _top_note; + std::vector::const_iterator _top_note; Note* _active_note; - void checkCurrentActiveNote(const microsec µseconds); - void checkForNextActiveNote(const microsec µseconds); + std::vector::const_iterator _last_visible_note; + microsec _visibility_offset; + + void checkCurrentActiveNote(const microsec &music_offset); + void checkForNextActiveNote(const microsec &music_offset); + void prepareNotesToDraw(const microsec &music_offset); /* Difference between top and active note is that * top note is the note handling input right now