forked from NaiJi/project-kyoku
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/System/Clock.hpp>
|
||||||
#include <SFML/Window/Keyboard.hpp>
|
#include <SFML/Window/Keyboard.hpp>
|
||||||
|
|
||||||
#include "debughelper.h"
|
|
||||||
#include "timeline.h"
|
#include "timeline.h"
|
||||||
#include "note.h"
|
#include "note.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
@ -13,7 +12,6 @@ class Application
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Application();
|
Application();
|
||||||
~Application();
|
|
||||||
void run();
|
void run();
|
||||||
void input();
|
void input();
|
||||||
void update();
|
void update();
|
||||||
|
@ -21,13 +19,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sf::RenderWindow _game_window;
|
sf::RenderWindow _game_window;
|
||||||
|
|
||||||
sf::Font _font;
|
|
||||||
sf::Text _grade;
|
|
||||||
|
|
||||||
std::unique_ptr<Timeline> _timeline;
|
std::unique_ptr<Timeline> _timeline;
|
||||||
DebugHelper _debug;
|
|
||||||
|
|
||||||
std::unique_ptr<Game> _game;
|
std::unique_ptr<Game> _game;
|
||||||
|
|
||||||
void exec();
|
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() :
|
Application::Application() :
|
||||||
_game_window({1280, 720}, "Test"),
|
_game_window({1280, 720}, "Test"),
|
||||||
_debug(true),
|
|
||||||
_game(std::make_unique<ClassicGame>())
|
_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()
|
void Application::run()
|
||||||
|
|
|
@ -8,7 +8,6 @@ ClassicGame::ClassicGame() :
|
||||||
_timeline(std::make_unique<ClassicTimeline>()),
|
_timeline(std::make_unique<ClassicTimeline>()),
|
||||||
_view_manager(std::make_unique<ClassicViewManager>())
|
_view_manager(std::make_unique<ClassicViewManager>())
|
||||||
{
|
{
|
||||||
_font.loadFromFile("VeraMono.ttf");
|
|
||||||
_keys_to_buttons =
|
_keys_to_buttons =
|
||||||
{
|
{
|
||||||
{sf::Keyboard::Up, Button::UP}, // Load from settings
|
{sf::Keyboard::Up, Button::UP}, // Load from settings
|
||||||
|
@ -83,25 +82,9 @@ void ClassicGame::input(const sf::Event& event)
|
||||||
|
|
||||||
auto note = _timeline->getActiveNote();
|
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));
|
(*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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,24 +102,9 @@ void ClassicGame::update()
|
||||||
{
|
{
|
||||||
_timeline->update();
|
_timeline->update();
|
||||||
_timeline->fetchVisibleNotes(_view_manager);
|
_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
|
void ClassicGame::draw(sf::RenderWindow& window) const
|
||||||
{
|
{
|
||||||
_timeline->drawVisibleNotes(window);
|
_timeline->drawVisibleNotes(window);
|
||||||
|
|
||||||
for (auto& grade : _grades)
|
|
||||||
{
|
|
||||||
window.draw(grade);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <SFML/Graphics/Text.hpp>
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "classicactions.h"
|
#include "classicactions.h"
|
||||||
|
|
||||||
|
@ -32,9 +31,6 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<ClassicTimeline> _timeline;
|
std::unique_ptr<ClassicTimeline> _timeline;
|
||||||
std::unique_ptr<ClassicViewManager> _view_manager;
|
std::unique_ptr<ClassicViewManager> _view_manager;
|
||||||
|
|
||||||
sf::Font _font;
|
|
||||||
std::list<sf::Text> _grades;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLASSICGAME_H
|
#endif // CLASSICGAME_H
|
||||||
|
|
|
@ -34,7 +34,11 @@ void ClassicNote::update(const microsec& music_offset)
|
||||||
int xb = getPt( 1280./2. , _coordinates.x , i );
|
int xb = getPt( 1280./2. , _coordinates.x , i );
|
||||||
int yb = getPt( 720./2. , _coordinates.y , 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
|
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";
|
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
||||||
_state = State::DEAD;
|
_state = State::DYING;
|
||||||
|
_sprite->showGrade();
|
||||||
return grade;
|
return grade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,53 @@
|
||||||
#include "classicsprite.h"
|
#include "classicsprite.h"
|
||||||
#include <SFML/Graphics/RenderTarget.hpp>
|
#include <SFML/Graphics/RenderTarget.hpp>
|
||||||
|
|
||||||
ClassicSprite::ClassicSprite(const sf::RectangleShape& shape) :
|
ClassicSprite::ClassicSprite(const sf::RectangleShape& shape, const sf::Font& font) :
|
||||||
_shape(shape),
|
_shape(shape),
|
||||||
_trail(shape)
|
_trail(shape),
|
||||||
{}
|
_font(font)
|
||||||
|
{
|
||||||
|
_grade_text.setFont(_font);
|
||||||
|
}
|
||||||
|
|
||||||
void ClassicSprite::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
void ClassicSprite::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||||
{
|
{
|
||||||
target.draw(_shape, states);
|
target.draw(_shape, states);
|
||||||
target.draw(_trail, states);
|
target.draw(_trail, states);
|
||||||
|
target.draw(_grade_text, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicSprite::setCoordinates(float x, float y, float trail_x, float trail_y) noexcept
|
void ClassicSprite::setCoordinates(float x, float y, float trail_x, float trail_y) noexcept
|
||||||
{
|
{
|
||||||
_shape.setPosition(x, y);
|
_shape.setPosition(x, y);
|
||||||
_trail.setPosition(trail_x, trail_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);
|
_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 "sprite.h"
|
||||||
#include "SFML/Graphics/RectangleShape.hpp"
|
#include "SFML/Graphics/RectangleShape.hpp"
|
||||||
|
#include "SFML/Graphics/Text.hpp"
|
||||||
|
|
||||||
class ClassicSprite : public Sprite, public sf::Drawable
|
class ClassicSprite : public Sprite, public sf::Drawable
|
||||||
{
|
{
|
||||||
public:
|
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;
|
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 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:
|
private:
|
||||||
sf::RectangleShape _shape;
|
sf::RectangleShape _shape;
|
||||||
sf::RectangleShape _trail;
|
sf::RectangleShape _trail;
|
||||||
|
sf::Text _grade_text;
|
||||||
|
sf::Font _font;
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,7 +79,8 @@ void ClassicTimeline::update()
|
||||||
|
|
||||||
void ClassicTimeline::checkCurrentActiveNote(const microsec &music_offset)
|
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);
|
expire(_active_note);
|
||||||
++_top_note;
|
++_top_note;
|
||||||
|
@ -124,8 +125,10 @@ void ClassicTimeline::discardExpiredNotes(const std::unique_ptr<ClassicViewManag
|
||||||
Iterator past_note = _top_note - 1;
|
Iterator past_note = _top_note - 1;
|
||||||
std::shared_ptr<ClassicSprite> sprite = (*past_note)->sprite();
|
std::shared_ptr<ClassicSprite> sprite = (*past_note)->sprite();
|
||||||
while (sprite)
|
while (sprite)
|
||||||
{ // CAREFULLY REWRITE
|
{
|
||||||
view_manager->resetNoteSprite(*past_note);
|
auto state = (*past_note)->state();
|
||||||
|
if (state == ClassicNote::State::DEAD || state == ClassicNote::State::FLYING)
|
||||||
|
view_manager->resetNoteSprite(*past_note);
|
||||||
if (past_note == _timeline.begin())
|
if (past_note == _timeline.begin())
|
||||||
return;
|
return;
|
||||||
--past_note;
|
--past_note;
|
||||||
|
@ -154,12 +157,9 @@ void ClassicTimeline::fetchVisibleNotes(const std::unique_ptr<ClassicViewManager
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note->state() == ClassicNote::State::DEAD)
|
if (note->state() == ClassicNote::State::DEAD)
|
||||||
{
|
|
||||||
view_manager->resetNoteSprite(note);
|
view_manager->resetNoteSprite(note);
|
||||||
}
|
|
||||||
else
|
|
||||||
note->update(music_offset);
|
|
||||||
|
|
||||||
|
note->update(music_offset);
|
||||||
++note_iterator;
|
++note_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ ClassicViewManager::ClassicViewManager()
|
||||||
{
|
{
|
||||||
reallocatePoll(kind_of_action);
|
reallocatePoll(kind_of_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_font.loadFromFile("VeraMono.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicViewManager::reallocatePoll(Action kind_of_action)
|
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));
|
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)
|
void ClassicViewManager::initNoteSprite(ClassicNote* note)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <SFML/Graphics/Font.hpp>
|
||||||
|
|
||||||
class ClassicSprite;
|
class ClassicSprite;
|
||||||
class ClassicNote;
|
class ClassicNote;
|
||||||
|
@ -25,6 +26,7 @@ private:
|
||||||
|
|
||||||
using SpritePoll = std::stack<std::shared_ptr<ClassicSprite>>;
|
using SpritePoll = std::stack<std::shared_ptr<ClassicSprite>>;
|
||||||
std::map<Action, SpritePoll> _sprite_dispatcher;
|
std::map<Action, SpritePoll> _sprite_dispatcher;
|
||||||
|
sf::Font _font;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLASSICDIVAVIEWMANAGER_H
|
#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…
Reference in New Issue