diff --git a/include/note.h b/include/note.h index 276b36f..119f828 100644 --- a/include/note.h +++ b/include/note.h @@ -16,7 +16,7 @@ public: virtual void putToGame(const microsec &offset) = 0; virtual bool isInGame() const = 0; - virtual bool isExpired() const = 0; + virtual bool shouldRemove() const = 0; microsec offset() const { diff --git a/src/classicgame/classicmapcreator.cpp b/src/classicgame/classicmapcreator.cpp index 7eaac04..514a792 100644 --- a/src/classicgame/classicmapcreator.cpp +++ b/src/classicgame/classicmapcreator.cpp @@ -9,11 +9,12 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const { (void) filepath; - microsec starting_beat_offset = 352162; + microsec starting_beat_offset = 362162; int amount_of_beats = 209; microsec interval = 1412162; - microsec tempo_interval = interval / 4; - microsec note_input_offset = 412162 / 3; + microsec tempo_interval = interval / 2; + microsec note_input_offset = 412162 / 2; + microsec note_input_offset_fast = 412162 / 6; microsec bpm_iterator = starting_beat_offset; microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); @@ -30,7 +31,7 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const while (bpm_iterator < bpm_end) { ClassicNote::ClassicNoteInitializer init; - ClassicNote::ClassicNoteInitializer::Element element, element2; + ClassicNote::ClassicNoteInitializer::Element element; init.intervals = input_intervals; init.perfect_offset = bpm_iterator; @@ -39,22 +40,29 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const element.keys = {sf::Keyboard::W, sf::Keyboard::Up}; element.type = Type::UP; + init.elements = {element}; + + notes.emplace_back(new ClassicNote(std::move(init), _graphics_manager)); + if (counter == 0) { - counter = 3; - element2.coordinates = {x, 300.}; - element2.falling_curve_interpolation = {}; - element2.keys = {sf::Keyboard::A, sf::Keyboard::Left}; - element2.type = Type::LEFT; + ClassicNote::ClassicNoteInitializer init2; + ClassicNote::ClassicNoteInitializer::Element element2; + init2.intervals = input_intervals; + init2.perfect_offset = bpm_iterator + note_input_offset_fast; - init.elements = {element, element2}; + element2.coordinates = {x + 35, 390. + 50.}; + element2.falling_curve_interpolation = {}; + element2.keys = {sf::Keyboard::D, sf::Keyboard::Right}; + element2.type = Type::RIGHT; + + init2.elements = {element2}; + notes.emplace_back(new ClassicNote(std::move(init2), _graphics_manager)); + counter = 3; } - else - init.elements = {element}; --counter; - notes.emplace_back(new ClassicNote(std::move(init), _graphics_manager)); bpm_iterator += tempo_interval; x += 70; diff --git a/src/classicgame/classicnote.cpp b/src/classicgame/classicnote.cpp index 459b85e..63a62bf 100644 --- a/src/classicgame/classicnote.cpp +++ b/src/classicgame/classicnote.cpp @@ -1,8 +1,11 @@ #include "classicnote.h" #include "classicsprite.h" #include "classicgraphicsmanager.h" + +// Replace with interface by dependency injection #include "classicflyinganimationscenario.h" #include "classicdyinganimationscenario.h" +// ClassicNote::ClassicNote(ClassicNoteInitializer &&init, const std::unique_ptr &manager) : Note(init.perfect_offset), @@ -17,6 +20,7 @@ ClassicNote::ClassicNote(ClassicNoteInitializer &&init, const std::unique_ptr(); _elements[i].animations[State::ACTIVE] = _elements[i].animations[State::FLYING]; @@ -49,7 +53,7 @@ bool ClassicNote::isInGame() const || _state == State::DYING; } -bool ClassicNote::isExpired() const +bool ClassicNote::shouldRemove() const { return _state == State::DEAD; } diff --git a/src/classicgame/classicnote.h b/src/classicgame/classicnote.h index 55332b2..0324c7a 100644 --- a/src/classicgame/classicnote.h +++ b/src/classicgame/classicnote.h @@ -56,7 +56,7 @@ public: virtual void input(PlayerInput&& inputdata) override; virtual void putToGame(const microsec &music_offset) override; virtual bool isInGame() const override; - virtual bool isExpired() const override; + virtual bool shouldRemove() const override; virtual void draw() const override; private: @@ -67,11 +67,11 @@ private: std::array, 5> animations; std::array keys; - Coordinates coordinates; - Type type; - - bool pressed = false; - sf::Keyboard::Key pressed_as; + Coordinates coordinates; // Each note may consist of several buttons. + Type type; // For example, ↑ → or ↓ → ← + // Note Element represents this idea. + bool pressed = false; // Each ending button in such sequence + sf::Keyboard::Key pressed_as; // is an element. }; std::vector _elements; diff --git a/src/classicgame/classictimeline.cpp b/src/classicgame/classictimeline.cpp index 84c77e2..ed96280 100644 --- a/src/classicgame/classictimeline.cpp +++ b/src/classicgame/classictimeline.cpp @@ -2,7 +2,10 @@ #include "classictimeline.h" #include -ClassicTimeline::ClassicTimeline() +ClassicTimeline::ClassicTimeline() : + _sfml_music_offset(0), + _previous_frame_offset(0), + _absolute_offset(0) { // BPM of METEOR is 170. // Length is 1:14 @@ -12,7 +15,6 @@ ClassicTimeline::ClassicTimeline() _music.openFromFile(song_filename); _music.setVolume(10); - _last_timestamp = -1; } void ClassicTimeline::run(std::vector&& notes, const microsec& visibility) @@ -27,6 +29,8 @@ void ClassicTimeline::run(std::vector&& notes, const microsec& visibility fetchVisibleNotes(); _music.play(); + + _previous_frame_offset = _offset_interpolator.restart().asMicroseconds(); } ClassicTimeline::~ClassicTimeline() @@ -44,15 +48,20 @@ void ClassicTimeline::clear() void ClassicTimeline::update() { - const auto& music_offset = currentMusicOffset(); - if (music_offset != _last_timestamp) + const auto interpolator_timestamp = _offset_interpolator.getElapsedTime().asMicroseconds(); + const auto sfml_new_offset = currentMusicOffset(); + + _absolute_offset += (interpolator_timestamp - _previous_frame_offset); + _previous_frame_offset = interpolator_timestamp; + if (sfml_new_offset != _sfml_music_offset) { - checkCurrentActiveNote(); - checkForNextActiveNote(); - updateVisibleSprites(music_offset); + _absolute_offset = ((_absolute_offset + sfml_new_offset) / 2); + _sfml_music_offset = sfml_new_offset; } - _last_timestamp = music_offset; + checkCurrentActiveNote(); + checkForNextActiveNote(); + updateVisibleSprites(_absolute_offset); } void ClassicTimeline::checkCurrentActiveNote() @@ -118,8 +127,7 @@ bool ClassicTimeline::isVisiblyClose(const Iterator& iterator, const microsec& m void ClassicTimeline::fetchVisibleNotes() { - const microsec music_offset = currentMusicOffset(); - findLastVisibleNote(music_offset); + findLastVisibleNote(_absolute_offset); findFirstVisibleNote(); } @@ -151,7 +159,7 @@ void ClassicTimeline::findFirstVisibleNote() while (note_iterator != _last_visible_note) { auto note = *note_iterator; - if (note->isExpired()) + if (note->shouldRemove()) ++_first_visible_note; ++note_iterator; diff --git a/src/classicgame/classictimeline.h b/src/classicgame/classictimeline.h index b72c26e..8d7dfab 100644 --- a/src/classicgame/classictimeline.h +++ b/src/classicgame/classictimeline.h @@ -3,6 +3,7 @@ #include "timeline.h" #include +#include #include #include @@ -33,9 +34,12 @@ private: std::vector _input_intervals; std::vector _timeline; microsec _visibility_offset; - microsec _last_timestamp; sf::Music _music; + sf::Clock _offset_interpolator; + microsec _sfml_music_offset; + microsec _previous_frame_offset; + microsec _absolute_offset; void updateVisibleSprites(const microsec& music_offset); void checkCurrentActiveNote();