forked from NaiJi/project-kyoku
Test implementation of drawing timeline
This commit is contained in:
parent
e8d1724b45
commit
dd3a175b55
|
@ -147,8 +147,6 @@ void Application::onTap(const Note::Arrow &arrow)
|
||||||
if (arrow == Note::Arrow::NONE)
|
if (arrow == Note::Arrow::NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_debug.spawnGreenPulse();
|
|
||||||
|
|
||||||
const auto music_offset = _music.getPlayingOffset().asMicroseconds();
|
const auto music_offset = _music.getPlayingOffset().asMicroseconds();
|
||||||
const auto note = _timeline.fetchActiveNote(music_offset);
|
const auto note = _timeline.fetchActiveNote(music_offset);
|
||||||
|
|
||||||
|
@ -178,6 +176,7 @@ void Application::update()
|
||||||
void Application::draw()
|
void Application::draw()
|
||||||
{
|
{
|
||||||
_game_window.clear();
|
_game_window.clear();
|
||||||
|
_game_window.draw(_timeline);
|
||||||
_game_window.draw(_debug);
|
_game_window.draw(_debug);
|
||||||
_game_window.draw(_grade);
|
_game_window.draw(_grade);
|
||||||
_game_window.display();
|
_game_window.display();
|
||||||
|
|
96
timeline.cpp
96
timeline.cpp
|
@ -1,6 +1,7 @@
|
||||||
#include "timeline.h"
|
#include "timeline.h"
|
||||||
#include "note.h"
|
#include "note.h"
|
||||||
|
|
||||||
|
#include <SFML/Graphics/RenderTarget.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
Timeline::Timeline()
|
Timeline::Timeline()
|
||||||
|
@ -9,64 +10,123 @@ Timeline::Timeline()
|
||||||
// Length is 1:14
|
// Length is 1:14
|
||||||
// I calculated that the time between beats is about 1412162 microseconds
|
// I calculated that the time between beats is about 1412162 microseconds
|
||||||
|
|
||||||
|
_timeline.reserve(1000);
|
||||||
|
|
||||||
microsec starting_beat_offset = 372162;
|
microsec starting_beat_offset = 372162;
|
||||||
int amount_of_beats = 209;
|
int amount_of_beats = 209;
|
||||||
microsec time_between_beats = 1412162;
|
microsec interval = 1412162;
|
||||||
microsec note_input_offset = 412162;
|
microsec note_input_offset = 412162;
|
||||||
microsec interval = starting_beat_offset;
|
microsec bpm_iterator = starting_beat_offset;
|
||||||
microsec AAAAAAAAENDBLYAT = starting_beat_offset + (time_between_beats * amount_of_beats);
|
microsec bpm_end = starting_beat_offset + (interval * amount_of_beats);
|
||||||
|
_visibility_offset = note_input_offset * 3;
|
||||||
|
|
||||||
Note::resetPrecisionQualifier(note_input_offset / 3);
|
Note::resetPrecisionQualifier(note_input_offset / 3);
|
||||||
|
|
||||||
while (interval < AAAAAAAAENDBLYAT)
|
while (bpm_iterator < bpm_end)
|
||||||
{
|
{
|
||||||
_timeline.emplace_back(new Note(interval, note_input_offset));
|
_timeline.emplace_back(new Note(bpm_iterator, note_input_offset));
|
||||||
interval += time_between_beats;
|
bpm_iterator += interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_timeline[0]->setPosition({200, 200});
|
||||||
|
_timeline[1]->setPosition({250, 200});
|
||||||
|
_timeline[2]->setPosition({300, 200});
|
||||||
|
_timeline[3]->setPosition({350, 200});
|
||||||
|
_timeline[4]->setPosition({400, 200});
|
||||||
|
_timeline[5]->setPosition({450, 200});
|
||||||
|
_timeline[6]->setPosition({200, 300});
|
||||||
|
_timeline[7]->setPosition({250, 300});
|
||||||
|
_timeline[8]->setPosition({300, 300});
|
||||||
|
_timeline[9]->setPosition({350, 300});
|
||||||
|
_timeline[10]->setPosition({400, 300});
|
||||||
|
_timeline[11]->setPosition({450, 300});
|
||||||
|
|
||||||
_active_note = nullptr;
|
_active_note = nullptr;
|
||||||
|
_last_visible_note = _timeline.end();
|
||||||
_top_note = _timeline.begin();
|
_top_note = _timeline.begin();
|
||||||
|
|
||||||
|
prepareNotesToDraw(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timeline::prepareNotesToDraw(const microsec &music_offset)
|
||||||
|
{
|
||||||
|
auto note_iterator = _top_note;
|
||||||
|
|
||||||
|
while (((*note_iterator)->offset() - _visibility_offset) >= music_offset)
|
||||||
|
++note_iterator;
|
||||||
|
|
||||||
|
_last_visible_note = note_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timeline::~Timeline()
|
Timeline::~Timeline()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timeline::clear()
|
||||||
{
|
{
|
||||||
for (auto note : _timeline)
|
for (auto note : _timeline)
|
||||||
delete note;
|
delete note;
|
||||||
|
|
||||||
_timeline.clear();
|
_timeline.clear();
|
||||||
_top_note = _timeline.end();
|
_top_note = _timeline.end();
|
||||||
|
_last_visible_note = _timeline.end();
|
||||||
_active_note = nullptr;
|
_active_note = nullptr;
|
||||||
|
|
||||||
Note::resetPrecisionQualifier();
|
Note::resetPrecisionQualifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::update(const microsec µseconds)
|
static sf::RectangleShape createNoteGlyph(const std::vector<Note*>::const_iterator& note_to_draw)
|
||||||
{
|
{ // Temporary solution
|
||||||
checkCurrentActiveNote(microseconds);
|
sf::RectangleShape ret;
|
||||||
checkForNextActiveNote(microseconds);
|
const auto position = (*note_to_draw)->position();
|
||||||
|
ret.setPosition(position.x, position.y);
|
||||||
|
ret.setFillColor(sf::Color(255, 100, 0));
|
||||||
|
ret.setSize({10.f, 10.f});
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::checkCurrentActiveNote(const microsec µseconds)
|
void Timeline::draw(sf::RenderTarget& target, sf::RenderStates states) const // Temporary solution
|
||||||
{
|
{
|
||||||
if (_active_note && !_active_note->isActive(microseconds))
|
if (_last_visible_note == _timeline.end() || _top_note > _last_visible_note)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto note_to_draw = _top_note;
|
||||||
|
while (note_to_draw != (_last_visible_note + 1))
|
||||||
|
{
|
||||||
|
target.draw(createNoteGlyph(note_to_draw), states);
|
||||||
|
++note_to_draw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timeline::update(const microsec &music_offset)
|
||||||
|
{
|
||||||
|
checkCurrentActiveNote(music_offset);
|
||||||
|
checkForNextActiveNote(music_offset);
|
||||||
|
prepareNotesToDraw(music_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timeline::checkCurrentActiveNote(const microsec &music_offset)
|
||||||
|
{
|
||||||
|
if (_active_note && !_active_note->isActive(music_offset))
|
||||||
{
|
{
|
||||||
_active_note = nullptr;
|
_active_note = nullptr;
|
||||||
++_top_note;
|
++_top_note;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timeline::checkForNextActiveNote(const microsec µseconds)
|
void Timeline::checkForNextActiveNote(const microsec &music_offset)
|
||||||
{
|
{
|
||||||
if (!_active_note && (*_top_note)->isActive(microseconds))
|
if (!_active_note && (*_top_note)->isActive(music_offset))
|
||||||
{
|
{
|
||||||
std::cout << "New active note: " << microseconds << '\n';
|
std::cout << "New active note: " << music_offset << '\n';
|
||||||
_active_note = *_top_note;
|
_active_note = *_top_note;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Note* Timeline::fetchActiveNote(const microsec µseconds) noexcept
|
const Note* Timeline::fetchActiveNote(const microsec &music_offset) noexcept
|
||||||
{
|
{
|
||||||
std::cout << "Clicked at: " << microseconds << '\n';
|
std::cout << "Clicked at: " << music_offset << '\n';
|
||||||
update(microseconds);
|
update(music_offset);
|
||||||
return _active_note;
|
return _active_note;
|
||||||
}
|
}
|
||||||
|
|
24
timeline.h
24
timeline.h
|
@ -2,6 +2,7 @@
|
||||||
#define TIMELINE_H
|
#define TIMELINE_H
|
||||||
|
|
||||||
#include <SFML/Config.hpp>
|
#include <SFML/Config.hpp>
|
||||||
|
#include <SFML/Graphics/RectangleShape.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -9,22 +10,31 @@
|
||||||
using microsec = sf::Int64;
|
using microsec = sf::Int64;
|
||||||
class Note;
|
class Note;
|
||||||
|
|
||||||
class Timeline
|
class Timeline : public sf::Drawable // Probably it's bad
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Timeline();
|
explicit Timeline();
|
||||||
~Timeline();
|
virtual ~Timeline();
|
||||||
|
|
||||||
void update(const microsec& microseconds);
|
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
const Note* fetchActiveNote(const microsec µseconds) noexcept;
|
|
||||||
|
void update(const microsec& music_offset);
|
||||||
|
const Note* fetchActiveNote(const microsec &music_offset) noexcept;
|
||||||
|
|
||||||
|
/* void init(); */
|
||||||
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Note*> _timeline;
|
std::vector<Note*> _timeline;
|
||||||
std::vector<Note*>::iterator _top_note;
|
std::vector<Note*>::const_iterator _top_note;
|
||||||
Note* _active_note;
|
Note* _active_note;
|
||||||
|
|
||||||
void checkCurrentActiveNote(const microsec µseconds);
|
std::vector<Note*>::const_iterator _last_visible_note;
|
||||||
void checkForNextActiveNote(const microsec µseconds);
|
microsec _visibility_offset;
|
||||||
|
|
||||||
|
void checkCurrentActiveNote(const microsec &music_offset);
|
||||||
|
void checkForNextActiveNote(const microsec &music_offset);
|
||||||
|
void prepareNotesToDraw(const microsec &music_offset);
|
||||||
|
|
||||||
/* Difference between top and active note is that
|
/* Difference between top and active note is that
|
||||||
* top note is the note handling input right now
|
* top note is the note handling input right now
|
||||||
|
|
Loading…
Reference in New Issue