forked from NaiJi/project-kyoku
Encapsulate timeline and implement logic on it
parent
47277ee754
commit
367316b327
@ -0,0 +1,66 @@
|
|||||||
|
#include "timeline.h"
|
||||||
|
#include "note.h"
|
||||||
|
|
||||||
|
Timeline::Timeline()
|
||||||
|
{
|
||||||
|
// BPM of METEOR is 170.
|
||||||
|
// Length is 1:14
|
||||||
|
// I calculated that the time between beats is about 1412162 microseconds
|
||||||
|
|
||||||
|
microsec starting_beat_offset = 372162;
|
||||||
|
int amount_of_beats = 209;
|
||||||
|
microsec time_between_beats = 1412162;
|
||||||
|
microsec note_input_offset = 412162;
|
||||||
|
microsec interval = starting_beat_offset + (time_between_beats * amount_of_beats);
|
||||||
|
|
||||||
|
Note::resetPrecisionQualifier(note_input_offset / 2);
|
||||||
|
|
||||||
|
while (interval > 0)
|
||||||
|
{
|
||||||
|
_timeline.emplace_back(new Note(interval, note_input_offset));
|
||||||
|
interval -= time_between_beats;
|
||||||
|
}
|
||||||
|
|
||||||
|
_active_note = nullptr;
|
||||||
|
_top_note = _timeline.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Timeline::~Timeline()
|
||||||
|
{
|
||||||
|
for (auto note : _timeline)
|
||||||
|
delete note;
|
||||||
|
|
||||||
|
_timeline.clear();
|
||||||
|
_top_note = _timeline.end();
|
||||||
|
_active_note = nullptr;
|
||||||
|
|
||||||
|
Note::resetPrecisionQualifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timeline::update(const microsec µseconds)
|
||||||
|
{
|
||||||
|
checkCurrentActiveNote(microseconds);
|
||||||
|
checkForNextActiveNote(microseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timeline::checkCurrentActiveNote(const microsec µseconds)
|
||||||
|
{
|
||||||
|
if (_active_note && !_active_note->isActive(microseconds))
|
||||||
|
{
|
||||||
|
_active_note = nullptr;
|
||||||
|
++_top_note;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timeline::checkForNextActiveNote(const microsec µseconds)
|
||||||
|
{
|
||||||
|
if (!_active_note && (*_top_note)->isActive(microseconds))
|
||||||
|
{
|
||||||
|
_active_note = *_top_note;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Note* Timeline::getActiveNote() const noexcept
|
||||||
|
{
|
||||||
|
return _active_note;
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef TIMELINE_H
|
||||||
|
#define TIMELINE_H
|
||||||
|
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using microsec = sf::Int64;
|
||||||
|
class Note;
|
||||||
|
|
||||||
|
class Timeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Timeline();
|
||||||
|
~Timeline();
|
||||||
|
|
||||||
|
void update(const microsec& microseconds);
|
||||||
|
const Note* getActiveNote() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Note*> _timeline;
|
||||||
|
std::vector<Note*>::iterator _top_note;
|
||||||
|
Note* _active_note;
|
||||||
|
|
||||||
|
void checkCurrentActiveNote(const microsec µseconds);
|
||||||
|
void checkForNextActiveNote(const microsec µseconds);
|
||||||
|
|
||||||
|
/* Difference between top and active note is that
|
||||||
|
* top note is the note handling input right now
|
||||||
|
* OR it's the closest note from current music offset
|
||||||
|
* position, not necessarily active. A note stops being top only
|
||||||
|
* after dying or being tapped by player, even if it's already
|
||||||
|
* past her perfect offset.
|
||||||
|
*
|
||||||
|
* Meanwhile active note is the note which is currently handling
|
||||||
|
* player input for grade.
|
||||||
|
*
|
||||||
|
* An active note is always top note but a top note
|
||||||
|
* is not always active note.
|
||||||
|
* */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TIMELINE_H
|
Loading…
Reference in New Issue