Implement PrecisionEvaluator for evaluating player input
This commit is contained in:
		
							parent
							
								
									76a69b534d
								
							
						
					
					
						commit
						89e9002b5e
					
				
							
								
								
									
										19
									
								
								include/game.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								include/game.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #ifndef GAME_H | ||||||
|  | #define GAME_H | ||||||
|  | 
 | ||||||
|  | #include <SFML/Graphics/RenderWindow.hpp> | ||||||
|  | #include <SFML/Window/Event.hpp> | ||||||
|  | 
 | ||||||
|  | class Game | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     virtual ~Game() = default; | ||||||
|  | 
 | ||||||
|  |     virtual void run() = 0; | ||||||
|  | 
 | ||||||
|  |     virtual void input(const sf::Event& event) = 0; | ||||||
|  |     virtual void update() = 0; | ||||||
|  |     virtual void draw(const sf::RenderWindow& window) const = 0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // GAME_H
 | ||||||
| @ -1,29 +0,0 @@ | |||||||
| #ifndef PRECISIONEVALUATOR_H |  | ||||||
| #define PRECISIONEVALUATOR_H |  | ||||||
| 
 |  | ||||||
| #include <SFML/System/Clock.hpp> |  | ||||||
| 
 |  | ||||||
| using microsec = sf::Int64; |  | ||||||
| 
 |  | ||||||
| template<typename GRADE> |  | ||||||
| class PrecisionEvaluator |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| 
 |  | ||||||
|     PrecisionEvaluator(microsec offset, microsec life_span_offset); |  | ||||||
| 
 |  | ||||||
|     microsec offset() const noexcept; |  | ||||||
|     bool isActive(microsec music_play_offset) const noexcept; |  | ||||||
|     GRADE calculatePrecision(microsec odds) const; |  | ||||||
| 
 |  | ||||||
|     static void resetPrecisionQualifier(microsec qualifier = 500000); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     microsec _offset; |  | ||||||
|     microsec _start_handling_offset; |  | ||||||
|     microsec _end_handling_offset; |  | ||||||
| 
 |  | ||||||
|     static microsec _precision_qualifier; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| #endif // PRECISIONEVALUATOR_H
 |  | ||||||
							
								
								
									
										66
									
								
								include/precisionevaluator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								include/precisionevaluator.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | |||||||
|  | #ifndef PRECISIONEVALUATOR_H | ||||||
|  | #define PRECISIONEVALUATOR_H | ||||||
|  | 
 | ||||||
|  | #include <numeric> | ||||||
|  | #include <type_traits> | ||||||
|  | #include <vector> | ||||||
|  | #include <cmath> | ||||||
|  | 
 | ||||||
|  | #include <SFML/System/Clock.hpp> | ||||||
|  | 
 | ||||||
|  | using microsec = sf::Int64; | ||||||
|  | 
 | ||||||
|  | template<typename GRADE, typename = std::enable_if_t<std::is_enum<GRADE>::value>> | ||||||
|  | class PrecisionEvaluator | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     PrecisionEvaluator(std::vector<microsec>&& intervals, microsec offset) : | ||||||
|  |         _offset(offset), | ||||||
|  |         _intervals(std::move(intervals)) | ||||||
|  |     { | ||||||
|  |         microsec&& handling_offset = std::accumulate(intervals.begin(), intervals.end(), 0); | ||||||
|  |         _start_handling_offset = _offset - handling_offset; | ||||||
|  |         _end_handling_offset = _offset + handling_offset; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline microsec offset() const noexcept | ||||||
|  |     { | ||||||
|  |         return _offset; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline bool isActive(microsec music_play_offset) const noexcept | ||||||
|  |     { | ||||||
|  |         return music_play_offset > _start_handling_offset | ||||||
|  |             && music_play_offset < _end_handling_offset; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline GRADE calculatePrecision(microsec odds) const | ||||||
|  |     { | ||||||
|  |         microsec shift_from_perfect = std::abs(odds - offset()); | ||||||
|  | 
 | ||||||
|  |         std::size_t raw_grade; | ||||||
|  |         for (raw_grade = 0; raw_grade < _intervals.size(); ++raw_grade) | ||||||
|  |         { | ||||||
|  |             if (shift_from_perfect <= _intervals[raw_grade]) | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return static_cast<GRADE>(raw_grade); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     microsec _offset; | ||||||
|  |     microsec _start_handling_offset; | ||||||
|  |     microsec _end_handling_offset; | ||||||
|  | 
 | ||||||
|  |     /* Amount of values in enum instanced as GRADES
 | ||||||
|  |      * represents capacity of _intervals. | ||||||
|  |      * So, for each V value in GRADES enum, _intervals[V] | ||||||
|  |      * should return time shift from V - 1. | ||||||
|  |      * V0 is PERFECT SCORE and the last V represents the worst | ||||||
|  |      * grades which is death of note by expiration */ | ||||||
|  | 
 | ||||||
|  |     std::vector<microsec> _intervals; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // PRECISIONEVALUATOR_H
 | ||||||
| @ -173,9 +173,5 @@ void Application::update() | |||||||
| 
 | 
 | ||||||
| void Application::draw() | void Application::draw() | ||||||
| { | { | ||||||
|     _game_window.clear(); | 
 | ||||||
|     _game_window.draw(*_timeline); |  | ||||||
|     _game_window.draw(_debug); |  | ||||||
|     _game_window.draw(_grade); |  | ||||||
|     _game_window.display(); |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								src/classicgame/classicgame.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/classicgame/classicgame.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | #include "classicgame.h" | ||||||
|  | 
 | ||||||
|  | ClassicGame::ClassicGame() | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								src/classicgame/classicgame.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/classicgame/classicgame.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | #ifndef CLASSICGAME_H | ||||||
|  | #define CLASSICGAME_H | ||||||
|  | 
 | ||||||
|  | #include "game.h" | ||||||
|  | 
 | ||||||
|  | class ClassicGame : public Game | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     explicit ClassicGame(); | ||||||
|  |     virtual ~ClassicGame() override; | ||||||
|  | 
 | ||||||
|  |     virtual void run() override; | ||||||
|  | 
 | ||||||
|  |     virtual void input(const sf::Event& event) override; | ||||||
|  |     virtual void update() override; | ||||||
|  |     virtual void draw(const sf::RenderWindow& window) const override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // CLASSICGAME_H
 | ||||||
							
								
								
									
										80
									
								
								src/note.cpp
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								src/note.cpp
									
									
									
									
									
								
							| @ -1,80 +0,0 @@ | |||||||
| #include "note.h" |  | ||||||
| #include <iostream> |  | ||||||
| #include <cmath> |  | ||||||
| 
 |  | ||||||
| Note::Note(microsec offset, microsec life_span_offset, Note::Arrow type) : |  | ||||||
|     _offset(offset), |  | ||||||
|     _start_handling_offset(_offset - life_span_offset), |  | ||||||
|     _end_handling_offset(_offset + life_span_offset), |  | ||||||
|     _type(type) |  | ||||||
| {} |  | ||||||
| 
 |  | ||||||
| void Note::setPosition(coordinates position) |  | ||||||
| { |  | ||||||
|     _position = position; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| coordinates Note::position() const noexcept |  | ||||||
| { |  | ||||||
|     return _position; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| microsec Note::offset() const noexcept |  | ||||||
| { |  | ||||||
|     return _offset; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| NoteGrade Note::onTap(Arrow arrow_type, microsec tap_time_stamp) |  | ||||||
| { |  | ||||||
|     if (arrow_type != _type) |  | ||||||
|         return {0, NoteGrade::Rating::WRONG}; |  | ||||||
| 
 |  | ||||||
|     microsec odds = std::abs(tap_time_stamp - _offset); |  | ||||||
|     return calculatePrecision(odds); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| NoteGrade Note::calculatePrecision(microsec odds) const |  | ||||||
| { |  | ||||||
|     NoteGrade ret(0, NoteGrade::Rating::BAD); |  | ||||||
| 
 |  | ||||||
|     if (odds < _precision_qualifier) |  | ||||||
|     { |  | ||||||
|         ret = {50, NoteGrade::Rating::GREAT}; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool Note::isActive(microsec music_play_offset) const noexcept |  | ||||||
| { |  | ||||||
|     return music_play_offset > _start_handling_offset |  | ||||||
|         && music_play_offset < _end_handling_offset; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Note::resetPrecisionQualifier(microsec qualifier) |  | ||||||
| { |  | ||||||
|     _precision_qualifier = qualifier; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Note::resetSprite(const std::shared_ptr<Sprite> &sprite) noexcept |  | ||||||
| { |  | ||||||
|     if (_sprite) |  | ||||||
|         _sprite->setAttachment(false); |  | ||||||
| 
 |  | ||||||
|     _sprite = sprite; |  | ||||||
| 
 |  | ||||||
|     if (_sprite) |  | ||||||
|         _sprite->setAttachment(true); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Note::Arrow Note::type() const noexcept |  | ||||||
| { |  | ||||||
|     return _type; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Note::draw(sf::RenderTarget &target, sf::RenderStates states) const |  | ||||||
| { |  | ||||||
|     target.draw(*_sprite, states); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| microsec Note::_precision_qualifier = 500000; // Default initialization as 0.5 second.
 |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user