forked from NaiJi/project-kyoku
Implement PrecisionEvaluator for evaluating player input
This commit is contained in:
parent
76a69b534d
commit
89e9002b5e
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef GAME_H
|
||||||
|
#define GAME_H
|
||||||
|
|
||||||
|
#include <SFML/Graphics/RenderWindow.hpp>
|
||||||
|
#include <SFML/Window/Event.hpp>
|
||||||
|
|
||||||
|
class Game
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Game() = default;
|
||||||
|
|
||||||
|
virtual void run() = 0;
|
||||||
|
|
||||||
|
virtual void input(const sf::Event& event) = 0;
|
||||||
|
virtual void update() = 0;
|
||||||
|
virtual void draw(const sf::RenderWindow& window) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GAME_H
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef PRECISIONEVALUATOR_H
|
|
||||||
#define PRECISIONEVALUATOR_H
|
|
||||||
|
|
||||||
#include <SFML/System/Clock.hpp>
|
|
||||||
|
|
||||||
using microsec = sf::Int64;
|
|
||||||
|
|
||||||
template<typename GRADE>
|
|
||||||
class PrecisionEvaluator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
PrecisionEvaluator(microsec offset, microsec life_span_offset);
|
|
||||||
|
|
||||||
microsec offset() const noexcept;
|
|
||||||
bool isActive(microsec music_play_offset) const noexcept;
|
|
||||||
GRADE calculatePrecision(microsec odds) const;
|
|
||||||
|
|
||||||
static void resetPrecisionQualifier(microsec qualifier = 500000);
|
|
||||||
|
|
||||||
private:
|
|
||||||
microsec _offset;
|
|
||||||
microsec _start_handling_offset;
|
|
||||||
microsec _end_handling_offset;
|
|
||||||
|
|
||||||
static microsec _precision_qualifier;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PRECISIONEVALUATOR_H
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef PRECISIONEVALUATOR_H
|
||||||
|
#define PRECISIONEVALUATOR_H
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <SFML/System/Clock.hpp>
|
||||||
|
|
||||||
|
using microsec = sf::Int64;
|
||||||
|
|
||||||
|
template<typename GRADE, typename = std::enable_if_t<std::is_enum<GRADE>::value>>
|
||||||
|
class PrecisionEvaluator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrecisionEvaluator(std::vector<microsec>&& intervals, microsec offset) :
|
||||||
|
_offset(offset),
|
||||||
|
_intervals(std::move(intervals))
|
||||||
|
{
|
||||||
|
microsec&& handling_offset = std::accumulate(intervals.begin(), intervals.end(), 0);
|
||||||
|
_start_handling_offset = _offset - handling_offset;
|
||||||
|
_end_handling_offset = _offset + handling_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline microsec offset() const noexcept
|
||||||
|
{
|
||||||
|
return _offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isActive(microsec music_play_offset) const noexcept
|
||||||
|
{
|
||||||
|
return music_play_offset > _start_handling_offset
|
||||||
|
&& music_play_offset < _end_handling_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GRADE calculatePrecision(microsec odds) const
|
||||||
|
{
|
||||||
|
microsec shift_from_perfect = std::abs(odds - offset());
|
||||||
|
|
||||||
|
std::size_t raw_grade;
|
||||||
|
for (raw_grade = 0; raw_grade < _intervals.size(); ++raw_grade)
|
||||||
|
{
|
||||||
|
if (shift_from_perfect <= _intervals[raw_grade])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<GRADE>(raw_grade);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
microsec _offset;
|
||||||
|
microsec _start_handling_offset;
|
||||||
|
microsec _end_handling_offset;
|
||||||
|
|
||||||
|
/* Amount of values in enum instanced as GRADES
|
||||||
|
* represents capacity of _intervals.
|
||||||
|
* So, for each V value in GRADES enum, _intervals[V]
|
||||||
|
* should return time shift from V - 1.
|
||||||
|
* V0 is PERFECT SCORE and the last V represents the worst
|
||||||
|
* grades which is death of note by expiration */
|
||||||
|
|
||||||
|
std::vector<microsec> _intervals;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PRECISIONEVALUATOR_H
|
|
@ -173,9 +173,5 @@ void Application::update()
|
||||||
|
|
||||||
void Application::draw()
|
void Application::draw()
|
||||||
{
|
{
|
||||||
_game_window.clear();
|
|
||||||
_game_window.draw(*_timeline);
|
|
||||||
_game_window.draw(_debug);
|
|
||||||
_game_window.draw(_grade);
|
|
||||||
_game_window.display();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "classicgame.h"
|
||||||
|
|
||||||
|
ClassicGame::ClassicGame()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef CLASSICGAME_H
|
||||||
|
#define CLASSICGAME_H
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
class ClassicGame : public Game
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ClassicGame();
|
||||||
|
virtual ~ClassicGame() override;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
virtual void input(const sf::Event& event) override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void draw(const sf::RenderWindow& window) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CLASSICGAME_H
|
80
src/note.cpp
80
src/note.cpp
|
@ -1,80 +0,0 @@
|
||||||
#include "note.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
Note::Note(microsec offset, microsec life_span_offset, Note::Arrow type) :
|
|
||||||
_offset(offset),
|
|
||||||
_start_handling_offset(_offset - life_span_offset),
|
|
||||||
_end_handling_offset(_offset + life_span_offset),
|
|
||||||
_type(type)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void Note::setPosition(coordinates position)
|
|
||||||
{
|
|
||||||
_position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
coordinates Note::position() const noexcept
|
|
||||||
{
|
|
||||||
return _position;
|
|
||||||
}
|
|
||||||
|
|
||||||
microsec Note::offset() const noexcept
|
|
||||||
{
|
|
||||||
return _offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
NoteGrade Note::onTap(Arrow arrow_type, microsec tap_time_stamp)
|
|
||||||
{
|
|
||||||
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(0, NoteGrade::Rating::BAD);
|
|
||||||
|
|
||||||
if (odds < _precision_qualifier)
|
|
||||||
{
|
|
||||||
ret = {50, NoteGrade::Rating::GREAT};
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Note::isActive(microsec music_play_offset) const noexcept
|
|
||||||
{
|
|
||||||
return music_play_offset > _start_handling_offset
|
|
||||||
&& music_play_offset < _end_handling_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Note::resetPrecisionQualifier(microsec qualifier)
|
|
||||||
{
|
|
||||||
_precision_qualifier = qualifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Note::resetSprite(const std::shared_ptr<Sprite> &sprite) noexcept
|
|
||||||
{
|
|
||||||
if (_sprite)
|
|
||||||
_sprite->setAttachment(false);
|
|
||||||
|
|
||||||
_sprite = sprite;
|
|
||||||
|
|
||||||
if (_sprite)
|
|
||||||
_sprite->setAttachment(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Note::Arrow Note::type() const noexcept
|
|
||||||
{
|
|
||||||
return _type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Note::draw(sf::RenderTarget &target, sf::RenderStates states) const
|
|
||||||
{
|
|
||||||
target.draw(*_sprite, states);
|
|
||||||
}
|
|
||||||
|
|
||||||
microsec Note::_precision_qualifier = 500000; // Default initialization as 0.5 second.
|
|
Loading…
Reference in New Issue