diff --git a/include/core/note.h b/include/core/note.h index 9db5844..23ac834 100644 --- a/include/core/note.h +++ b/include/core/note.h @@ -16,10 +16,6 @@ public: virtual bool isActive(const microsec& offset) const = 0; virtual void update(const microsec& music_offset) = 0; - virtual void putToGame() = 0; - virtual bool isInGame() const = 0; - virtual bool shouldRemove() const = 0; - virtual void input(kku::GameEvent&& input) = 0; inline const microsec& getPerfectOffset() const noexcept diff --git a/include/core/rectangle.h b/include/core/rectangle.h index 546e0bb..f8b831e 100644 --- a/include/core/rectangle.h +++ b/include/core/rectangle.h @@ -18,6 +18,7 @@ public: virtual void move(const kku::Vector2& delta) = 0; virtual void setColor(const Color& color) = 0; + virtual kku::Color getColor() const = 0; virtual bool contains(const kku::Point& position) const = 0; virtual void display() = 0; diff --git a/include/core/spritecontainer.h b/include/core/spritecontainer.h index 82e81cb..139a3e8 100644 --- a/include/core/spritecontainer.h +++ b/include/core/spritecontainer.h @@ -1,9 +1,7 @@ #pragma once - #include #include #include - namespace kku { @@ -48,7 +46,7 @@ private: SpritePoll &poll = _sprite_dispatcher[sprite_type]; for (std::size_t i = 0; i < _poll_reserve_size; ++i) { - poll.push(_sprite_factory->create(sprite_type)); + poll.push(_sprite_factory->createSprite(sprite_type)); } } @@ -60,4 +58,4 @@ private: std::size_t _poll_reserve_size; }; -} \ No newline at end of file +} diff --git a/src/application/shared/application/application.h b/src/application/shared/application/application.h index 3892930..77f863f 100644 --- a/src/application/shared/application/application.h +++ b/src/application/shared/application/application.h @@ -7,8 +7,6 @@ #include "../../include/application/state.h" // HOW? WHY DOESN'T "application/state.h" LINK ON BY ITSELF #include "core/corefactory.h" -class ClassicFactory; - class Application { public: @@ -22,7 +20,6 @@ public: protected: std::shared_ptr _core_factory; - std::shared_ptr _game_factory; std::array, GUIState::Tag::AMOUNT> _states; std::vector> _state_stack; diff --git a/src/application/src/application.cpp b/src/application/src/application.cpp index a9731b2..ab19aee 100644 --- a/src/application/src/application.cpp +++ b/src/application/src/application.cpp @@ -10,7 +10,7 @@ bool Application::init() { - if (!_game_factory || !_core_factory) + if (!_core_factory) return false; MainMenu::Callbacks callbacks = @@ -22,8 +22,8 @@ bool Application::init() EditorState::Callbacks editor_callbacks = {[&](){ popState(); }}; const auto main_menu = std::make_shared(_core_factory, std::move(callbacks)); - const auto game_state = std::make_shared(_core_factory, _game_factory->getGame(), GameState::Callbacks()); - const auto editor = std::make_shared(_core_factory, _game_factory->getEditor(), std::move(editor_callbacks)); + const auto game_state = std::make_shared(_core_factory, classic::getGame(_core_factory), GameState::Callbacks()); + const auto editor = std::make_shared(_core_factory, classic::getEditor(_core_factory), std::move(editor_callbacks)); _states[GUIState::Tag::MAIN_MENU] = main_menu; _states[GUIState::Tag::GAME] = game_state; diff --git a/src/impl/sfml/application/applicationsfml.cpp b/src/impl/sfml/application/applicationsfml.cpp index 39d0648..cc9ef2a 100644 --- a/src/impl/sfml/application/applicationsfml.cpp +++ b/src/impl/sfml/application/applicationsfml.cpp @@ -1,6 +1,5 @@ #include "applicationsfml.h" #include "sfml/corefactorysfml.h" -#include "sfml/classicmode/classicfactorysfml.h" #include "sfml/application/inputconvertersfml.h" #include @@ -16,7 +15,6 @@ ApplicationSFML::ApplicationSFML(sf::RenderWindow * const render_window) : _render_window->setVerticalSyncEnabled(true); _core_factory = std::make_shared(_render_window); - _game_factory = std::make_shared(_render_window); } void ApplicationSFML::display() diff --git a/src/impl/sfml/classicmode/classicfactorysfml.h b/src/impl/sfml/classicmode/classicfactorysfml.h deleted file mode 100644 index 7343823..0000000 --- a/src/impl/sfml/classicmode/classicfactorysfml.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include - -#include "shared/classicmode/classicfactory.h" - -class ClassicFactorySFML : public ClassicFactory -{ -public: - explicit ClassicFactorySFML(sf::RenderTarget * const render_target); - virtual std::unique_ptr getGame() const override; - virtual std::unique_ptr getEditor() const override; - -private: - sf::RenderTarget * const _render_target; -}; diff --git a/src/impl/sfml/classicmode/classicspritesfml.cpp b/src/impl/sfml/classicmode/classicspritesfml.cpp deleted file mode 100644 index 66aa44e..0000000 --- a/src/impl/sfml/classicmode/classicspritesfml.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "classicspritesfml.h" - -ClassicSpriteSFML::ClassicSpriteSFML(sf::RenderTarget * const render_target, - const sf::RectangleShape& shape) : - _prototype(shape), - _shape(shape), - _trail(shape), - _render_target(render_target) -{} - -void ClassicSpriteSFML::reset() -{ - _shape.setPosition(0, 0); - _trail.setPosition(0, 0); - - _shape = _prototype; - _trail = _prototype; -} - -void ClassicSpriteSFML::setPosition(const kku::Point& position) -{ - _shape.setPosition(position.x, position.y); -} - -void ClassicSpriteSFML::setTrailPosition(const kku::Point &position) -{ - _trail.setPosition(position.x, position.y); -} - -kku::Point ClassicSpriteSFML::getPosition() const -{ - return kku::Point{ _shape.getPosition().x, _shape.getPosition().y }; -} - -kku::Point ClassicSpriteSFML::getTrailPosition() const -{ - return kku::Point{ _trail.getPosition().x, _trail.getPosition().y }; -} - -void ClassicSpriteSFML::setColor(const kku::Color& color) -{ - _shape.setFillColor(sf::Color{ color.red, color.green, color.blue, color.alpha }); -} - -void ClassicSpriteSFML::setTrailColor(const kku::Color& color) -{ - _trail.setFillColor(sf::Color{ color.red, color.green, color.blue, color.alpha }); -} - -kku::Color ClassicSpriteSFML::getColor() const -{ - const auto color = _shape.getFillColor(); - return kku::Color{ color.r, color.g, color.b, color.a }; -} - -kku::Color ClassicSpriteSFML::getTrailColor() const -{ - const auto color = _trail.getFillColor(); - return kku::Color{ color.r, color.g, color.b, color.a }; -} - -void ClassicSpriteSFML::display() const -{ - _render_target->draw(_shape); - _render_target->draw(_trail); -} diff --git a/src/impl/sfml/classicmode/classicspritesfml.h b/src/impl/sfml/classicmode/classicspritesfml.h deleted file mode 100644 index eca2f66..0000000 --- a/src/impl/sfml/classicmode/classicspritesfml.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "graphics/classicsprite.h" - -#include -#include - -class ClassicSpriteSFML : public ClassicSprite -{ -public: - explicit ClassicSpriteSFML(sf::RenderTarget * const render_target, - const sf::RectangleShape& shape); - - virtual void reset() override; - virtual void display() const override; - - virtual void setPosition(const kku::Point &position) override; - virtual void setTrailPosition(const kku::Point &position) override; - virtual kku::Point getPosition() const override; - virtual kku::Point getTrailPosition() const override; - - virtual void setColor(const kku::Color& color) override; - virtual void setTrailColor(const kku::Color& color) override; - virtual kku::Color getColor() const override; - virtual kku::Color getTrailColor() const override; - -private: - sf::RectangleShape _prototype; - - sf::RectangleShape _shape; - sf::RectangleShape _trail; - - sf::RenderTarget * const _render_target; -}; diff --git a/src/impl/sfml/classicmode/spritefactorysfml.cpp b/src/impl/sfml/classicmode/spritefactorysfml.cpp deleted file mode 100644 index d0615a3..0000000 --- a/src/impl/sfml/classicmode/spritefactorysfml.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "spritefactorysfml.h" -#include "classicspritesfml.h" - -ClassicSpriteFactorySFML::ClassicSpriteFactorySFML(sf::RenderTarget * const render_target) : - _render_target(render_target) -{} - -std::shared_ptr ClassicSpriteFactorySFML::create(Type type) const -{ - sf::RectangleShape sprite; - sprite.setSize({20.f, 20.f}); - switch (type) - { - case Type::UP: - sprite.setFillColor(sf::Color(255, 0, 0)); - break; - - case Type::DOWN: - sprite.setFillColor(sf::Color(0, 255, 0)); - break; - - case Type::LEFT: - sprite.setFillColor(sf::Color(0, 0, 255)); - break; - - case Type::RIGHT: - sprite.setFillColor(sf::Color(255, 0, 255)); - break; - - default: // yellow - sprite.setFillColor(sf::Color(255, 239, 0)); - } - - return std::make_shared(_render_target, sprite); -} diff --git a/src/impl/sfml/classicmode/spritefactorysfml.h b/src/impl/sfml/classicmode/spritefactorysfml.h deleted file mode 100644 index 2a163b8..0000000 --- a/src/impl/sfml/classicmode/spritefactorysfml.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "graphics/classicspritefactory.h" - -#include - -class ClassicSpriteFactorySFML : public ClassicSpriteFactory -{ -public: - explicit ClassicSpriteFactorySFML(sf::RenderTarget * const render_target); - virtual std::shared_ptr create(Type type) const override; - -private: - sf::RenderTarget * const _render_target; -}; diff --git a/src/impl/sfml/rectanglesfml.cpp b/src/impl/sfml/rectanglesfml.cpp index edf07a3..b828182 100644 --- a/src/impl/sfml/rectanglesfml.cpp +++ b/src/impl/sfml/rectanglesfml.cpp @@ -40,6 +40,12 @@ void RectangleSFML::setColor(const kku::Color& color) color.blue, color.alpha}); } +kku::Color RectangleSFML::getColor() const +{ + const auto color = _rectangle.getFillColor(); + return kku::Color{color.r, color.g, color.b, color.a}; +} + bool RectangleSFML::contains(const kku::Point& position) const { return _rectangle.getGlobalBounds().contains(position.x, position.y); diff --git a/src/impl/sfml/rectanglesfml.h b/src/impl/sfml/rectanglesfml.h index ddcb5d3..03a26b1 100644 --- a/src/impl/sfml/rectanglesfml.h +++ b/src/impl/sfml/rectanglesfml.h @@ -18,6 +18,7 @@ public: virtual void move(const kku::Vector2& delta) override; virtual void setColor(const kku::Color& color) override; + virtual kku::Color getColor() const override; virtual bool contains(const kku::Point& position) const override; virtual void display() override; diff --git a/src/main.cpp b/src/main.cpp index 40a076a..e4d0c35 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,7 @@ int main() { - sf::RenderWindow window(sf::VideoMode{1280, 720}, "Test", sf::Style::Fullscreen); + sf::RenderWindow window(sf::VideoMode{1280, 720}, "Test", sf::Style::Default); ApplicationSFML app(&window); if (app.init()) app.run(); diff --git a/src/modes/classicmode/CMakeLists.txt b/src/modes/classicmode/CMakeLists.txt index 00827be..22013a1 100644 --- a/src/modes/classicmode/CMakeLists.txt +++ b/src/modes/classicmode/CMakeLists.txt @@ -9,7 +9,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared) file(GLOB_RECURSE SOURCES "editor/*.h" "editor/*.cpp" "graphics/*.h" "graphics/*.cpp" "game/*.h" "game/*.cpp" - "shared/*.h" + "shared/*.h" "*.cpp" "include/*.h") add_library(classicmode STATIC ${SOURCES} ${HEADERS}) diff --git a/src/impl/sfml/classicmode/classicfactorysfml.cpp b/src/modes/classicmode/classicfactory.cpp similarity index 64% rename from src/impl/sfml/classicmode/classicfactorysfml.cpp rename to src/modes/classicmode/classicfactory.cpp index c4a3b88..f276f62 100644 --- a/src/impl/sfml/classicmode/classicfactorysfml.cpp +++ b/src/modes/classicmode/classicfactory.cpp @@ -1,34 +1,31 @@ -#include "classicfactorysfml.h" -#include "spritefactorysfml.h" +#include "classicmode/classicfactory.h" #include "graphics/classicscenegraphicsmanager.h" -#include "core/timeline.h" +#include "graphics/classicgraphicsfactory.h" +#include "core/timeline.h" #include "game/classicgame.h" #include "editor/classiceditor.h" -ClassicFactorySFML::ClassicFactorySFML(sf::RenderTarget * const render_target) : - _render_target(render_target) -{} -std::unique_ptr ClassicFactorySFML::getGame() const +std::unique_ptr classic::getGame(const std::shared_ptr& core_factory) { // read offset from beatmap metadata const kku::microsec visibility_offset = 1648648; - const auto factory = std::make_shared(_render_target); + const auto factory = std::make_shared(core_factory); const auto timeline = std::make_shared>(); const auto graphics_manager = std::make_shared(timeline, factory, visibility_offset); return std::make_unique(timeline, graphics_manager); } -std::unique_ptr ClassicFactorySFML::getEditor() const +std::unique_ptr classic::getEditor(const std::shared_ptr& core_factory) { // read offset from beatmap metadata const kku::microsec visibility_offset = 1648648; - const auto factory = std::make_shared(_render_target); + const auto factory = std::make_shared(core_factory); const auto timeline = std::make_shared>(); const auto graphics_manager = std::make_shared(timeline, factory, visibility_offset); diff --git a/src/modes/classicmode/editor/classiceditor.cpp b/src/modes/classicmode/editor/classiceditor.cpp index 57335ae..dc81292 100644 --- a/src/modes/classicmode/editor/classiceditor.cpp +++ b/src/modes/classicmode/editor/classiceditor.cpp @@ -1,6 +1,8 @@ #include "classiceditor.h" -#include "game/classicarrownote.h" +#include "game/classicmocknote.h" +#include "graphics/classicgraphicsmanager.h" +#include "game/classicmapcreator.h" // Replace with interface by dependency injection #include "graphics/animations/classicflyinganimationscenario.h" @@ -15,7 +17,65 @@ ClassicEditor::ClassicEditor(const std::shared_ptr>& _current_time(0), _scroll_step(500000) { - _timeline->setNotes({}); + kku::microsec starting_beat_offset = 402162; + int amount_of_beats = 209; + kku::microsec interval = 1412162; + kku::microsec tempo_interval = interval / 4; + kku::microsec note_input_offset = 412162 / 2; + //microsec note_input_offset_fast = 412162 / 6; + kku::microsec bpm_iterator = starting_beat_offset; + kku::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::set notes; + input_intervals.shrink_to_fit(); + + bpm_iterator += tempo_interval; + + float x = 90.; + + int counter = 3; + + while (bpm_iterator < bpm_end) + { + ArrowNoteInitializer init; + ArrowElementInitializer element; + init.initializer.intervals = input_intervals; + init.initializer.perfect_offset = bpm_iterator; + init.hold = false; + + element.element.position = kku::Point(x, 390.f); + element.element.falling_curve_interpolation = {}; + + element.keys = {kku::SystemEvent::Key::Code::W, + kku::SystemEvent::Key::Code::Up}; + + element.element.type = Type::UP; + + if (counter == 0) + { + init.hold = true; + + element.keys = {kku::SystemEvent::Key::Code::D, + kku::SystemEvent::Key::Code::Right}; + + element.element.type = Type::RIGHT; + } + + --counter; + + init.elements = {element}; + + notes.insert(new ClassicMockNote(std::move(init))); + + bpm_iterator += tempo_interval; + x += 70; + + if (x >= 1200) + x = 90.; + } + + _timeline->setNotes(notes); } kku::microsec ClassicEditor::adjustOffset(kku::microsec offset) const noexcept @@ -59,8 +119,10 @@ void ClassicEditor::input(kku::GameEvent&& input) init.elements = { element }; - _timeline->insertNote(new ClassicArrowNote(std::move(init))); + _timeline->insertNote(new ClassicMockNote(std::move(init))); } + else + _graphics_manager->input(std::move(input)); break; } @@ -70,10 +132,12 @@ void ClassicEditor::input(kku::GameEvent&& input) void ClassicEditor::update(kku::UpdateData&& updatedata) { _timeline->update(updatedata.timestamp); + _graphics_manager->update(updatedata.timestamp); } void ClassicEditor::display() const { + _graphics_manager->display(); } void ClassicEditor::recalculate(const kku::microsec& timestamp) diff --git a/src/modes/classicmode/game/classicarrownote.cpp b/src/modes/classicmode/game/classicarrownote.cpp index be388ac..95accde 100644 --- a/src/modes/classicmode/game/classicarrownote.cpp +++ b/src/modes/classicmode/game/classicarrownote.cpp @@ -5,6 +5,7 @@ ClassicArrowNote::ClassicArrowNote(ArrowNoteInitializer&& init) : ClassicNote(std::move(init.initializer)), + _evaluator(init.initializer.intervals, _perfect_offset), _is_hold(init.hold) { _elements.resize(init.elements.size()); @@ -17,14 +18,15 @@ ClassicArrowNote::ClassicArrowNote(ArrowNoteInitializer&& init) : } } -void ClassicArrowNote::putToGame() +bool ClassicArrowNote::isActive(const kku::microsec& offset) const { - _state = State::FLYING; + return _evaluator.isActive(offset) + && _state != State::DYING; } void ClassicArrowNote::input(kku::GameEvent&& input) { - auto grade = ClassicNote::Grade::BAD; + auto grade = Grade::BAD; bool input_valid = std::any_of(_elements.begin(), _elements.end(), [input=input](auto& element) diff --git a/src/modes/classicmode/game/classicarrownote.h b/src/modes/classicmode/game/classicarrownote.h index b49a3a2..67c4294 100644 --- a/src/modes/classicmode/game/classicarrownote.h +++ b/src/modes/classicmode/game/classicarrownote.h @@ -8,10 +8,17 @@ class ClassicArrowNote : public ClassicNote { public: + enum class Grade + { + PERFECT, + GOOD, + BAD + }; + explicit ClassicArrowNote(ArrowNoteInitializer&& init); virtual ~ClassicArrowNote() = default; - virtual void putToGame() override; + virtual bool isActive(const kku::microsec& offset) const override; virtual void update(const kku::microsec &music_offset) override; virtual void input(kku::GameEvent&& input) override; @@ -23,6 +30,8 @@ public: inline bool isHold() const; private: + const kku::PrecisionEvaluator _evaluator; + std::vector _elements; bool _is_hold; }; diff --git a/src/modes/classicmode/game/classicmocknote.cpp b/src/modes/classicmode/game/classicmocknote.cpp new file mode 100644 index 0000000..3f6dc77 --- /dev/null +++ b/src/modes/classicmode/game/classicmocknote.cpp @@ -0,0 +1,85 @@ +#include "classicmocknote.h" +#include "graphics/classicscenegraphicsmanager.h" +#include "graphics/animations/classicanimationscenario.h" +#include "holdmanager.h" + +ClassicMockNote::ClassicMockNote(ArrowNoteInitializer&& init) : + ClassicNote(std::move(init.initializer)) +{ + _elements.resize(init.elements.size()); + + for (std::size_t i = 0; i < _elements.size(); ++i) + { + _elements[i].position = init.elements[i].element.position; + _elements[i].type = init.elements[i].element.type; + } +} + +bool ClassicMockNote::isActive(const kku::microsec &offset) const +{ + (void)offset; + return _state != State::DEAD + && _state != State::NONE; +} + +void ClassicMockNote::input(kku::GameEvent&& input) +{ + switch (input.event.type) + { + + default: + break; + + case kku::SystemEvent::Type::MousePress: + { + const auto position = std::get(input.event.data).position; + for (auto& element : _elements) + { + if (element.sprite->getRectangle()->contains(position)) + { + element.selected = !element.selected; + element.selection->toggle(element.selected); + } + } + break; + } + + } +} + +void ClassicMockNote::update(const kku::microsec& music_offset) +{ + switch (_state) + { + default: return; + break; + + case State::FLYING: + if (music_offset >= getPerfectOffset()) + { + _state = State::DYING; + for (auto& element : _elements) + element.animations[_state]->launch(element.sprite, music_offset, getPerfectOffset()); + } + break; + + case State::DYING: + if (_elements[0].animations[_state]->isDone()) + _state = State::DEAD; + break; + } + + for (auto& element : _elements) + if (element.animations[_state]) + element.animations[_state]->update(music_offset); +} + +void ClassicMockNote::display(const ClassicGraphicsManager * const manager) const +{ + manager->display(_elements); +} + +void ClassicMockNote::setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) +{ + manager->setGraphics(_elements, std::move(range)); +} diff --git a/src/modes/classicmode/game/classicmocknote.h b/src/modes/classicmode/game/classicmocknote.h new file mode 100644 index 0000000..c9b4f08 --- /dev/null +++ b/src/modes/classicmode/game/classicmocknote.h @@ -0,0 +1,27 @@ +#pragma once + +#include "arrowelement.h" +#include "classicnote.h" + +#include "mockelement.h" +#include "initializers/arrownoteinitializer.h" + +class ClassicMockNote : public ClassicNote +{ +public: + explicit ClassicMockNote(ArrowNoteInitializer&& init); + virtual ~ClassicMockNote() = default; + + virtual bool isActive(const kku::microsec& offset) const override; + virtual void update(const kku::microsec &music_offset) override; + virtual void input(kku::GameEvent&& input) override; + + virtual void display(const ClassicGraphicsManager * const manager) const override; + virtual void setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) override; + +private: + std::vector _elements; + bool _is_selected; +}; + +using MockElements = std::vector; diff --git a/src/modes/classicmode/game/classicnote.cpp b/src/modes/classicmode/game/classicnote.cpp index 44158d0..ea4868f 100644 --- a/src/modes/classicmode/game/classicnote.cpp +++ b/src/modes/classicmode/game/classicnote.cpp @@ -2,24 +2,16 @@ ClassicNote::ClassicNote(NoteInitializer &&init) : Note(init.perfect_offset), - _evaluator(init.intervals, _perfect_offset), _state(State::NONE), _context(init.context) {} -bool ClassicNote::isActive(const kku::microsec& offset) const +void ClassicNote::setState(ClassicNote::State state) noexcept { - return _evaluator.isActive(offset) - && _state != State::DYING; + _state = state; } -bool ClassicNote::isInGame() const +auto ClassicNote::getState() const noexcept -> State { - return _state == State::FLYING - || _state == State::DYING; -} - -bool ClassicNote::shouldRemove() const -{ - return _state == State::DEAD; + return _state; } diff --git a/src/modes/classicmode/game/classicnote.h b/src/modes/classicmode/game/classicnote.h index 1a14937..658600c 100644 --- a/src/modes/classicmode/game/classicnote.h +++ b/src/modes/classicmode/game/classicnote.h @@ -5,21 +5,12 @@ #include "classicmode/noteinitializer.h" #include "classicmode/context.h" -class ClassicSprite; -class ClassicAnimationScenario; class ClassicGraphicsManager; class ClassicNote : public kku::Note { public: - enum class Grade - { - PERFECT, - GOOD, - BAD - }; - enum State { NONE, @@ -32,11 +23,7 @@ public: explicit ClassicNote(NoteInitializer&& init); virtual ~ClassicNote() override = default; - virtual bool isActive(const kku::microsec& offset) const override final; - virtual bool isInGame() const override final; - virtual bool shouldRemove() const override final; - - virtual void putToGame() override = 0; + virtual bool isActive(const kku::microsec& offset) const override = 0; virtual void update(const kku::microsec &music_offset) override = 0; virtual void input(kku::GameEvent&& input) override = 0; @@ -44,9 +31,10 @@ public: virtual void display(const ClassicGraphicsManager * const manager) const = 0; virtual void setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) = 0; -protected: - const kku::PrecisionEvaluator _evaluator; + void setState(State state) noexcept; + State getState() const noexcept; +protected: State _state; const Context *_context; }; diff --git a/src/modes/classicmode/game/mockelement.h b/src/modes/classicmode/game/mockelement.h new file mode 100644 index 0000000..91f7f0c --- /dev/null +++ b/src/modes/classicmode/game/mockelement.h @@ -0,0 +1,32 @@ +#pragma once + +#include "classicmode/classicactions.h" + +#include "core/gameevent.h" +#include "core/point.h" + +#include +#include +#include + +class ClassicAnimationScenario; +class ClassicSprite; +class ClassicSelection; + +struct MockElement +{ + std::shared_ptr sprite; + std::shared_ptr selection; + bool selected; + + std::array, 5> animations; + + kku::Point position; + std::vector falling_curve_interpolation; + + Type type = Type::NONE; + + // Each note may consist of several buttons. + // For example, ↑ → or ↓ → ← + // Note Element represents this idea. +}; diff --git a/src/modes/classicmode/graphics/classicgraphicsfactory.cpp b/src/modes/classicmode/graphics/classicgraphicsfactory.cpp new file mode 100644 index 0000000..e11e562 --- /dev/null +++ b/src/modes/classicmode/graphics/classicgraphicsfactory.cpp @@ -0,0 +1,56 @@ +#include "classicgraphicsfactory.h" + +ClassicGraphicsFactory::ClassicGraphicsFactory(const std::shared_ptr& core_factory) : + _core_factory(core_factory) +{} + + + +auto ClassicGraphicsFactory::generate(Type type) const -> SpriteData +{ + auto shape = _core_factory->getRectangle(); + auto trail = _core_factory->getRectangle(); + shape->setRect(kku::Area{0.f, 0.f, 20.f, 20.f}); + trail->setRect(kku::Area{0.f, 0.f, 20.f, 20.f}); + + kku::Color color; + + switch (type) + { + case Type::UP: + color = kku::Color{255, 0, 0, 255}; + break; + + case Type::DOWN: + color = kku::Color{0, 255, 0, 255}; + break; + + case Type::LEFT: + color = kku::Color{0, 0, 255, 255}; + break; + + case Type::RIGHT: + color = kku::Color{255, 0, 255, 255}; + break; + + default: // yellow + color = kku::Color{255, 239, 0, 255}; + } + + shape->setColor(color); + trail->setColor(color); + + return SpriteData{shape, trail, color}; +} + +std::shared_ptr ClassicGraphicsFactory::createSprite(Type type) const +{ + const auto data = generate(type); + return std::make_shared(ClassicSprite::Init{data.shape, data.trail, data.color}); +} + +std::shared_ptr ClassicGraphicsFactory::createSelection() const +{ + const auto shape = _core_factory->getRectangle(); + return std::make_shared(ClassicSelection::Init{shape, kku::Color{51, 153, 255, 0}}); +} diff --git a/src/modes/classicmode/graphics/classicgraphicsfactory.h b/src/modes/classicmode/graphics/classicgraphicsfactory.h new file mode 100644 index 0000000..8688bca --- /dev/null +++ b/src/modes/classicmode/graphics/classicgraphicsfactory.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include "classicmode/classicactions.h" +#include "graphics/classicsprite.h" +#include "graphics/classicselection.h" +#include "core/rectangle.h" +#include "core/corefactory.h" + +class ClassicGraphicsFactory +{ +public: + explicit ClassicGraphicsFactory(const std::shared_ptr& core_factory); + + std::shared_ptr createSprite(Type type) const; + std::shared_ptr createSelection() const; + +private: + const std::shared_ptr _core_factory; + + struct SpriteData + { + std::shared_ptr shape; + std::shared_ptr trail; + kku::Color color; + }; + + SpriteData generate(Type type) const; +}; diff --git a/src/modes/classicmode/graphics/classicgraphicsmanager.h b/src/modes/classicmode/graphics/classicgraphicsmanager.h index a1ec1b3..36fa08c 100644 --- a/src/modes/classicmode/graphics/classicgraphicsmanager.h +++ b/src/modes/classicmode/graphics/classicgraphicsmanager.h @@ -7,6 +7,7 @@ #include struct ArrowElement; +struct MockElement; class ClassicGraphicsManager : public std::enable_shared_from_this { @@ -16,9 +17,14 @@ public: _visibility_offset(visibility_offset) {} + virtual void input(kku::GameEvent&& input) = 0; + virtual void display(const std::vector& elements) const = 0; virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) = 0; + virtual void display(const std::vector& elements) const = 0; + virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) = 0; + virtual void display() const = 0; virtual void update(const kku::microsec& offset) = 0; diff --git a/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp b/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp index 0e0ae53..d7b344a 100644 --- a/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp +++ b/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp @@ -1,24 +1,36 @@ #include "classicscenegraphicsmanager.h" -#include "graphics/classicsprite.h" +#include "game/mockelement.h" #include "game/arrowelement.h" #include "graphics/animations/classicflyinganimationscenario.h" #include "graphics/animations/classicdyinganimationscenario.h" ClassicSceneGraphicsManager::ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, - const std::shared_ptr& factory, + const std::shared_ptr& factory, const kku::microsec& visibility_offset) : ClassicGraphicsManager(visibility_offset), _sprite_container({Type::UP, Type::DOWN, Type::LEFT, Type::RIGHT}, factory), + _factory(factory), _timeline(timeline) { _timeline->expire(_first); _timeline->expire(_last); } +void ClassicSceneGraphicsManager::input(kku::GameEvent&& input) +{ + if (nothingToDraw()) + return; + + for (auto it = _first; it != _last; ++it) + { + (*it)->input(std::move(input)); + } +} + void ClassicSceneGraphicsManager::display() const { if (nothingToDraw()) @@ -75,6 +87,47 @@ void ClassicSceneGraphicsManager::setGraphics(std::vector& element } } +void ClassicSceneGraphicsManager::display(const std::vector& elements) const +{ + for (std::size_t i = 0; i < elements.size(); ++i) + { + const auto& sprite = elements[i].sprite; + const auto& selection = elements[i].selection; + + if (i >= 1) + { + //const auto& neighbor_sprite = elements[i - 1].sprite; + + //const auto c1 = neighbor_sprite->trailPosition(); + //const auto c2 = sprite->trailPosition(); + + //_render_target->draw(makeLine(c1, c2)); + } + + sprite->display(); + selection->display(); + } +} + +void ClassicSceneGraphicsManager::setGraphics(std::vector& elements, kku::TimeRange &&range) +{ + for (auto& element : elements) + { + element.sprite = _sprite_container.getSprite(element.type); + element.sprite->setPosition(element.position); + element.sprite->setTrailPosition(kku::Point( 0.f, 9.f )); + + element.selection = _factory->createSelection(); + element.selection->adjustTo(element.sprite); + + element.animations[ClassicNote::State::NONE] = nullptr; + element.animations[ClassicNote::State::FLYING] = std::make_shared(); + element.animations[ClassicNote::State::DYING] = std::make_shared(); + element.animations[ClassicNote::State::DEAD] = nullptr; + element.animations[ClassicNote::State::FLYING]->launch(element.sprite, range.begin, range.end); + } +} + /*sf::VertexArray ClassicSceneGraphicsSFML::makeLine(const kku::Point& c1, const kku::Point& c2) const { sf::VertexArray line(sf::LinesStrip, 2); @@ -103,7 +156,7 @@ void ClassicSceneGraphicsManager::fetchFirstNote(const kku::microsec& offset) while (note_iterator != _last) { auto note = *note_iterator; - if (note->shouldRemove()) + if (note->getState() == ClassicNote::State::DEAD) ++_first; ++note_iterator; @@ -120,9 +173,10 @@ void ClassicSceneGraphicsManager::fetchLastNote(const kku::microsec& offset) auto note = *note_iterator; - if (!note->isInGame()) + if (note->getState() != ClassicNote::State::FLYING + && note->getState() != ClassicNote::State::DYING) { - note->putToGame(); + note->setState(ClassicNote::State::FLYING); note->setGraphics(this, kku::TimeRange{offset, note->getPerfectOffset()}); } diff --git a/src/modes/classicmode/graphics/classicscenegraphicsmanager.h b/src/modes/classicmode/graphics/classicscenegraphicsmanager.h index bef2ae3..a9473a4 100644 --- a/src/modes/classicmode/graphics/classicscenegraphicsmanager.h +++ b/src/modes/classicmode/graphics/classicscenegraphicsmanager.h @@ -2,7 +2,7 @@ #include "game/classicnote.h" #include "graphics/classicgraphicsmanager.h" -#include "graphics/classicspritefactory.h" +#include "graphics/classicgraphicsfactory.h" #include "core/timeline.h" #include "core/spritecontainer.h" @@ -12,17 +12,23 @@ class ClassicSceneGraphicsManager : public ClassicGraphicsManager { public: explicit ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, - const std::shared_ptr& factory, + const std::shared_ptr& factory, const kku::microsec& visibility_offset); + virtual void input(kku::GameEvent&& input) override; + virtual void display() const override; virtual void update(const kku::microsec& offset) override; virtual void display(const std::vector& elements) const override; virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) override; + virtual void display(const std::vector& elements) const override; + virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) override; + protected: - kku::SpriteContainer _sprite_container; + kku::SpriteContainer _sprite_container; + const std::shared_ptr _factory; using Iterator = kku::Timeline::Iterator; Iterator _first; diff --git a/src/modes/classicmode/graphics/classicselection.cpp b/src/modes/classicmode/graphics/classicselection.cpp new file mode 100644 index 0000000..dd44672 --- /dev/null +++ b/src/modes/classicmode/graphics/classicselection.cpp @@ -0,0 +1,34 @@ +#include "classicselection.h" +#include "classicsprite.h" + +ClassicSelection::ClassicSelection(ClassicSelection::Init&& init) : + _fill_color(init.color), + _shape(init.shape) +{ + _shape->setColor(init.color); +} + +void ClassicSelection::reset() +{ + _shape->setPosition(kku::Point{0, 0}); + _shape->setColor(kku::Color{0, 0, 0, 0}); +} + +void ClassicSelection::display() const +{ + _shape->display(); +} + +void ClassicSelection::adjustTo(const std::shared_ptr& sprite) +{ + _shape->setRect(sprite->getRectangle()->getRect()); +} + +void ClassicSelection::toggle(bool selected) +{ + _fill_color.alpha = selected + ? 120 + : 0; + + _shape->setColor(_fill_color); +} diff --git a/src/modes/classicmode/graphics/classicselection.h b/src/modes/classicmode/graphics/classicselection.h new file mode 100644 index 0000000..b105258 --- /dev/null +++ b/src/modes/classicmode/graphics/classicselection.h @@ -0,0 +1,31 @@ +#pragma once + +#include "core/sprite.h" +#include "core/color.h" +#include "core/rectangle.h" + +#include + +class ClassicSprite; + +class ClassicSelection : public kku::Sprite +{ +public: + + struct Init + { + std::shared_ptr shape; + kku::Color color; + }; + + explicit ClassicSelection(ClassicSelection::Init&& init); + virtual void reset() override; + virtual void display() const override; + + void adjustTo(const std::shared_ptr& sprite); + void toggle(bool selected); + +protected: + kku::Color _fill_color; + std::shared_ptr _shape; +}; diff --git a/src/modes/classicmode/graphics/classicsprite.cpp b/src/modes/classicmode/graphics/classicsprite.cpp new file mode 100644 index 0000000..5fc94f6 --- /dev/null +++ b/src/modes/classicmode/graphics/classicsprite.cpp @@ -0,0 +1,70 @@ +#include "classicsprite.h" + +ClassicSprite::ClassicSprite(ClassicSprite::Init&& init) : + _reset_color(init.color), + _shape(init.shape), + _trail(init.trail) +{ + _shape->setColor(init.color); + _trail->setColor(init.color); +} + +void ClassicSprite::reset() +{ + _shape->setPosition(kku::Point{0, 0}); + _trail->setPosition(kku::Point{0, 0}); + + _shape->setColor(_reset_color); + _trail->setColor(_reset_color); +} + +void ClassicSprite::setPosition(const kku::Point& position) +{ + _shape->setPosition(position); +} + +void ClassicSprite::setTrailPosition(const kku::Point &position) +{ + _trail->setPosition(position); +} + +kku::Point ClassicSprite::getPosition() const +{ + return _shape->getPosition(); +} + +kku::Point ClassicSprite::getTrailPosition() const +{ + return _trail->getPosition(); +} + +void ClassicSprite::setColor(const kku::Color& color) +{ + _shape->setColor(color); +} + +void ClassicSprite::setTrailColor(const kku::Color& color) +{ + _trail->setColor(color); +} + +kku::Color ClassicSprite::getColor() const +{ + return _shape->getColor(); +} + +kku::Color ClassicSprite::getTrailColor() const +{ + return _trail->getColor(); +} + +void ClassicSprite::display() const +{ + _shape->display(); + _trail->display(); +} + +std::shared_ptr ClassicSprite::getRectangle() const +{ + return _shape; +} diff --git a/src/modes/classicmode/graphics/classicsprite.h b/src/modes/classicmode/graphics/classicsprite.h index 4ea04e6..40f7e0a 100644 --- a/src/modes/classicmode/graphics/classicsprite.h +++ b/src/modes/classicmode/graphics/classicsprite.h @@ -3,22 +3,39 @@ #include "core/sprite.h" #include "core/point.h" #include "core/color.h" +#include "core/rectangle.h" #include class ClassicSprite : public kku::Sprite { public: - virtual void reset() override = 0; - virtual void display() const override = 0; - - virtual void setPosition(const kku::Point &position) = 0; - virtual void setTrailPosition(const kku::Point &position) = 0; - virtual kku::Point getPosition() const = 0; - virtual kku::Point getTrailPosition() const = 0; - - virtual void setColor(const kku::Color& color) = 0; - virtual void setTrailColor(const kku::Color& color) = 0; - virtual kku::Color getColor() const = 0; - virtual kku::Color getTrailColor() const = 0; + + struct Init + { + std::shared_ptr shape; + std::shared_ptr trail; + kku::Color color; + }; + + explicit ClassicSprite(ClassicSprite::Init&& init); + virtual void reset() override; + virtual void display() const override; + + virtual void setPosition(const kku::Point &position); + virtual void setTrailPosition(const kku::Point &position); + virtual kku::Point getPosition() const; + virtual kku::Point getTrailPosition() const; + + virtual void setColor(const kku::Color& color); + virtual void setTrailColor(const kku::Color& color); + virtual kku::Color getColor() const; + virtual kku::Color getTrailColor() const; + + std::shared_ptr getRectangle() const; + +protected: + kku::Color _reset_color; + std::shared_ptr _shape; + std::shared_ptr _trail; }; diff --git a/src/modes/classicmode/graphics/classicspritefactory.h b/src/modes/classicmode/graphics/classicspritefactory.h deleted file mode 100644 index 397300c..0000000 --- a/src/modes/classicmode/graphics/classicspritefactory.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -#include "classicmode/classicactions.h" -#include "graphics/classicsprite.h" - -class ClassicSpriteFactory -{ -public: - virtual ~ClassicSpriteFactory() = default; - virtual std::shared_ptr create(Type type) const = 0; -}; diff --git a/src/modes/classicmode/graphics/classictimelinegraphicsmanager.cpp b/src/modes/classicmode/graphics/classictimelinegraphicsmanager.cpp deleted file mode 100644 index a3abe47..0000000 --- a/src/modes/classicmode/graphics/classictimelinegraphicsmanager.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "classictimelinegraphicsmanager.h" -#include "graphics/classicsprite.h" - -#include "game/arrowelement.h" - -#include "graphics/animations/classicflyinganimationscenario.h" -#include "graphics/animations/classicdyinganimationscenario.h" - -ClassicTimelineGraphicsManager::ClassicTimelineGraphicsManager(const std::shared_ptr>& timeline, - const std::shared_ptr& factory, - const kku::microsec& visibility_offset) : - ClassicGraphicsManager(factory, visibility_offset), - _timeline(timeline), - _display_offset(0) -{ - _timeline->expire(_first); - _timeline->expire(_last); - - _sprites[Type::NONE] = nullptr; - _sprites[Type::UP] = factory->getSprite(Type::UP); - _sprites[Type::RIGHT] = factory->getSprite(Type::RIGHT); - _sprites[Type::DOWN] = factory->getSprite(Type::DOWN); - _sprites[Type::LEFT] = factory->getSprite(Type::LEFT); - //_sprites[Type::SLIDER_RIGHT] = factory->getSprite(Type::SLIDER_RIGHT); - //_sprites[Type::SLIDER_LEFT] = factory->getSprite(Type::SLIDER_LEFT); -} - -void ClassicTimelineGraphicsManager::display() const -{ - if (nothingToDraw()) - return; - - for (auto it = _first; it != _last; ++it) - { - const auto& note = (*it); - note->display(this); - } -} - -void ClassicTimelineGraphicsManager::update(const kku::microsec &offset) -{ - _timeline->expire(_first); - _timeline->expire(_last); - - fetchLastNote(offset); - fetchFirstNote(offset); - - _display_offset = offset; -} - -void ClassicTimelineGraphicsManager::display(const std::vector& elements) const -{ - for (std::size_t i = 0; i < elements.size(); ++i) - { - auto sprite = *_sprites.at(elements.at(i).type) - - if (i >= 1) - { - //const auto& neighbor_sprite = elements[i - 1].sprite; - - //const auto c1 = neighbor_sprite->trailPosition(); - //const auto c2 = sprite->trailPosition(); - - //_render_target->draw(makeLine(c1, c2)); - } - - sprite->setPosition(kku::Position{}); - sprite->display(); - } -} - -void ClassicTimelineGraphicsManager::fetchFirstNote(const kku::microsec& offset) -{ - if (nothingToDraw()) - return; - - Iterator note_iterator = _first; - while (!_timeline->isExpired(note_iterator) && isVisiblyClose(note_iterator, offset)) - { - --note_iterator; - } - - _first = note_iterator; -} - -void ClassicTimelineGraphicsManager::fetchLastNote(const kku::microsec& offset) -{ - Iterator note_iterator = _timeline->getTopNote(); - while (!_timeline->isExpired(note_iterator) && isVisiblyClose(note_iterator, offset)) - { - if (nothingToDraw()) - _first = note_iterator; - - ++note_iterator; - } - - _last = note_iterator; -} - -bool ClassicTimelineGraphicsManager::nothingToDraw() const noexcept -{ - return _timeline->isExpired(_first) - || _timeline->isExpired(_last); -} - -bool ClassicTimelineGraphicsManager::isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept -{ - const auto& perfect_offset = (*iterator)->getPerfectOffset(); - - return ((perfect_offset - _visibility_offset) <= music_offset) - || ((perfect_offset + (_visibility_offset / 4.)) >= music_offset); -} diff --git a/src/modes/classicmode/graphics/classictimelinegraphicsmanager.h b/src/modes/classicmode/graphics/classictimelinegraphicsmanager.h deleted file mode 100644 index 4ef9aa6..0000000 --- a/src/modes/classicmode/graphics/classictimelinegraphicsmanager.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "game/classicnote.h" -#include "graphics/classicgraphicsmanager.h" -#include "core/timeline.h" - -class ClassicSprite; - -class ClassicTimelineGraphicsManager : public ClassicGraphicsManager -{ -public: - explicit ClassicTimelineGraphicsManager(const std::shared_ptr>& timeline, - const std::shared_ptr& factory, - const kku::microsec& visibility_offset); - - virtual void display() const override; - virtual void update(const kku::microsec& offset) override; - - virtual void display(const std::vector& elements) const override; - -protected: - using Iterator = kku::Timeline::Iterator; - - Iterator _first; - Iterator _last; - - const std::shared_ptr> _timeline; - kku::microsec _display_offset; - - mutable std::map, Type::COUNT> _sprites; - - inline bool nothingToDraw() const noexcept; - inline bool isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept; - - void fetchFirstNote(const kku::microsec& offset); - void fetchLastNote(const kku::microsec& offset); -}; diff --git a/src/modes/classicmode/graphics/painters/classicnotepainter.h b/src/modes/classicmode/graphics/painters/classicnotepainter.h deleted file mode 100644 index 676bcb3..0000000 --- a/src/modes/classicmode/graphics/painters/classicnotepainter.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include -#include - -class ClassicNotePainter -{ - virtual ~ClassicNotePainter() = default; -}; diff --git a/src/modes/classicmode/shared/classicmode/classicfactory.h b/src/modes/classicmode/shared/classicmode/classicfactory.h index 194fa9f..4d944eb 100644 --- a/src/modes/classicmode/shared/classicmode/classicfactory.h +++ b/src/modes/classicmode/shared/classicmode/classicfactory.h @@ -4,11 +4,12 @@ #include "core/game.h" #include "core/editor.h" +#include "core/corefactory.h" -class ClassicFactory +namespace classic { -public: - virtual ~ClassicFactory() = default; - virtual std::unique_ptr getGame() const = 0; - virtual std::unique_ptr getEditor() const = 0; -}; + +std::unique_ptr getGame(const std::shared_ptr& core_factory); +std::unique_ptr getEditor(const std::shared_ptr& core_factory); + +} diff --git a/src/tools/src/beatutils.cpp b/src/tools/src/beatutils.cpp index 0fa5112..52b1fb9 100644 --- a/src/tools/src/beatutils.cpp +++ b/src/tools/src/beatutils.cpp @@ -7,11 +7,10 @@ auto beat_utils::calculateBeatRateInfo(const std::vector& approxi if (approximate_deltas.empty()) return {}; - const kku::microsec sum = std::accumulate(approximate_deltas.begin(), approximate_deltas.end(), 0); - const std::size_t amount = approximate_deltas.size(); + const long double sum = std::accumulate(approximate_deltas.begin(), approximate_deltas.end(), 0); + const long double amount = approximate_deltas.size(); - long double average = static_cast(sum) - / static_cast(amount); + long double average = sum / amount; const int bpm = static_cast(60000000. / average);