forked from NaiJi/project-kyoku
Add Note
This commit is contained in:
parent
5b1a00adeb
commit
bf8e6be88f
|
@ -4,16 +4,22 @@ project(project-kyoku LANGUAGES CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(SOURCES application.cpp main.cpp)
|
set(SOURCES application.cpp note.cpp main.cpp)
|
||||||
set(HEADER_FILES application.h)
|
set(HEADER_FILES application.h note.h)
|
||||||
|
|
||||||
# STATIC #
|
# STATIC #
|
||||||
# You need to build SFML from sources with cmake
|
# You need to build SFML from sources with cmake
|
||||||
set(SFML_LIB_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-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-system.so.2.5
|
||||||
${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-window.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)
|
#set(SFML_INCL_DIR ${CMAKE_SOURCE_DIR}/SFML-2.5.1/include)
|
||||||
include_directories(${SFML_INCL_DIR})
|
#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} )
|
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)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include <SFML/Graphics/Color.hpp>
|
#include <SFML/Graphics/Color.hpp>
|
||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
|
#include <SFML/Window/Keyboard.hpp>
|
||||||
|
|
||||||
|
const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 60.f);
|
||||||
|
|
||||||
Application::Application() :
|
Application::Application() :
|
||||||
game_window({1280, 720}, "Test")
|
game_window({1280, 720}, "Test")
|
||||||
|
@ -10,24 +13,37 @@ Application::Application() :
|
||||||
pulse_mask.setSize({x, y});
|
pulse_mask.setSize({x, y});
|
||||||
pulse_mask.setOrigin(0.f, 0.f);
|
pulse_mask.setOrigin(0.f, 0.f);
|
||||||
pulse_mask.setFillColor(sf::Color(255, 0, 0, 0));
|
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()
|
void Application::run()
|
||||||
{
|
{
|
||||||
game_window.display();
|
game_window.display();
|
||||||
timeline.push(5500000);
|
sf::Int64 iter = 9000 + (1412162 * 25);
|
||||||
timeline.push(5000000);
|
while (iter > 9000)
|
||||||
timeline.push(4500000);
|
{
|
||||||
timeline.push(4000000);
|
Note note(iter, iter + 412162);
|
||||||
timeline.push(3500000);
|
timeline.push(note);
|
||||||
timeline.push(3000000);
|
iter -= 1412162;
|
||||||
timeline.push(2500000);
|
}
|
||||||
timeline.push(2000000);
|
|
||||||
timeline.push(1500000);
|
sf::Clock timer;
|
||||||
timeline.push(1000000);
|
sf::Time time_since_last_update = sf::Time::Zero;
|
||||||
//music.openFromFile("/home/egor/test.flac");
|
music.openFromFile("/home/naiji/METEOR.flac");
|
||||||
//usic.play();
|
music.play();
|
||||||
music.restart();
|
|
||||||
while (game_window.isOpen())
|
while (game_window.isOpen())
|
||||||
{
|
{
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
|
@ -35,25 +51,65 @@ void Application::run()
|
||||||
{
|
{
|
||||||
if (event.type == sf::Event::Closed)
|
if (event.type == sf::Event::Closed)
|
||||||
game_window.close();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
time_since_last_update += timer.restart();
|
||||||
|
if (time_since_last_update >= TIME_PER_FRAME)
|
||||||
|
{
|
||||||
|
time_since_last_update -= TIME_PER_FRAME;
|
||||||
update();
|
update();
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::update()
|
void Application::update()
|
||||||
{
|
{
|
||||||
if (!timeline.empty() && timeline.top() <= music.getElapsedTime().asMicroseconds())
|
if (!timeline.empty() && timeline.top().deathOffset() <= music.getPlayingOffset().asMicroseconds())
|
||||||
{
|
{
|
||||||
timeline.pop();
|
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)
|
if (pulse_mask.getFillColor().a > 0)
|
||||||
{
|
{
|
||||||
const auto alpha = pulse_mask.getFillColor().a - 1;
|
const auto alpha = pulse_mask.getFillColor().a - 25;
|
||||||
pulse_mask.setFillColor(sf::Color(255, 0, 0, alpha));
|
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.clear();
|
||||||
game_window.draw(pulse_mask);
|
game_window.draw(pulse_mask);
|
||||||
|
game_window.draw(pulse_mask_green);
|
||||||
|
game_window.draw(text);
|
||||||
|
game_window.draw(grade);
|
||||||
game_window.display();
|
game_window.display();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,16 @@
|
||||||
#define APPLICATION_H
|
#define APPLICATION_H
|
||||||
|
|
||||||
#include <SFML/Graphics/RenderWindow.hpp>
|
#include <SFML/Graphics/RenderWindow.hpp>
|
||||||
//#include <SFML/Audio/Music.hpp>
|
#include <SFML/Audio/Music.hpp>
|
||||||
#include <SFML/System/Clock.hpp>
|
#include <SFML/System/Clock.hpp>
|
||||||
|
#include <SFML/Graphics/Text.hpp>
|
||||||
|
#include <SFML/Graphics/Font.hpp>
|
||||||
#include <SFML/Graphics/RectangleShape.hpp>
|
#include <SFML/Graphics/RectangleShape.hpp>
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
|
#include "note.h"
|
||||||
|
|
||||||
class Application
|
class Application
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -18,11 +22,17 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sf::RenderWindow game_window;
|
sf::RenderWindow game_window;
|
||||||
sf::Clock music;
|
sf::Music music;
|
||||||
//sf::Music music;
|
|
||||||
sf::RectangleShape pulse_mask;
|
sf::RectangleShape pulse_mask;
|
||||||
|
sf::RectangleShape pulse_mask_green;
|
||||||
|
|
||||||
std::stack<sf::Int64> timeline;
|
std::stack<Note> 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
|
#endif // APPLICATION_H
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "note.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef NOTE_H
|
||||||
|
#define NOTE_H
|
||||||
|
|
||||||
|
#include <SFML/System/Clock.hpp>
|
||||||
|
|
||||||
|
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
|
Loading…
Reference in New Issue