diff --git a/include/timeline.h b/include/timeline.h index 18d1606..cce3057 100644 --- a/include/timeline.h +++ b/include/timeline.h @@ -10,13 +10,9 @@ class Note; class Timeline { public: - - using Iterator = std::vector::const_iterator; - virtual ~Timeline() = default; virtual void update() = 0; - virtual void run(std::vector&& notes, const microsec& visibility) = 0; virtual void clear() = 0; virtual microsec currentMusicOffset() const = 0; diff --git a/src/classicgame/classicgame.cpp b/src/classicgame/classicgame.cpp index 3039828..98edd9e 100644 --- a/src/classicgame/classicgame.cpp +++ b/src/classicgame/classicgame.cpp @@ -1,6 +1,8 @@ #include "classicgame.h" #include "classictimeline.h" +#include "classicnote.h" #include "classicmapcreator.h" +#include ClassicGame::ClassicGame(std::unique_ptr&& manager) : _timeline(std::make_unique()), @@ -67,19 +69,43 @@ void ClassicGame::input(PlayerInput&& inputdata) { default: return; - break; - case sf::Event::KeyPressed: - case sf::Event::KeyReleased: - { - auto note = _timeline->getActiveNote(); + break; - if (!_timeline->isExpired(note)) + case sf::Event::KeyPressed: + { + auto note_it = _timeline->getActiveNote(); + + if (!_timeline->isExpired(note_it)) + { + auto note = (*note_it); + note->input(std::move(inputdata)); + _slap.play(); + + if (note->isHold() && note->allElementsPressed()) // also check for Type { - (*note)->input(std::move(inputdata)); - _slap.play(); + _notes_on_hold.emplace_back(note); + std::cout << "HOLD initited by " << inputdata.event.key.code << '\n'; } } - break; + } + break; + + case sf::Event::KeyReleased: + { + bool key_match = std::any_of(_notes_on_hold.begin(), _notes_on_hold.end(), + [key=inputdata.event.key.code](const auto& note) + { + return note->isPressedAs(key); + }); + + if (key_match) + { + _notes_on_hold.clear(); + std::cout << "HOLD released by " << inputdata.event.key.code << '\n'; + } + } + break; + } } diff --git a/src/classicgame/classicgame.h b/src/classicgame/classicgame.h index 6ef0b7a..464411e 100644 --- a/src/classicgame/classicgame.h +++ b/src/classicgame/classicgame.h @@ -7,6 +7,7 @@ #include #include +class ClassicNote; class ClassicTimeline; class ClassicGraphicsManager; @@ -27,6 +28,8 @@ private: std::map _buttons_to_pressed_actions; std::map _buttons_to_released_actions; + std::vector _notes_on_hold; + std::unique_ptr _timeline; std::unique_ptr _graphics_manager; sf::SoundBuffer _slap_buffer; diff --git a/src/classicgame/classicmapcreator.cpp b/src/classicgame/classicmapcreator.cpp index 514a792..ee6a380 100644 --- a/src/classicgame/classicmapcreator.cpp +++ b/src/classicgame/classicmapcreator.cpp @@ -14,12 +14,12 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const microsec interval = 1412162; microsec tempo_interval = interval / 2; microsec note_input_offset = 412162 / 2; - microsec note_input_offset_fast = 412162 / 6; + //microsec note_input_offset_fast = 412162 / 6; microsec bpm_iterator = starting_beat_offset; microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); std::vector input_intervals = {note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset}; - std::vector notes; + std::vector notes; input_intervals.shrink_to_fit(); bpm_iterator += tempo_interval; @@ -34,35 +34,26 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const ClassicNote::ClassicNoteInitializer::Element element; init.intervals = input_intervals; init.perfect_offset = bpm_iterator; + init.hold = false; element.coordinates = {x, 390.}; element.falling_curve_interpolation = {}; 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) { - ClassicNote::ClassicNoteInitializer init2; - ClassicNote::ClassicNoteInitializer::Element element2; - init2.intervals = input_intervals; - init2.perfect_offset = bpm_iterator + note_input_offset_fast; - - 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; + init.hold = true; + element.keys = {sf::Keyboard::D, sf::Keyboard::Right}; + element.type = Type::RIGHT; } --counter; + init.elements = {element}; + + notes.emplace_back(new ClassicNote(std::move(init), _graphics_manager)); + bpm_iterator += tempo_interval; x += 70; diff --git a/src/classicgame/classicmapcreator.h b/src/classicgame/classicmapcreator.h index 068fe19..76ac02c 100644 --- a/src/classicgame/classicmapcreator.h +++ b/src/classicgame/classicmapcreator.h @@ -8,7 +8,7 @@ struct Beatmap { - std::vector notes; + std::vector notes; microsec visibility_offset; }; diff --git a/src/classicgame/classicnote.cpp b/src/classicgame/classicnote.cpp index 63a62bf..9cc616d 100644 --- a/src/classicgame/classicnote.cpp +++ b/src/classicgame/classicnote.cpp @@ -14,6 +14,8 @@ ClassicNote::ClassicNote(ClassicNoteInitializer &&init, const std::unique_ptrdraw(_elements[i].sprite); } } + +bool ClassicNote::isHold() const +{ + return _isHold; +} + +bool ClassicNote::allElementsPressed() const +{ + return std::all_of(_elements.begin(), _elements.end(), + [](const auto& element) + { + return element.pressed; + }); +} + +bool ClassicNote::isPressedAs(sf::Keyboard::Key key) const +{ + return std::any_of(_elements.begin(), _elements.end(), + [key=key](const auto& element) + { + return key == element.pressed_as; + }); +} diff --git a/src/classicgame/classicnote.h b/src/classicgame/classicnote.h index 0324c7a..d35968c 100644 --- a/src/classicgame/classicnote.h +++ b/src/classicgame/classicnote.h @@ -36,6 +36,7 @@ public: { std::vector intervals; microsec perfect_offset; + bool hold; struct Element { @@ -59,6 +60,10 @@ public: virtual bool shouldRemove() const override; virtual void draw() const override; + bool isHold() const; + bool allElementsPressed() const; + bool isPressedAs(sf::Keyboard::Key key) const; + private: struct NoteElement @@ -80,4 +85,5 @@ private: const std::unique_ptr& _graphics_manager; State _state; + bool _isHold; }; diff --git a/src/classicgame/classictimeline.cpp b/src/classicgame/classictimeline.cpp index ed96280..9284eaf 100644 --- a/src/classicgame/classictimeline.cpp +++ b/src/classicgame/classictimeline.cpp @@ -1,4 +1,4 @@ -#include "note.h" +#include "classicnote.h" #include "classictimeline.h" #include @@ -17,7 +17,7 @@ ClassicTimeline::ClassicTimeline() : _music.setVolume(10); } -void ClassicTimeline::run(std::vector&& notes, const microsec& visibility) +void ClassicTimeline::run(std::vector&& notes, const microsec& visibility) { _visibility_offset = visibility; _timeline = std::move(notes); diff --git a/src/classicgame/classictimeline.h b/src/classicgame/classictimeline.h index 8d7dfab..58f5799 100644 --- a/src/classicgame/classictimeline.h +++ b/src/classicgame/classictimeline.h @@ -7,7 +7,7 @@ #include #include -class Note; +class ClassicNote; class ClassicTimeline : public Timeline { @@ -15,16 +15,19 @@ public: explicit ClassicTimeline(); virtual ~ClassicTimeline(); virtual void update() override; - virtual void run(std::vector&& notes, const microsec& visibility) override; virtual void clear() override; virtual microsec currentMusicOffset() const override; virtual void drawVisibleNotes() const override; + void run(std::vector&& notes, const microsec& visibility); + void fetchVisibleNotes(); void findLastVisibleNote(const microsec& music_offset); void findFirstVisibleNote(); + using Iterator = std::vector::const_iterator; + Iterator getActiveNote() noexcept; bool isExpired(const Iterator& iterator) const; @@ -32,7 +35,7 @@ public: private: std::vector _input_intervals; - std::vector _timeline; + std::vector _timeline; microsec _visibility_offset; sf::Music _music;