From bf8e6be88f4878c30c55d4799cdf2090c45a5c5b Mon Sep 17 00:00:00 2001 From: NaiJi Date: Sun, 4 Apr 2021 23:43:12 +0300 Subject: [PATCH] Add Note --- CMakeLists.txt | 24 +++++++----- application.cpp | 97 +++++++++++++++++++++++++++++++++++++++---------- application.h | 18 +++++++-- note.cpp | 34 +++++++++++++++++ note.h | 45 +++++++++++++++++++++++ 5 files changed, 186 insertions(+), 32 deletions(-) create mode 100644 note.cpp create mode 100644 note.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d7a25d..39acc9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,16 +4,22 @@ project(project-kyoku LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(SOURCES application.cpp main.cpp) -set(HEADER_FILES application.h) +set(SOURCES application.cpp note.cpp main.cpp) +set(HEADER_FILES application.h note.h) # STATIC # # You need to build SFML from sources with cmake -set(SFML_LIB_DIR - ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-graphics.so.2.5 - ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-system.so.2.5 - ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-window.so.2.5) -set(SFML_INCL_DIR ${CMAKE_SOURCE_DIR}/SFML-2.5.1/include) -include_directories(${SFML_INCL_DIR}) +#set(SFML_LIB_DIR +# ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-graphics.so.2.5 +# ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-system.so.2.5 +# ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-window.so.2.5) +#set(SFML_INCL_DIR ${CMAKE_SOURCE_DIR}/SFML-2.5.1/include) +#include_directories(${SFML_INCL_DIR}) +#add_executable(project-kyoku ${SOURCES} ${HEADER_FILES} ) +#target_link_libraries(project-kyoku ${SFML_LIB_DIR}) + +# DYNAMIC # +# You only need to install SFML from your package manager +find_package(SFML REQUIRED graphics window system) add_executable(project-kyoku ${SOURCES} ${HEADER_FILES} ) -target_link_libraries(project-kyoku ${SFML_LIB_DIR}) +target_link_libraries(project-kyoku sfml-system sfml-audio sfml-graphics sfml-network) diff --git a/application.cpp b/application.cpp index 6faa52a..269cb64 100644 --- a/application.cpp +++ b/application.cpp @@ -1,6 +1,9 @@ #include "application.h" #include #include +#include + +const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 60.f); Application::Application() : game_window({1280, 720}, "Test") @@ -10,24 +13,37 @@ Application::Application() : pulse_mask.setSize({x, y}); pulse_mask.setOrigin(0.f, 0.f); pulse_mask.setFillColor(sf::Color(255, 0, 0, 0)); + pulse_mask_green.setSize({x, y}); + pulse_mask_green.setOrigin(0.f, 0.f); + pulse_mask_green.setFillColor(sf::Color(0, 255, 0, 0)); + font.loadFromFile("VeraMono.ttf"); + font2.loadFromFile("VeraMono.ttf"); + text.setFont(font); + text.setPosition(60, 60); + text.setFillColor(sf::Color(255, 255, 255)); + text.setCharacterSize(25); + + grade.setFont(font2); + grade.setPosition(100, 100); + grade.setFillColor(sf::Color(255, 255, 255, 0)); + grade.setCharacterSize(35); } void Application::run() { game_window.display(); - timeline.push(5500000); - timeline.push(5000000); - timeline.push(4500000); - timeline.push(4000000); - timeline.push(3500000); - timeline.push(3000000); - timeline.push(2500000); - timeline.push(2000000); - timeline.push(1500000); - timeline.push(1000000); - //music.openFromFile("/home/egor/test.flac"); - //usic.play(); - music.restart(); + sf::Int64 iter = 9000 + (1412162 * 25); + while (iter > 9000) + { + Note note(iter, iter + 412162); + timeline.push(note); + iter -= 1412162; + } + + sf::Clock timer; + sf::Time time_since_last_update = sf::Time::Zero; + music.openFromFile("/home/naiji/METEOR.flac"); + music.play(); while (game_window.isOpen()) { sf::Event event; @@ -35,25 +51,65 @@ void Application::run() { if (event.type == sf::Event::Closed) game_window.close(); + + if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Z && !timeline.empty()) + { + const auto current_note = timeline.top(); + const auto grade_result = current_note.onTap(Note::Arrow::UP, music.getPlayingOffset().asMicroseconds()); + pulse_mask.setFillColor(sf::Color(255, 0, 0, 255)); + switch (grade_result.rating) + { + case (NoteGrade::Rating::BAD): + grade.setString("BAD"); + grade.setFillColor(sf::Color(255, 255, 255, 255)); + break; + + case (NoteGrade::Rating::GREAT): + grade.setString("GREAT"); + grade.setFillColor(sf::Color(255, 255, 0, 255)); + break; + } + + } + } - update(); - draw(); + time_since_last_update += timer.restart(); + if (time_since_last_update >= TIME_PER_FRAME) + { + time_since_last_update -= TIME_PER_FRAME; + update(); + draw(); + } } } void Application::update() { - if (!timeline.empty() && timeline.top() <= music.getElapsedTime().asMicroseconds()) + if (!timeline.empty() && timeline.top().deathOffset() <= music.getPlayingOffset().asMicroseconds()) { timeline.pop(); - pulse_mask.setFillColor(sf::Color(255, 0, 0, 255)); + pulse_mask_green.setFillColor(sf::Color(0, 255, 0, 255)); } + text.setString(std::to_string(music.getPlayingOffset().asSeconds())); + if (pulse_mask.getFillColor().a > 0) { - const auto alpha = pulse_mask.getFillColor().a - 1; - pulse_mask.setFillColor(sf::Color(255, 0, 0, alpha)); + const auto alpha = pulse_mask.getFillColor().a - 25; + pulse_mask.setFillColor(sf::Color(255, 0, 0, alpha < 0 ? 0 : alpha)); + } + + if (pulse_mask_green.getFillColor().a > 0) + { + const auto alpha = pulse_mask_green.getFillColor().a - 25; + pulse_mask_green.setFillColor(sf::Color(0, 255, 0, alpha < 0 ? 0 : alpha)); + } + + if (grade.getFillColor().a > 0) + { + const auto alpha = grade.getFillColor().a - 20; + grade.setFillColor(sf::Color(255, 255, 255, alpha < 0 ? 0 : alpha)); } } @@ -62,5 +118,8 @@ void Application::draw() { game_window.clear(); game_window.draw(pulse_mask); + game_window.draw(pulse_mask_green); + game_window.draw(text); + game_window.draw(grade); game_window.display(); } diff --git a/application.h b/application.h index c0499f3..c937a94 100644 --- a/application.h +++ b/application.h @@ -2,12 +2,16 @@ #define APPLICATION_H #include -//#include +#include #include +#include +#include #include #include +#include "note.h" + class Application { public: @@ -18,11 +22,17 @@ public: private: sf::RenderWindow game_window; - sf::Clock music; - //sf::Music music; + sf::Music music; sf::RectangleShape pulse_mask; + sf::RectangleShape pulse_mask_green; - std::stack timeline; + std::stack timeline; + sf::Int64 time_since_last_tick; + sf::Int64 last_stamp; + sf::Font font; + sf::Font font2; + sf::Text text; + sf::Text grade; }; #endif // APPLICATION_H diff --git a/note.cpp b/note.cpp new file mode 100644 index 0000000..3f97888 --- /dev/null +++ b/note.cpp @@ -0,0 +1,34 @@ +#include "note.h" +#include + +Note::Note(microsec offset, microsec death_offset, Note::Arrow type) : + _offset(offset), + _death_offset(death_offset), + _type(type) +{} + +microsec Note::deathOffset() const noexcept +{ + return _death_offset; +} + +NoteGrade Note::onTap(Arrow arrow_type, microsec tap_time_stamp) const +{ + 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; + if (odds < 500000) + { + ret.score = 50; + ret.rating = NoteGrade::Rating::GREAT; + } + + return ret; +} diff --git a/note.h b/note.h new file mode 100644 index 0000000..7844cad --- /dev/null +++ b/note.h @@ -0,0 +1,45 @@ +#ifndef NOTE_H +#define NOTE_H + +#include + +using microsec = sf::Int64; + +struct NoteGrade +{ + int score = 0; + enum class Rating + { + WRONG, + BAD, + GOOD, + GREAT + } rating = Rating::BAD; +}; + +class Note +{ +public: + enum class Arrow + { + UP, + RIGHT, + DOWN, + LEFT + }; + + Note(microsec offset, microsec death_offset, Note::Arrow type = Note::Arrow::UP); + + NoteGrade onTap(Arrow arrow_type, microsec tap_time_stamp) const; + microsec deathOffset() const noexcept; + + +private: + microsec _offset; + microsec _death_offset; + Arrow _type = Arrow::UP; + + NoteGrade calculatePrecision(microsec odds) const; +}; + +#endif // NOTE_H