Implement more precise active note detection
This commit is contained in:
		
							parent
							
								
									192e371d2f
								
							
						
					
					
						commit
						ad1b31c95c
					
				| @ -4,7 +4,6 @@ | ||||
| #include <SFML/System/Clock.hpp> | ||||
| #include <SFML/Window/Keyboard.hpp> | ||||
| 
 | ||||
| #include "debughelper.h" | ||||
| #include "timeline.h" | ||||
| #include "note.h" | ||||
| #include "game.h" | ||||
| @ -13,7 +12,6 @@ class Application | ||||
| { | ||||
| public: | ||||
|     Application(); | ||||
|    ~Application(); | ||||
|     void run(); | ||||
|     void input(); | ||||
|     void update(); | ||||
| @ -21,13 +19,7 @@ public: | ||||
| 
 | ||||
| private: | ||||
|     sf::RenderWindow _game_window; | ||||
| 
 | ||||
|     sf::Font _font; | ||||
|     sf::Text _grade; | ||||
| 
 | ||||
|     std::unique_ptr<Timeline> _timeline; | ||||
|     DebugHelper _debug; | ||||
| 
 | ||||
|     std::unique_ptr<Game> _game; | ||||
| 
 | ||||
|     void exec(); | ||||
|  | ||||
| @ -1,47 +0,0 @@ | ||||
| #ifndef DEBUGHELPER_H | ||||
| #define DEBUGHELPER_H | ||||
| 
 | ||||
| #include <SFML/Graphics/RenderWindow.hpp> | ||||
| #include <SFML/Graphics/RectangleShape.hpp> | ||||
| #include <SFML/Graphics/Font.hpp> | ||||
| #include <SFML/Graphics/Text.hpp> | ||||
| 
 | ||||
| using microsec = sf::Int64; | ||||
| 
 | ||||
| class DebugHelper : public sf::Drawable | ||||
| { | ||||
| public: | ||||
|     DebugHelper(bool init = true); | ||||
| 
 | ||||
|     void toggle(); | ||||
|     void update(const microsec& microseconds); | ||||
|     virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; | ||||
| 
 | ||||
|     void spawnGreenPulse(); | ||||
|     void spawnRedPulse(); | ||||
|     void spawnBluePulse(); | ||||
| 
 | ||||
| private: | ||||
|     bool _toggled; | ||||
|     sf::Font _font; | ||||
|     sf::Text _time_print; | ||||
| 
 | ||||
|     class Pulse : public sf::Drawable | ||||
|     { | ||||
|     public: | ||||
|         Pulse(sf::Vector2f position, sf::Color fill_color); | ||||
|         void appear(); | ||||
|         void fade(); | ||||
| 
 | ||||
|         virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; | ||||
| 
 | ||||
|     private: | ||||
|         sf::RectangleShape _pulse_shape; | ||||
|     }; | ||||
| 
 | ||||
|     Pulse _red_pulse; | ||||
|     Pulse _green_pulse; | ||||
|     Pulse _blue_pulse; | ||||
| }; | ||||
| 
 | ||||
| #endif // DEBUGHELPER_H
 | ||||
| @ -7,18 +7,7 @@ const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 60.f); | ||||
| 
 | ||||
| Application::Application() : | ||||
|     _game_window({1280, 720}, "Test"), | ||||
|     _debug(true), | ||||
|     _game(std::make_unique<ClassicGame>()) | ||||
| { | ||||
|     _font.loadFromFile("/usr/share/qtcreator/fonts/SourceCodePro-Regular.ttf"); | ||||
|     _grade.setFont(_font); | ||||
|     _grade.setPosition(160, 160); | ||||
|     _grade.setFillColor(sf::Color(255, 0, 0)); | ||||
|     _grade.setCharacterSize(35); | ||||
|     _grade.setString("NOT INIT"); | ||||
| } | ||||
| 
 | ||||
| Application::~Application() | ||||
| {} | ||||
| 
 | ||||
| void Application::run() | ||||
|  | ||||
| @ -8,7 +8,6 @@ ClassicGame::ClassicGame() : | ||||
|     _timeline(std::make_unique<ClassicTimeline>()), | ||||
|     _view_manager(std::make_unique<ClassicViewManager>()) | ||||
| { | ||||
|     _font.loadFromFile("VeraMono.ttf"); | ||||
|     _keys_to_buttons = | ||||
|     { | ||||
|         {sf::Keyboard::Up, Button::UP},      // Load from settings
 | ||||
| @ -83,25 +82,9 @@ void ClassicGame::input(const sf::Event& event) | ||||
| 
 | ||||
|     auto note = _timeline->getActiveNote(); | ||||
| 
 | ||||
|     if (!_timeline->isExpired(note) || (*note)->state() != ClassicNote::State::DEAD) | ||||
|     if (!_timeline->isExpired(note) && (*note)->state() == ClassicNote::State::FLYING) | ||||
|     { | ||||
|         auto grade = (*note)->input(ClassicInputType(timestamp, new_action)); | ||||
| 
 | ||||
|         sf::Text new_grade; | ||||
|         new_grade.setFillColor(sf::Color::White); | ||||
|         new_grade.setPosition((*note)->getCoordinates().x, (*note)->getCoordinates().y - 40); | ||||
|         switch (grade) | ||||
|         { | ||||
|         case ClassicNote::Grade::PERFECT: | ||||
|             new_grade.setString("PERFECT"); break; | ||||
|         case ClassicNote::Grade::GOOD: | ||||
|             new_grade.setString("GOOD"); break; | ||||
|         case ClassicNote::Grade::BAD: | ||||
|             new_grade.setString("BAD"); break; | ||||
|         } | ||||
| 
 | ||||
|         new_grade.setFont(_font); | ||||
|         _grades.emplace_back(new_grade); | ||||
|         (*note)->input(ClassicInputType(timestamp, new_action)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -119,24 +102,9 @@ void ClassicGame::update() | ||||
| { | ||||
|     _timeline->update(); | ||||
|     _timeline->fetchVisibleNotes(_view_manager); | ||||
| 
 | ||||
|     for (auto& grade : _grades) | ||||
|     { | ||||
|         if (grade.getFillColor().a > 20) | ||||
|         { | ||||
|             grade.setFillColor(sf::Color(255, 255, 255, grade.getFillColor().a - 20)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     _grades.remove_if([](const auto& grade) { return grade.getFillColor().a <= 20; }); | ||||
| } | ||||
| 
 | ||||
| void ClassicGame::draw(sf::RenderWindow& window) const | ||||
| { | ||||
|     _timeline->drawVisibleNotes(window); | ||||
| 
 | ||||
|     for (auto& grade : _grades) | ||||
|     { | ||||
|         window.draw(grade); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -3,7 +3,6 @@ | ||||
| 
 | ||||
| #include <map> | ||||
| #include <list> | ||||
| #include <SFML/Graphics/Text.hpp> | ||||
| #include "game.h" | ||||
| #include "classicactions.h" | ||||
| 
 | ||||
| @ -32,9 +31,6 @@ private: | ||||
| 
 | ||||
|     std::unique_ptr<ClassicTimeline> _timeline; | ||||
|     std::unique_ptr<ClassicViewManager> _view_manager; | ||||
| 
 | ||||
|     sf::Font _font; | ||||
|     std::list<sf::Text> _grades; | ||||
| }; | ||||
| 
 | ||||
| #endif // CLASSICGAME_H
 | ||||
|  | ||||
| @ -34,7 +34,11 @@ void ClassicNote::update(const microsec& music_offset) | ||||
|     int xb = getPt( 1280./2. , _coordinates.x , i ); | ||||
|     int yb = getPt( 720./2. , _coordinates.y , i ); | ||||
| 
 | ||||
|     _sprite->setTrailCoordinates(getPt( xa , xb , i ), getPt( ya , yb , i )); | ||||
|     _sprite->update(getPt( xa , xb , i ), getPt( ya , yb , i )); | ||||
| 
 | ||||
|     if (_state == State::DYING) | ||||
|         if (_sprite->isDead()) | ||||
|             _state = State::DEAD; | ||||
| } | ||||
| 
 | ||||
| void ClassicNote::draw(sf::RenderTarget& target, sf::RenderStates states) const | ||||
| @ -52,7 +56,8 @@ auto ClassicNote::input(ClassicInputType&& input_data) -> Grade | ||||
|     } | ||||
| 
 | ||||
|     std::cout << "User input: " << static_cast<int>(grade) << "\n"; | ||||
|     _state = State::DEAD; | ||||
|     _state = State::DYING; | ||||
|     _sprite->showGrade(); | ||||
|     return grade; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,24 +1,53 @@ | ||||
| #include "classicsprite.h" | ||||
| #include <SFML/Graphics/RenderTarget.hpp> | ||||
| 
 | ||||
| ClassicSprite::ClassicSprite(const sf::RectangleShape& shape) : | ||||
| ClassicSprite::ClassicSprite(const sf::RectangleShape& shape, const sf::Font& font) : | ||||
|     _shape(shape), | ||||
|     _trail(shape) | ||||
| {} | ||||
|     _trail(shape), | ||||
|     _font(font) | ||||
| { | ||||
|     _grade_text.setFont(_font); | ||||
| } | ||||
| 
 | ||||
| void ClassicSprite::draw(sf::RenderTarget& target, sf::RenderStates states) const | ||||
| { | ||||
|     target.draw(_shape, states); | ||||
|     target.draw(_trail, states); | ||||
|     target.draw(_grade_text, states); | ||||
| } | ||||
| 
 | ||||
| void ClassicSprite::setCoordinates(float x, float y, float trail_x, float trail_y) noexcept | ||||
| { | ||||
|     _shape.setPosition(x, y); | ||||
|     _trail.setPosition(trail_x, trail_y); | ||||
|     _grade_text.setPosition(x + _shape.getSize().x/2, y + 10); | ||||
| } | ||||
| 
 | ||||
| void ClassicSprite::setTrailCoordinates(float trail_x, float trail_y) noexcept | ||||
| void ClassicSprite::update(float trail_x, float trail_y) noexcept | ||||
| { | ||||
|     _trail.setPosition(trail_x, trail_y); | ||||
|     fade(); | ||||
| } | ||||
| 
 | ||||
| void ClassicSprite::showGrade() | ||||
| { | ||||
|     _grade_text.setFillColor(sf::Color(255, 255, 255, 255)); | ||||
| } | ||||
| 
 | ||||
| void ClassicSprite::fade() | ||||
| { | ||||
|     auto fill_color = _grade_text.getFillColor(); | ||||
| 
 | ||||
|     if (fill_color.a == 0) | ||||
|         return; | ||||
| 
 | ||||
|     const auto new_alpha = fill_color.a - 55; | ||||
|     fill_color.a = new_alpha < 0 ? 0 : new_alpha; | ||||
| 
 | ||||
|     _grade_text.setFillColor(fill_color); | ||||
| } | ||||
| 
 | ||||
| bool ClassicSprite::isDead() const | ||||
| { | ||||
|     return _grade_text.getFillColor().a == 0; | ||||
| } | ||||
|  | ||||
| @ -2,17 +2,23 @@ | ||||
| 
 | ||||
| #include "sprite.h" | ||||
| #include "SFML/Graphics/RectangleShape.hpp" | ||||
| #include "SFML/Graphics/Text.hpp" | ||||
| 
 | ||||
| class ClassicSprite : public Sprite, public sf::Drawable | ||||
| { | ||||
| public: | ||||
|     ClassicSprite(const sf::RectangleShape& shape); | ||||
|     ClassicSprite(const sf::RectangleShape& shape, const sf::Font &font); | ||||
|     virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; | ||||
| 
 | ||||
|     void setCoordinates(float x, float y, float trail_x, float trail_y) noexcept; | ||||
|     void setTrailCoordinates(float trail_x, float trail_y) noexcept; | ||||
|     void update(float trail_x, float trail_y) noexcept; | ||||
|     void showGrade(); | ||||
|     void fade(); | ||||
|     bool isDead() const; | ||||
| 
 | ||||
| private: | ||||
|     sf::RectangleShape _shape; | ||||
|     sf::RectangleShape _trail; | ||||
|     sf::Text _grade_text; | ||||
|     sf::Font _font; | ||||
| }; | ||||
|  | ||||
| @ -79,7 +79,8 @@ void ClassicTimeline::update() | ||||
| 
 | ||||
| void ClassicTimeline::checkCurrentActiveNote(const microsec &music_offset) | ||||
| { | ||||
|     if (!isExpired(_active_note) && !(*_active_note)->isActive(music_offset)) | ||||
|     if (!isExpired(_active_note) | ||||
|     && ((!(*_active_note)->isActive(music_offset)) || (*_active_note)->state() == ClassicNote::State::DEAD)) | ||||
|     { | ||||
|         expire(_active_note); | ||||
|         ++_top_note; | ||||
| @ -124,7 +125,9 @@ void ClassicTimeline::discardExpiredNotes(const std::unique_ptr<ClassicViewManag | ||||
|     Iterator past_note = _top_note - 1; | ||||
|     std::shared_ptr<ClassicSprite> sprite = (*past_note)->sprite(); | ||||
|     while (sprite) | ||||
|     {                                               // CAREFULLY REWRITE
 | ||||
|     { | ||||
|         auto state = (*past_note)->state(); | ||||
|         if (state == ClassicNote::State::DEAD || state == ClassicNote::State::FLYING) | ||||
|             view_manager->resetNoteSprite(*past_note); | ||||
|         if (past_note == _timeline.begin()) | ||||
|             return; | ||||
| @ -154,12 +157,9 @@ void ClassicTimeline::fetchVisibleNotes(const std::unique_ptr<ClassicViewManager | ||||
|         } | ||||
| 
 | ||||
|         if (note->state() == ClassicNote::State::DEAD) | ||||
|         { | ||||
|             view_manager->resetNoteSprite(note); | ||||
|         } | ||||
|         else | ||||
|             note->update(music_offset); | ||||
| 
 | ||||
|         note->update(music_offset); | ||||
|         ++note_iterator; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -13,6 +13,8 @@ ClassicViewManager::ClassicViewManager() | ||||
|     { | ||||
|         reallocatePoll(kind_of_action); | ||||
|     } | ||||
| 
 | ||||
|     _font.loadFromFile("VeraMono.ttf"); | ||||
| } | ||||
| 
 | ||||
| void ClassicViewManager::reallocatePoll(Action kind_of_action) | ||||
| @ -50,7 +52,7 @@ std::shared_ptr<ClassicSprite> ClassicViewManager::createSprite(Action kind_of_a | ||||
|         sprite.setFillColor(sf::Color(255, 239, 0)); | ||||
|     } | ||||
| 
 | ||||
|     return std::make_shared<ClassicSprite>(sprite); | ||||
|     return std::make_shared<ClassicSprite>(sprite, _font); | ||||
| } | ||||
| 
 | ||||
| void ClassicViewManager::initNoteSprite(ClassicNote* note) | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| #include <memory> | ||||
| #include <stack> | ||||
| #include <map> | ||||
| #include <SFML/Graphics/Font.hpp> | ||||
| 
 | ||||
| class ClassicSprite; | ||||
| class ClassicNote; | ||||
| @ -25,6 +26,7 @@ private: | ||||
| 
 | ||||
|     using SpritePoll = std::stack<std::shared_ptr<ClassicSprite>>; | ||||
|     std::map<Action, SpritePoll> _sprite_dispatcher; | ||||
|     sf::Font _font; | ||||
| }; | ||||
| 
 | ||||
| #endif // CLASSICDIVAVIEWMANAGER_H
 | ||||
|  | ||||
| @ -1,89 +0,0 @@ | ||||
| #include "debughelper.h" | ||||
| 
 | ||||
| DebugHelper::DebugHelper(bool init) : | ||||
|     _toggled(init), | ||||
|     _red_pulse({0.f, 0.f}, sf::Color(255, 0, 0)), | ||||
|     _green_pulse({460.f, 0.f}, sf::Color(0, 255, 0)), | ||||
|     _blue_pulse({460.f, 360.f}, sf::Color(0, 100, 255)) | ||||
| { | ||||
|     _font.loadFromFile("/usr/share/qtcreator/fonts/SourceCodePro-Regular.ttf"); | ||||
| 
 | ||||
|     _time_print.setFont(_font); | ||||
|     _time_print.setPosition(60, 60); | ||||
|     _time_print.setFillColor(sf::Color(255, 255, 255)); | ||||
|     _time_print.setCharacterSize(25); | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::toggle() | ||||
| { | ||||
|     _toggled = !_toggled; | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::update(const microsec µseconds) | ||||
| { | ||||
|     _time_print.setString(std::to_string(microseconds)); | ||||
| 
 | ||||
|     _red_pulse.fade(); | ||||
|     _green_pulse.fade(); | ||||
|     _blue_pulse.fade(); | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::draw(sf::RenderTarget& target, sf::RenderStates states) const | ||||
| { | ||||
|     if (_toggled) | ||||
|     { | ||||
|         target.draw(_green_pulse, states); | ||||
|         target.draw(_red_pulse, states); | ||||
|         target.draw(_blue_pulse, states); | ||||
|         target.draw(_time_print, states); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::spawnGreenPulse() | ||||
| { | ||||
|     _green_pulse.appear(); | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::spawnRedPulse() | ||||
| { | ||||
|     _red_pulse.appear(); | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::spawnBluePulse() | ||||
| { | ||||
|     _blue_pulse.appear(); | ||||
| } | ||||
| 
 | ||||
| DebugHelper::Pulse::Pulse(sf::Vector2f position, sf::Color fill_color) | ||||
| { | ||||
|     _pulse_shape.setSize({480, 360}); | ||||
|     _pulse_shape.move(position.x, position.y); | ||||
| 
 | ||||
|     fill_color.a = 0; | ||||
|     _pulse_shape.setFillColor(fill_color); | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::Pulse::appear() | ||||
| { | ||||
|     auto fill_color = _pulse_shape.getFillColor(); | ||||
|     fill_color.a = 255; | ||||
|     _pulse_shape.setFillColor(fill_color); | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::Pulse::fade() | ||||
| { | ||||
|     auto fill_color = _pulse_shape.getFillColor(); | ||||
| 
 | ||||
|     if (fill_color.a == 0) | ||||
|         return; | ||||
| 
 | ||||
|     const auto new_alpha = fill_color.a - 25; | ||||
|     fill_color.a = new_alpha < 0 ? 0 : new_alpha; | ||||
| 
 | ||||
|     _pulse_shape.setFillColor(fill_color); | ||||
| } | ||||
| 
 | ||||
| void DebugHelper::Pulse::draw(sf::RenderTarget& target, sf::RenderStates states) const | ||||
| { | ||||
|     target.draw(_pulse_shape, states); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user