Improve work with timeline
This commit is contained in:
		
							parent
							
								
									f66951bcec
								
							
						
					
					
						commit
						e5969d1484
					
				| @ -1,7 +1,6 @@ | |||||||
| #ifndef APPLICATION_H | #ifndef APPLICATION_H | ||||||
| #define APPLICATION_H | #define APPLICATION_H | ||||||
| 
 | 
 | ||||||
| #include <SFML/Audio/Music.hpp> |  | ||||||
| #include <SFML/System/Clock.hpp> | #include <SFML/System/Clock.hpp> | ||||||
| #include <SFML/Window/Keyboard.hpp> | #include <SFML/Window/Keyboard.hpp> | ||||||
| 
 | 
 | ||||||
| @ -21,7 +20,6 @@ public: | |||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     sf::RenderWindow _game_window; |     sf::RenderWindow _game_window; | ||||||
|     sf::Music _music; |  | ||||||
| 
 | 
 | ||||||
|     sf::Font _font; |     sf::Font _font; | ||||||
|     sf::Text _grade; |     sf::Text _grade; | ||||||
|  | |||||||
| @ -12,6 +12,13 @@ public: | |||||||
|         _perfect_offset(perfect_offset) {} |         _perfect_offset(perfect_offset) {} | ||||||
|     virtual ~Note() = 0; |     virtual ~Note() = 0; | ||||||
| 
 | 
 | ||||||
|  |     virtual bool isActive(microsec music_offset) const = 0; | ||||||
|  | 
 | ||||||
|  |     virtual microsec offset() const | ||||||
|  |     { | ||||||
|  |         return _perfect_offset; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| protected: | protected: | ||||||
|     microsec _perfect_offset; |     microsec _perfect_offset; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -11,9 +11,11 @@ class Timeline | |||||||
| public: | public: | ||||||
|     virtual ~Timeline() = default; |     virtual ~Timeline() = default; | ||||||
| 
 | 
 | ||||||
|     virtual void update(const microsec& music_offset) = 0; |     virtual void update() = 0; | ||||||
|     virtual void init() = 0; |     virtual void init() = 0; | ||||||
|     virtual void clear() = 0; |     virtual void clear() = 0; | ||||||
|  | 
 | ||||||
|  |     virtual microsec currentMusicOffset() const = 0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif // TIMELINE_H
 | #endif // TIMELINE_H
 | ||||||
|  | |||||||
| @ -20,12 +20,6 @@ Application::Application() : | |||||||
| 
 | 
 | ||||||
| void Application::run() | void Application::run() | ||||||
| { | { | ||||||
|     std::string song_filename = "/home/naiji/METEOR.flac"; |  | ||||||
| 
 |  | ||||||
|     _music.openFromFile(song_filename); |  | ||||||
|     _music.play(); |  | ||||||
|     _music.setVolume(30); |  | ||||||
| 
 |  | ||||||
|     _game_window.display(); |     _game_window.display(); | ||||||
| 
 | 
 | ||||||
|     startGameLoop(); |     startGameLoop(); | ||||||
| @ -63,10 +57,10 @@ void Application::input() | |||||||
| 
 | 
 | ||||||
| void Application::update() | void Application::update() | ||||||
| { | { | ||||||
| 
 |     _game->update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Application::draw() | void Application::draw() | ||||||
| { | { | ||||||
| 
 | //  _game->draw();
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #include "classicgame.h" | #include "classicgame.h" | ||||||
| #include "classicinputtype.h" | #include "classicinputtype.h" | ||||||
| #include "classictimeline.h" | #include "classictimeline.h" | ||||||
|  | #include "classicnote.h" | ||||||
| 
 | 
 | ||||||
| ClassicGame::ClassicGame() : | ClassicGame::ClassicGame() : | ||||||
|     _timeline(std::make_unique<ClassicTimeline>()) |     _timeline(std::make_unique<ClassicTimeline>()) | ||||||
| @ -52,7 +53,7 @@ void ClassicGame::run() | |||||||
| void ClassicGame::input(const sf::Event& event) | void ClassicGame::input(const sf::Event& event) | ||||||
| { | { | ||||||
|     Action new_action = Action::NONE; |     Action new_action = Action::NONE; | ||||||
|     microsec timestamp = 0; /* 0 is temp. get from timeline */ |     microsec timestamp = _timeline->currentMusicOffset(); | ||||||
| 
 | 
 | ||||||
|     switch (event.type) |     switch (event.type) | ||||||
|     { |     { | ||||||
| @ -72,9 +73,10 @@ void ClassicGame::input(const sf::Event& event) | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ClassicInputType input(timestamp, new_action); |     auto note = _timeline->getActiveNote(); | ||||||
|     auto note = _timeline->getActiveNote(timestamp); | 
 | ||||||
|     note-> |     if (!_timeline->isExpired(note)) | ||||||
|  |         (*note)->input(ClassicInputType(timestamp, new_action)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Action ClassicGame::getActionKeyPressed(Button button) const | Action ClassicGame::getActionKeyPressed(Button button) const | ||||||
| @ -89,7 +91,8 @@ Action ClassicGame::getActionKeyReleased(Button button) const | |||||||
| 
 | 
 | ||||||
| void ClassicGame::update() | void ClassicGame::update() | ||||||
| { | { | ||||||
| 
 |     _timeline->update(); | ||||||
|  |     _timeline->fetchVisibleNotes(_view_manager); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ClassicGame::draw(const sf::RenderWindow& window) const | void ClassicGame::draw(const sf::RenderWindow& window) const | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ | |||||||
| #include "classicactions.h" | #include "classicactions.h" | ||||||
| 
 | 
 | ||||||
| class ClassicTimeline; | class ClassicTimeline; | ||||||
|  | class ClassicViewManager; | ||||||
| 
 | 
 | ||||||
| class ClassicGame final : public Game | class ClassicGame final : public Game | ||||||
| { | { | ||||||
| @ -29,7 +30,7 @@ private: | |||||||
|     Action getActionKeyReleased(Button button) const; |     Action getActionKeyReleased(Button button) const; | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<ClassicTimeline> _timeline; |     std::unique_ptr<ClassicTimeline> _timeline; | ||||||
| 
 |     std::unique_ptr<ClassicViewManager> _view_manager; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif // CLASSICGAME_H
 | #endif // CLASSICGAME_H
 | ||||||
|  | |||||||
| @ -1,8 +1,22 @@ | |||||||
| #include "classicnote.h" | #include "classicnote.h" | ||||||
| 
 | 
 | ||||||
| ClassicNote::ClassicNote(const std::vector<microsec>& intervals, microsec perfect_offset) : | ClassicNote::ClassicNote(const std::vector<microsec>& intervals, microsec perfect_offset, Action action) : | ||||||
|     Note(perfect_offset), |     Note(perfect_offset), | ||||||
|     _evaluator(intervals, _perfect_offset) |     _evaluator(intervals, _perfect_offset), | ||||||
| { |     _action(action) | ||||||
|  | {} | ||||||
| 
 | 
 | ||||||
|  | bool ClassicNote::isActive(microsec music_offset) const | ||||||
|  | { | ||||||
|  |     return _evaluator.isActive(music_offset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ClassicNote::GRADE ClassicNote::input(ClassicInputType&& input_data) | ||||||
|  | { | ||||||
|  |     if (input_data == _action) | ||||||
|  |     { | ||||||
|  |         return _evaluator.calculatePrecision(input_data.timestamp()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return ClassicNote::GRADE::BAD; | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| #include "note.h" | #include "note.h" | ||||||
| #include "precisionevaluator.h" | #include "precisionevaluator.h" | ||||||
|  | #include "classicinputtype.h" | ||||||
| 
 | 
 | ||||||
| class ClassicNote : public Note | class ClassicNote : public Note | ||||||
| { | { | ||||||
| @ -14,9 +15,13 @@ public: | |||||||
|             BAD |             BAD | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     explicit ClassicNote(const std::vector<microsec>& intervals, microsec perfect_offset); |     explicit ClassicNote(const std::vector<microsec>& intervals, microsec perfect_offset, Action action); | ||||||
|     virtual ~ClassicNote() = default; |     virtual ~ClassicNote() = default; | ||||||
|  |     virtual bool isActive(microsec music_offset) const override; | ||||||
|  | 
 | ||||||
|  |     GRADE input(ClassicInputType&& input_data); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     PrecisionEvaluator<GRADE> _evaluator; |     PrecisionEvaluator<GRADE> _evaluator; | ||||||
|  |     Action _action; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| #include <iostream> | #include <iostream> | ||||||
| #include "classicactions.h" | #include "classicactions.h" | ||||||
| #include "classictimeline.h" | #include "classictimeline.h" | ||||||
| #include "note.h" | #include "classicnote.h" | ||||||
| 
 | 
 | ||||||
| ClassicTimeline::ClassicTimeline() | ClassicTimeline::ClassicTimeline() | ||||||
| { | { | ||||||
| @ -9,6 +9,12 @@ ClassicTimeline::ClassicTimeline() | |||||||
|     // Length is 1:14
 |     // Length is 1:14
 | ||||||
|     // I calculated that the time between beats is about 1412162 microseconds
 |     // I calculated that the time between beats is about 1412162 microseconds
 | ||||||
| 
 | 
 | ||||||
|  |     std::string song_filename = "/home/naiji/METEOR.flac"; | ||||||
|  | 
 | ||||||
|  |     _music.openFromFile(song_filename); | ||||||
|  |     _music.play(); | ||||||
|  |     _music.setVolume(30); | ||||||
|  | 
 | ||||||
|     _timeline.reserve(1000); |     _timeline.reserve(1000); | ||||||
| 
 | 
 | ||||||
|     microsec starting_beat_offset = 372162; |     microsec starting_beat_offset = 372162; | ||||||
| @ -19,91 +25,100 @@ ClassicTimeline::ClassicTimeline() | |||||||
|     microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); |     microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); | ||||||
|     _visibility_offset = note_input_offset * 12; |     _visibility_offset = note_input_offset * 12; | ||||||
| 
 | 
 | ||||||
|     _timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Button::DOWN)); |     _timeline.emplace_back(new ClassicNote({note_input_offset}, bpm_iterator, Action::PRESS_DOWN)); | ||||||
|     bpm_iterator += interval; |     bpm_iterator += interval; | ||||||
| 
 | 
 | ||||||
|     _timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Button::LEFT)); |     _timeline.emplace_back(new ClassicNote({note_input_offset}, bpm_iterator, Action::PRESS_LEFT)); | ||||||
|     bpm_iterator += interval; |     bpm_iterator += interval; | ||||||
| 
 | 
 | ||||||
|     _timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Button::LEFT)); |     _timeline.emplace_back(new ClassicNote({note_input_offset}, bpm_iterator, Action::PRESS_LEFT)); | ||||||
|     bpm_iterator += interval; |     bpm_iterator += interval; | ||||||
| 
 | 
 | ||||||
|     while (bpm_iterator < bpm_end) |     while (bpm_iterator < bpm_end) | ||||||
|     { |     { | ||||||
|         _timeline.emplace_back(new Note(bpm_iterator, note_input_offset)); |         _timeline.emplace_back(new ClassicNote({note_input_offset}, bpm_iterator, Action::PRESS_UP)); | ||||||
|         bpm_iterator += interval; |         bpm_iterator += interval; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     _active_note = nullptr; |     expire(_active_note); | ||||||
|     _last_visible_note = _timeline.end(); |  | ||||||
|     _top_note = _timeline.begin(); |     _top_note = _timeline.begin(); | ||||||
| 
 |  | ||||||
|     _last_visible_note = _top_note; |     _last_visible_note = _top_note; | ||||||
|     _view_manager->initNoteGraphics(*_top_note); |  | ||||||
|     prepareNotesToDraw(0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Timeline::prepareNotesToDraw(const microsec &music_offset) | ClassicTimeline::~ClassicTimeline() | ||||||
| { |  | ||||||
|     auto note_iterator = _top_note; |  | ||||||
| 
 |  | ||||||
|     while (((*note_iterator)->offset() - _visibility_offset) <= music_offset) |  | ||||||
|     { |  | ||||||
|         ++note_iterator; |  | ||||||
|         if (note_iterator > _last_visible_note) |  | ||||||
|             _view_manager->initNoteGraphics((*note_iterator)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     _last_visible_note = note_iterator; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Timeline::~Timeline() |  | ||||||
| { | { | ||||||
|     clear(); |     clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Timeline::clear() | void ClassicTimeline::clear() | ||||||
| { | { | ||||||
|     for (auto note : _timeline) |     for (auto note : _timeline) | ||||||
|         delete note; |         delete note; | ||||||
| 
 | 
 | ||||||
|     _timeline.clear(); |     _timeline.clear(); | ||||||
|     _top_note = _timeline.end(); |     expire(_top_note); | ||||||
|     _last_visible_note = _timeline.end(); |     expire(_last_visible_note); | ||||||
|     _active_note = nullptr; |     expire(_active_note); | ||||||
| 
 |  | ||||||
|     Note::resetPrecisionQualifier(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Timeline::update(const microsec &music_offset) | void ClassicTimeline::update() | ||||||
| { | { | ||||||
|     checkCurrentActiveNote(music_offset); |     const auto& offset = currentMusicOffset(); | ||||||
|     checkForNextActiveNote(music_offset); |     std::cout << "Upadting at: " << offset << '\n'; | ||||||
|     prepareNotesToDraw(music_offset); |     checkCurrentActiveNote(offset); | ||||||
|  |     checkForNextActiveNote(offset); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Timeline::checkCurrentActiveNote(const microsec &music_offset) | void ClassicTimeline::checkCurrentActiveNote(const microsec &music_offset) | ||||||
| { | { | ||||||
|     if (_active_note && !_active_note->isActive(music_offset)) |     if (!isExpired(_active_note) && !(*_active_note)->isActive(music_offset)) | ||||||
|     { |     { | ||||||
|         _active_note = nullptr; |         expire(_active_note); | ||||||
|         (*_top_note)->resetSprite(); |  | ||||||
|         ++_top_note; |         ++_top_note; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Timeline::checkForNextActiveNote(const microsec &music_offset) | void ClassicTimeline::checkForNextActiveNote(const microsec &music_offset) | ||||||
| { | { | ||||||
|     if (!_active_note && (*_top_note)->isActive(music_offset)) |     if (isExpired(_active_note) && (*_top_note)->isActive(music_offset)) | ||||||
|     { |     { | ||||||
|         std::cout << "New active note: " << music_offset << '\n'; |         std::cout << "New active note: " << music_offset << '\n'; | ||||||
|         _active_note = *_top_note; |         _active_note = _top_note; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Note* Timeline::fetchActiveNote(const microsec &music_offset) noexcept | ClassicTimeline::Iterator ClassicTimeline::getActiveNote() noexcept | ||||||
| { | { | ||||||
|     std::cout << "Clicked at: " << music_offset << '\n'; |     update(); | ||||||
|     update(music_offset); |  | ||||||
|     return _active_note; |     return _active_note; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool ClassicTimeline::isExpired(const Iterator &iterator) | ||||||
|  | { | ||||||
|  |     return iterator == _timeline.end(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ClassicTimeline::expire(Iterator &iterator) | ||||||
|  | { | ||||||
|  |     iterator = _timeline.end(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | microsec ClassicTimeline::currentMusicOffset() const | ||||||
|  | { | ||||||
|  |     return _music.getPlayingOffset().asMicroseconds(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ClassicTimeline::fetchVisibleNotes(const std::unique_ptr<ClassicViewManager>& view_manager) | ||||||
|  | { | ||||||
|  |     Iterator note_iterator = _top_note; | ||||||
|  |     auto music_offset = currentMusicOffset(); | ||||||
|  | 
 | ||||||
|  |     while (((*note_iterator)->offset() - _visibility_offset) <= music_offset) | ||||||
|  |     { | ||||||
|  |         ++note_iterator; | ||||||
|  |         if (note_iterator > _last_visible_note) | ||||||
|  |             (void) view_manager;//_view_manager->initNoteGraphics((*note_iterator));
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     _last_visible_note = note_iterator; | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,31 +1,45 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <vector> | #include <vector> | ||||||
|  | #include <memory> | ||||||
| #include "timeline.h" | #include "timeline.h" | ||||||
|  | #include <SFML/Audio/Music.hpp> | ||||||
| 
 | 
 | ||||||
| class Note; | class ClassicNote; | ||||||
|  | class ClassicViewManager; | ||||||
| 
 | 
 | ||||||
| class ClassicTimeline : public Timeline | class ClassicTimeline : public Timeline | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     explicit ClassicTimeline(); |     explicit ClassicTimeline(); | ||||||
|     virtual void update(const microsec& music_offset) override; |     virtual ~ClassicTimeline(); | ||||||
|  |     virtual void update() override; | ||||||
|     virtual void init() override; |     virtual void init() override; | ||||||
|     virtual void clear() override; |     virtual void clear() override; | ||||||
| 
 | 
 | ||||||
|     Note *getActiveNote(const microsec &music_offset) noexcept; |     virtual microsec currentMusicOffset() const override; | ||||||
|  | 
 | ||||||
|  |     void fetchVisibleNotes(const std::unique_ptr<ClassicViewManager>& view_manager); | ||||||
|  | 
 | ||||||
|  |     using Iterator = std::vector<ClassicNote*>::const_iterator; | ||||||
|  | 
 | ||||||
|  |     Iterator getActiveNote() noexcept; | ||||||
|  | 
 | ||||||
|  |     bool isExpired(const Iterator& iterator); | ||||||
|  |     void expire(Iterator& iterator); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     std::vector<Note*> _timeline; |     std::vector<ClassicNote*> _timeline; | ||||||
|     std::vector<Note*>::const_iterator _top_note; |     Iterator _top_note; | ||||||
|     Note* _active_note; |     Iterator _active_note; | ||||||
|  |     Iterator _last_visible_note; | ||||||
| 
 | 
 | ||||||
|     std::vector<Note*>::const_iterator _last_visible_note; |  | ||||||
|     microsec _visibility_offset; |     microsec _visibility_offset; | ||||||
| 
 | 
 | ||||||
|  |     sf::Music _music; | ||||||
|  | 
 | ||||||
|     void checkCurrentActiveNote(const microsec &music_offset); |     void checkCurrentActiveNote(const microsec &music_offset); | ||||||
|     void checkForNextActiveNote(const microsec &music_offset); |     void checkForNextActiveNote(const microsec &music_offset); | ||||||
|     void prepareNotesToDraw(const microsec &music_offset); |  | ||||||
| 
 | 
 | ||||||
|     /* Difference between top and active note is that
 |     /* Difference between top and active note is that
 | ||||||
|      * top note is the note handling input right now |      * top note is the note handling input right now | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user