2021-06-23 15:18:33 -04:00
|
|
|
#include "note.h"
|
2021-06-07 14:19:58 -04:00
|
|
|
#include "classictimeline.h"
|
2021-06-23 15:18:33 -04:00
|
|
|
#include <iostream>
|
2021-04-08 15:51:59 -04:00
|
|
|
|
2021-06-07 14:19:58 -04:00
|
|
|
ClassicTimeline::ClassicTimeline()
|
2021-04-08 09:34:03 -04:00
|
|
|
{
|
|
|
|
// BPM of METEOR is 170.
|
|
|
|
// Length is 1:14
|
|
|
|
// I calculated that the time between beats is about 1412162 microseconds
|
|
|
|
|
2021-06-11 12:58:44 -04:00
|
|
|
std::string song_filename = "METEOR.flac";
|
2021-06-08 14:32:36 -04:00
|
|
|
|
|
|
|
_music.openFromFile(song_filename);
|
2021-06-09 14:08:58 -04:00
|
|
|
_music.setVolume(10);
|
2021-06-23 15:18:33 -04:00
|
|
|
}
|
2021-06-08 14:32:36 -04:00
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
void ClassicTimeline::run(std::vector<Note*>&& notes, const microsec& visibility)
|
|
|
|
{
|
|
|
|
_visibility_offset = visibility;
|
|
|
|
_timeline = std::move(notes);
|
2021-04-08 09:34:03 -04:00
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
_top_note = _timeline.begin();
|
2021-06-16 11:16:18 -04:00
|
|
|
expire(_first_visible_note);
|
2021-06-09 18:47:18 -04:00
|
|
|
expire(_last_visible_note);
|
2021-06-08 14:32:36 -04:00
|
|
|
expire(_active_note);
|
2021-04-08 09:34:03 -04:00
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
fetchVisibleNotes();
|
2021-06-09 18:47:18 -04:00
|
|
|
_music.play();
|
2021-06-09 14:08:58 -04:00
|
|
|
}
|
|
|
|
|
2021-06-08 14:32:36 -04:00
|
|
|
ClassicTimeline::~ClassicTimeline()
|
2021-04-09 09:28:45 -04:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
2021-06-08 14:32:36 -04:00
|
|
|
void ClassicTimeline::clear()
|
2021-04-08 09:34:03 -04:00
|
|
|
{
|
2021-06-16 13:11:00 -04:00
|
|
|
for (auto& note : _timeline)
|
2021-04-08 09:34:03 -04:00
|
|
|
delete note;
|
|
|
|
|
|
|
|
_timeline.clear();
|
|
|
|
}
|
|
|
|
|
2021-06-08 14:32:36 -04:00
|
|
|
void ClassicTimeline::update()
|
2021-04-08 09:34:03 -04:00
|
|
|
{
|
2021-06-23 15:18:33 -04:00
|
|
|
const auto& music_offset = currentMusicOffset();
|
|
|
|
checkCurrentActiveNote(music_offset);
|
|
|
|
checkForNextActiveNote(music_offset);
|
|
|
|
updateVisibleSprites(music_offset);
|
2021-04-08 09:34:03 -04:00
|
|
|
}
|
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
void ClassicTimeline::checkCurrentActiveNote(const microsec& music_offset)
|
2021-04-08 09:34:03 -04:00
|
|
|
{
|
2021-06-16 11:16:18 -04:00
|
|
|
if (isExpired(_active_note))
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto note = *_active_note;
|
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
if (!note->isActive(music_offset))
|
2021-04-08 09:34:03 -04:00
|
|
|
{
|
2021-06-08 14:32:36 -04:00
|
|
|
expire(_active_note);
|
2021-04-08 09:34:03 -04:00
|
|
|
++_top_note;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
void ClassicTimeline::checkForNextActiveNote(const microsec& music_offset)
|
2021-04-08 09:34:03 -04:00
|
|
|
{
|
2021-06-16 11:16:18 -04:00
|
|
|
if (!isExpired(_active_note))
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto top_note = *_top_note;
|
2021-06-23 15:18:33 -04:00
|
|
|
if (top_note->isActive(music_offset))
|
2021-06-08 14:32:36 -04:00
|
|
|
_active_note = _top_note;
|
2021-04-08 09:34:03 -04:00
|
|
|
}
|
|
|
|
|
2021-06-16 13:11:00 -04:00
|
|
|
void ClassicTimeline::updateVisibleSprites(const microsec& music_offset)
|
|
|
|
{
|
|
|
|
if (nothingToDraw())
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::for_each(_first_visible_note, _last_visible_note,
|
|
|
|
[&music_offset](const auto& note)
|
|
|
|
{
|
|
|
|
note->update(music_offset);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-06-08 14:32:36 -04:00
|
|
|
ClassicTimeline::Iterator ClassicTimeline::getActiveNote() noexcept
|
2021-04-08 09:34:03 -04:00
|
|
|
{
|
|
|
|
return _active_note;
|
|
|
|
}
|
2021-06-08 14:32:36 -04:00
|
|
|
|
2021-06-16 13:11:00 -04:00
|
|
|
bool ClassicTimeline::isExpired(const Iterator& iterator) const
|
2021-06-08 14:32:36 -04:00
|
|
|
{
|
|
|
|
return iterator == _timeline.end();
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:11:00 -04:00
|
|
|
void ClassicTimeline::expire(Iterator& iterator)
|
2021-06-08 14:32:36 -04:00
|
|
|
{
|
|
|
|
iterator = _timeline.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
microsec ClassicTimeline::currentMusicOffset() const
|
|
|
|
{
|
|
|
|
return _music.getPlayingOffset().asMicroseconds();
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:11:00 -04:00
|
|
|
bool ClassicTimeline::isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const
|
2021-06-09 18:47:18 -04:00
|
|
|
{
|
|
|
|
return ((*iterator)->offset() - _visibility_offset) <= music_offset;
|
|
|
|
}
|
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
void ClassicTimeline::fetchVisibleNotes()
|
2021-06-08 14:32:36 -04:00
|
|
|
{
|
2021-06-11 12:58:44 -04:00
|
|
|
const microsec music_offset = currentMusicOffset();
|
2021-06-23 15:18:33 -04:00
|
|
|
findLastVisibleNote(music_offset);
|
|
|
|
findFirstVisibleNote();
|
2021-06-16 11:16:18 -04:00
|
|
|
}
|
2021-06-08 14:32:36 -04:00
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
void ClassicTimeline::findLastVisibleNote(const microsec &music_offset)
|
2021-06-16 11:16:18 -04:00
|
|
|
{
|
2021-06-09 18:47:18 -04:00
|
|
|
Iterator note_iterator = _top_note;
|
|
|
|
while (isVisiblyClose(note_iterator, music_offset))
|
2021-06-08 14:32:36 -04:00
|
|
|
{
|
2021-06-16 11:16:18 -04:00
|
|
|
if (nothingToDraw())
|
|
|
|
_first_visible_note = note_iterator;
|
2021-06-11 12:58:44 -04:00
|
|
|
|
2021-06-16 11:16:18 -04:00
|
|
|
auto note = *note_iterator;
|
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
if (note->isExpired())
|
2021-06-21 15:10:50 -04:00
|
|
|
note->putToGame(music_offset);
|
2021-06-09 18:47:18 -04:00
|
|
|
|
2021-06-16 13:11:00 -04:00
|
|
|
++note_iterator;
|
2021-06-08 14:32:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
_last_visible_note = note_iterator;
|
|
|
|
}
|
2021-06-09 14:08:58 -04:00
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
void ClassicTimeline::findFirstVisibleNote()
|
2021-06-09 14:08:58 -04:00
|
|
|
{
|
2021-06-16 11:16:18 -04:00
|
|
|
if (nothingToDraw())
|
2021-06-09 14:08:58 -04:00
|
|
|
return;
|
|
|
|
|
2021-06-16 11:16:18 -04:00
|
|
|
auto note_iterator = _first_visible_note;
|
|
|
|
while (note_iterator != _last_visible_note)
|
2021-06-09 14:08:58 -04:00
|
|
|
{
|
2021-06-16 11:16:18 -04:00
|
|
|
auto note = *note_iterator;
|
2021-06-21 15:10:50 -04:00
|
|
|
if (note->isExpired())
|
2021-06-16 11:16:18 -04:00
|
|
|
++_first_visible_note;
|
2021-06-16 13:11:00 -04:00
|
|
|
|
|
|
|
++note_iterator;
|
2021-06-09 14:08:58 -04:00
|
|
|
}
|
|
|
|
}
|
2021-06-16 11:16:18 -04:00
|
|
|
|
|
|
|
bool ClassicTimeline::nothingToDraw() const noexcept
|
|
|
|
{
|
|
|
|
return isExpired(_first_visible_note);
|
|
|
|
}
|
|
|
|
|
2021-06-23 15:18:33 -04:00
|
|
|
void ClassicTimeline::drawVisibleNotes() const
|
2021-06-16 11:16:18 -04:00
|
|
|
{
|
|
|
|
if (nothingToDraw())
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::for_each(_first_visible_note, _last_visible_note,
|
2021-06-23 15:18:33 -04:00
|
|
|
[](const auto& note)
|
2021-06-16 11:16:18 -04:00
|
|
|
{
|
2021-06-23 15:18:33 -04:00
|
|
|
note->draw();
|
2021-06-16 11:16:18 -04:00
|
|
|
});
|
|
|
|
}
|
2021-06-16 13:11:00 -04:00
|
|
|
|