diff --git a/include/inputtype.h b/include/inputtype.h index bd4131f..916488b 100644 --- a/include/inputtype.h +++ b/include/inputtype.h @@ -1,10 +1,8 @@ #ifndef INPUTTYPE_H #define INPUTTYPE_H -#include #include - -using microsec = sf::Int64; +#include "mathutils.h" struct PlayerInput { diff --git a/include/mathutils.h b/include/mathutils.h new file mode 100644 index 0000000..9ea1b43 --- /dev/null +++ b/include/mathutils.h @@ -0,0 +1,38 @@ +#pragma once +#include + +using microsec = sf::Int64; + +struct Coordinates +{ + float x; + float y; + + constexpr inline Coordinates operator+(const Coordinates& right) const noexcept + { + return {right.x + x, right.y + y}; + } + + constexpr inline Coordinates operator-(const Coordinates& right) const noexcept + { + return {right.x - x, right.y - y}; + } + + inline void moveBy(float x, float y) noexcept + { + this->x += x; + this->y += y; + } + + inline void moveBy(const Coordinates& right) noexcept + { + this->x += right.x; + this->y += right.y; + } + + inline void scale(float factor) noexcept + { + x *= factor; + y *= factor; + } +}; diff --git a/include/note.h b/include/note.h index d5ac9d2..276b36f 100644 --- a/include/note.h +++ b/include/note.h @@ -1,13 +1,7 @@ #pragma once -#include -#include -#include - #include "inputtype.h" -using microsec = sf::Int64; - class Note { public: @@ -15,12 +9,13 @@ public: _perfect_offset(perfect_offset) {} virtual ~Note() = default; - virtual bool isActive(const microsec& music_offset) const = 0; + virtual bool isActive() const = 0; virtual void update(const microsec& music_offset) = 0; virtual void input(PlayerInput&& inputdata) = 0; virtual void draw() const = 0; virtual void putToGame(const microsec &offset) = 0; + virtual bool isInGame() const = 0; virtual bool isExpired() const = 0; microsec offset() const diff --git a/include/precisionevaluator.h b/include/precisionevaluator.h index e658a46..8388ce1 100644 --- a/include/precisionevaluator.h +++ b/include/precisionevaluator.h @@ -1,16 +1,13 @@ #ifndef PRECISIONEVALUATOR_H #define PRECISIONEVALUATOR_H +#include "mathutils.h" #include #include #include #include #include -#include - -using microsec = sf::Int64; - template::value>> class PrecisionEvaluator { diff --git a/include/timeline.h b/include/timeline.h index e8956c3..18d1606 100644 --- a/include/timeline.h +++ b/include/timeline.h @@ -1,11 +1,9 @@ #ifndef TIMELINE_H #define TIMELINE_H -#include -#include +#include "mathutils.h" #include - -using microsec = sf::Int64; +#include class Note; diff --git a/src/application.cpp b/src/application.cpp index 0519fe3..3ad18ee 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -4,6 +4,8 @@ #include "classicgame/classicgame.h" #include "classicgame/classicgraphicsmanager.h" +#include + const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 90.f); Application::Application() : @@ -27,7 +29,6 @@ void Application::run() void Application::exec() { sf::Clock timer; - sf::Clock game_timer; sf::Time time_since_last_update = sf::Time::Zero; while (_game_window.isOpen()) @@ -41,7 +42,6 @@ void Application::exec() if (isOneFramePassed) { time_since_last_update -= TIME_PER_FRAME; - game_timer.restart(); update(); draw(); } diff --git a/src/classicgame/classicanimationscenario.cpp b/src/classicgame/classicanimationscenario.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/classicgame/classicanimationscenario.h b/src/classicgame/classicanimationscenario.h index a9c1986..c551fcd 100644 --- a/src/classicgame/classicanimationscenario.h +++ b/src/classicgame/classicanimationscenario.h @@ -1,10 +1,8 @@ #pragma once -#include +#include "mathutils.h" #include -using microsec = sf::Int64; - class ClassicSprite; class ClassicAnimationScenario diff --git a/src/classicgame/classicflyinganimationscenario.cpp b/src/classicgame/classicflyinganimationscenario.cpp index b60cb8b..afdb17c 100644 --- a/src/classicgame/classicflyinganimationscenario.cpp +++ b/src/classicgame/classicflyinganimationscenario.cpp @@ -24,10 +24,10 @@ void ClassicFlyingAnimationScenario::update(const microsec& music_offset) auto update_time = music_offset - _time_begin; i = update_time / _percentage * 0.01; - float xa = getPoint( crd.first + 20. , crd.first + 90. , i ); - float ya = getPoint( crd.second - 600. , crd.second - 150. , i ); - float xb = getPoint( crd.first + 90. , crd.first , i ); - float yb = getPoint( crd.second - 150. , crd.second , i ); + float xa = getPoint( crd.x + 20. , crd.x + 90. , i ); + float ya = getPoint( crd.y - 600. , crd.y - 150. , i ); + float xb = getPoint( crd.x + 90. , crd.x , i ); + float yb = getPoint( crd.y - 150. , crd.y , i ); _sprite->update(getPoint( xa , xb , i ), getPoint( ya , yb , i )); if (i >= 1) diff --git a/src/classicgame/classicgraphicsmanager.cpp b/src/classicgame/classicgraphicsmanager.cpp index 943e006..8859b16 100644 --- a/src/classicgame/classicgraphicsmanager.cpp +++ b/src/classicgame/classicgraphicsmanager.cpp @@ -11,12 +11,13 @@ ClassicGraphicsManager::ClassicGraphicsManager(sf::RenderTarget& target) : void ClassicGraphicsManager::initGraphics(ClassicNote* note) { note->setSprite(_sprite_container.getSprite(note->type())); - note->sprite()->setCoordinates(note->getCoordinates().x, note->getCoordinates().y, 0, 0); + note->sprite()->setCoordinates(note->getCoordinates(), 0, 0); } void ClassicGraphicsManager::resetGraphics(ClassicNote* note) { _sprite_container.resetSprite(note->sprite(), note->type()); + note->setSprite(nullptr); } void ClassicGraphicsManager::draw(const ClassicNote *note) diff --git a/src/classicgame/classicmapcreator.cpp b/src/classicgame/classicmapcreator.cpp index d310ce3..44dd962 100644 --- a/src/classicgame/classicmapcreator.cpp +++ b/src/classicgame/classicmapcreator.cpp @@ -12,7 +12,7 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const microsec starting_beat_offset = 352162; int amount_of_beats = 209; microsec interval = 1412162; - microsec tempo_interval = interval / 2; + microsec tempo_interval = interval / 4; microsec note_input_offset = 412162 / 3; microsec bpm_iterator = starting_beat_offset; microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); diff --git a/src/classicgame/classicnote.cpp b/src/classicgame/classicnote.cpp index 32695ac..efb3beb 100644 --- a/src/classicgame/classicnote.cpp +++ b/src/classicgame/classicnote.cpp @@ -3,7 +3,6 @@ #include "classicgraphicsmanager.h" #include "classicflyinganimationscenario.h" #include "classicdyinganimationscenario.h" -#include ClassicNote::ClassicNote(const std::vector& intervals, microsec perfect_offset, Type type, const Coordinates& coord, const std::unique_ptr &manager) : @@ -12,48 +11,66 @@ ClassicNote::ClassicNote(const std::vector& intervals, microsec perfec _evaluator(intervals, _perfect_offset), _keys({sf::Keyboard::W, sf::Keyboard::Up}), _graphics_manager(manager), - _is_expired(true), _type(type), _state(State::NONE) { _animations[State::NONE] = nullptr; _animations[State::FLYING] = std::make_shared(); + _animations[State::ACTIVE] = _animations[State::FLYING]; _animations[State::DYING] = std::make_shared(); + _animations[State::DEAD] = nullptr; } -bool ClassicNote::isActive(const microsec &music_offset) const +bool ClassicNote::isActive() const { - return _evaluator.isActive(music_offset); + return _state == State::ACTIVE; } void ClassicNote::putToGame(const microsec &music_offset) { - _is_expired = false; _graphics_manager->initGraphics(this); _state = State::FLYING; _animations[_state]->launch(_sprite, music_offset, offset()); } +bool ClassicNote::isInGame() const +{ + return _state == State::FLYING || _state == State::ACTIVE || _state == State::DYING; +} + bool ClassicNote::isExpired() const { - return _is_expired; + return _state == State::DEAD; } void ClassicNote::update(const microsec& music_offset) { - if (!_animations[_state]) - return; - - bool is_not_active_anymore = (!_is_expired && !isActive(music_offset)); - - if (is_not_active_anymore) + switch (_state) { - _state = State::DYING; - _animations[_state]->launch(_sprite, music_offset, offset()); + default: return; + break; + + case State::FLYING: + if (_evaluator.isActive(music_offset)) + _state = State::ACTIVE; + break; + + case State::DYING: + if (_animations[_state]->isDone()) + _state = State::DEAD; + break; + + case State::ACTIVE: + if (!_evaluator.isActive(music_offset)) + { + _state = State::DYING; + _animations[_state]->launch(_sprite, music_offset, offset()); + } + break; } - _animations[_state]->update(music_offset); - _is_expired = _animations[_state]->isDone(); + if (_animations[_state]) + _animations[_state]->update(music_offset); } void ClassicNote::input(PlayerInput&& inputdata) diff --git a/src/classicgame/classicnote.h b/src/classicgame/classicnote.h index c0d1299..d87d0df 100644 --- a/src/classicgame/classicnote.h +++ b/src/classicgame/classicnote.h @@ -7,17 +7,6 @@ #include #include -struct Coordinates -{ - float x; - float y; - - inline Coordinates operator+(const Coordinates& right) noexcept - { - return {right.x + x, right.y - y}; - } -}; // MOVE TO OWN HEADER ^ - class ClassicSprite; class ClassicGraphicsManager; class ClassicAnimationScenario; @@ -38,7 +27,9 @@ public: NONE, FLYING, - DYING + ACTIVE, + DYING, + DEAD }; explicit ClassicNote(const std::vector& intervals, microsec perfect_offset, @@ -46,10 +37,11 @@ public: const std::unique_ptr& manager); virtual ~ClassicNote() = default; - virtual bool isActive(const microsec &music_offset) const override; + virtual bool isActive() const override; virtual void update(const microsec &music_offset) override; 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 void draw() const override; @@ -67,9 +59,8 @@ private: const std::unique_ptr& _graphics_manager; std::shared_ptr _sprite; - bool _is_expired; const Type _type; State _state; - std::array, 3> _animations; + std::array, 5> _animations; }; diff --git a/src/classicgame/classicsprite.cpp b/src/classicgame/classicsprite.cpp index a0f26fb..4ae3386 100644 --- a/src/classicgame/classicsprite.cpp +++ b/src/classicgame/classicsprite.cpp @@ -29,16 +29,16 @@ void ClassicSprite::reset() _trail_fade = false; } -void ClassicSprite::setCoordinates(float x, float y, float trail_x, float trail_y) noexcept +void ClassicSprite::setCoordinates(const Coordinates& coordinates, float trail_x, float trail_y) noexcept { - _shape.setPosition(x, y); + _shape.setPosition(coordinates.x, coordinates.y); _trail.setPosition(trail_x, trail_y); - _grade_text.setPosition(x + _shape.getSize().x/2, y + 10); + _grade_text.setPosition(coordinates.x + _shape.getSize().x/2, coordinates.y + 10); } -std::pair ClassicSprite::coordinates() const +Coordinates ClassicSprite::coordinates() const { - return std::make_pair(_shape.getPosition().x, _shape.getPosition().y); + return {_shape.getPosition().x, _shape.getPosition().y}; } void ClassicSprite::update(float trail_x, float trail_y) noexcept @@ -76,8 +76,12 @@ void ClassicSprite::fade() { auto fill_color = _grade_text.getFillColor(); - if (fill_color.a == 0) + if (fill_color.a <= 15) + { + fill_color.a = 0; + _grade_text.setFillColor(fill_color); return; + } auto new_alpha = fill_color.a - 15; fill_color.a = new_alpha < 0 ? 0 : new_alpha; @@ -87,7 +91,11 @@ void ClassicSprite::fade() fill_color = _shape.getFillColor(); if (fill_color.a == 0) + { + fill_color.a = 0; + _shape.setFillColor(fill_color); return; + } new_alpha = fill_color.a - 15; fill_color.a = new_alpha < 0 ? 0 : new_alpha; diff --git a/src/classicgame/classicsprite.h b/src/classicgame/classicsprite.h index e4ebed0..bc816da 100644 --- a/src/classicgame/classicsprite.h +++ b/src/classicgame/classicsprite.h @@ -1,5 +1,6 @@ #pragma once +#include "mathutils.h" #include "sprite.h" #include "SFML/Graphics/RectangleShape.hpp" #include "SFML/Graphics/Text.hpp" @@ -11,8 +12,8 @@ public: virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; virtual void reset() override; - void setCoordinates(float x, float y, float trail_x, float trail_y) noexcept; - std::pair coordinates() const; + void setCoordinates(const Coordinates &coordinates, float trail_x, float trail_y) noexcept; + Coordinates coordinates() const; void update(float trail_x, float trail_y) noexcept; void update() noexcept; diff --git a/src/classicgame/classictimeline.cpp b/src/classicgame/classictimeline.cpp index 4267c94..84c77e2 100644 --- a/src/classicgame/classictimeline.cpp +++ b/src/classicgame/classictimeline.cpp @@ -12,6 +12,7 @@ ClassicTimeline::ClassicTimeline() _music.openFromFile(song_filename); _music.setVolume(10); + _last_timestamp = -1; } void ClassicTimeline::run(std::vector&& notes, const microsec& visibility) @@ -44,32 +45,37 @@ void ClassicTimeline::clear() void ClassicTimeline::update() { const auto& music_offset = currentMusicOffset(); - checkCurrentActiveNote(music_offset); - checkForNextActiveNote(music_offset); - updateVisibleSprites(music_offset); + if (music_offset != _last_timestamp) + { + checkCurrentActiveNote(); + checkForNextActiveNote(); + updateVisibleSprites(music_offset); + } + + _last_timestamp = music_offset; } -void ClassicTimeline::checkCurrentActiveNote(const microsec& music_offset) +void ClassicTimeline::checkCurrentActiveNote() { if (isExpired(_active_note)) return; auto note = *_active_note; - if (!note->isActive(music_offset)) + if (!note->isActive()) { expire(_active_note); ++_top_note; } } -void ClassicTimeline::checkForNextActiveNote(const microsec& music_offset) +void ClassicTimeline::checkForNextActiveNote() { if (!isExpired(_active_note)) return; auto top_note = *_top_note; - if (top_note->isActive(music_offset)) + if (top_note->isActive()) _active_note = _top_note; } @@ -127,7 +133,7 @@ void ClassicTimeline::findLastVisibleNote(const microsec &music_offset) auto note = *note_iterator; - if (note->isExpired()) + if (!note->isInGame()) note->putToGame(music_offset); ++note_iterator; diff --git a/src/classicgame/classictimeline.h b/src/classicgame/classictimeline.h index 7404d24..b72c26e 100644 --- a/src/classicgame/classictimeline.h +++ b/src/classicgame/classictimeline.h @@ -33,12 +33,13 @@ private: std::vector _input_intervals; std::vector _timeline; microsec _visibility_offset; + microsec _last_timestamp; sf::Music _music; void updateVisibleSprites(const microsec& music_offset); - void checkCurrentActiveNote(const microsec& music_offset); - void checkForNextActiveNote(const microsec& music_offset); + void checkCurrentActiveNote(); + void checkForNextActiveNote(); bool isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const; inline bool nothingToDraw() const noexcept;