Run classic timelineviewmanager

This commit is contained in:
NaiJi ✨ 2021-04-17 19:14:36 +03:00
parent ecd0e67ed1
commit 8a7602af78
11 changed files with 105 additions and 52 deletions

View File

@ -2,6 +2,7 @@
#include <SFML/Graphics/Color.hpp> #include <SFML/Graphics/Color.hpp>
#include <SFML/Window/Event.hpp> #include <SFML/Window/Event.hpp>
#include "timelineviews/classicviewmanager.h"
const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 60.f); const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 60.f);
@ -9,6 +10,7 @@ Application::Application() :
_game_window({1280, 720}, "Test"), _game_window({1280, 720}, "Test"),
_debug(true) _debug(true)
{ {
_timeline = std::make_unique<Timeline>(std::make_unique<ClassicViewManager>());
_font.loadFromFile("/usr/share/qtcreator/fonts/SourceCodePro-Regular.ttf"); _font.loadFromFile("/usr/share/qtcreator/fonts/SourceCodePro-Regular.ttf");
_grade.setFont(_font); _grade.setFont(_font);
_grade.setPosition(160, 160); _grade.setPosition(160, 160);
@ -144,7 +146,7 @@ void Application::onTap(const Note::Arrow &arrow)
return; return;
const auto music_offset = _music.getPlayingOffset().asMicroseconds(); const auto music_offset = _music.getPlayingOffset().asMicroseconds();
auto note = _timeline.fetchActiveNote(music_offset); auto note = _timeline->fetchActiveNote(music_offset);
if (note) if (note)
{ {
@ -158,7 +160,7 @@ void Application::update()
{ {
const auto music_offset = _music.getPlayingOffset().asMicroseconds(); const auto music_offset = _music.getPlayingOffset().asMicroseconds();
_timeline.update(music_offset); _timeline->update(music_offset);
_debug.update(music_offset); _debug.update(music_offset);
if (_grade.getFillColor().a > 0) // TODO: Encapsulate if (_grade.getFillColor().a > 0) // TODO: Encapsulate
@ -172,7 +174,7 @@ void Application::update()
void Application::draw() void Application::draw()
{ {
_game_window.clear(); _game_window.clear();
_game_window.draw(_timeline); _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();

View File

@ -25,7 +25,7 @@ private:
sf::Font _font; sf::Font _font;
sf::Text _grade; sf::Text _grade;
Timeline _timeline; std::unique_ptr<Timeline> _timeline;
DebugHelper _debug; DebugHelper _debug;
void startGameLoop(); void startGameLoop();

View File

@ -26,9 +26,6 @@ microsec Note::offset() const noexcept
NoteGrade Note::onTap(Arrow arrow_type, microsec tap_time_stamp) NoteGrade Note::onTap(Arrow arrow_type, microsec tap_time_stamp)
{ {
_sprite->setAttachment(false);
_sprite = nullptr;
if (arrow_type != _type) if (arrow_type != _type)
return {0, NoteGrade::Rating::WRONG}; return {0, NoteGrade::Rating::WRONG};
@ -61,7 +58,23 @@ void Note::resetPrecisionQualifier(microsec qualifier)
void Note::resetSprite(const std::shared_ptr<Sprite> &sprite) noexcept void Note::resetSprite(const std::shared_ptr<Sprite> &sprite) noexcept
{ {
if (_sprite)
_sprite->setAttachment(false);
_sprite = sprite; _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. microsec Note::_precision_qualifier = 500000; // Default initialization as 0.5 second.

18
note.h
View File

@ -4,6 +4,7 @@
#include <SFML/System/Clock.hpp> #include <SFML/System/Clock.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/RectangleShape.hpp> // TEMP MOCK #include <SFML/Graphics/RectangleShape.hpp> // TEMP MOCK
#include <SFML/Graphics/RenderTarget.hpp>
#include <memory> #include <memory>
@ -12,13 +13,21 @@
using microsec = sf::Int64; using microsec = sf::Int64;
using coordinates = sf::Vector2i; using coordinates = sf::Vector2i;
class Sprite // MOCK class Sprite : public sf::Drawable // MOCK
{ {
public: public:
Sprite(sf::RectangleShape shape) : _shape(shape), _attached(false) {}; Sprite(sf::RectangleShape shape) : _shape(shape), _attached(false) {};
bool isAttached() const noexcept bool isAttached() const noexcept
{ return _attached; } { return _attached; }
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override
{
target.draw(_shape, states);
}
void setCoordinates(coordinates cords) noexcept
{ _shape.setPosition(cords.x, cords.y); }
void setAttachment(bool attached) noexcept void setAttachment(bool attached) noexcept
{ _attached = attached; } { _attached = attached; }
@ -43,7 +52,7 @@ struct NoteGrade
//////////////////////////////// ////////////////////////////////
class Note class Note : public sf::Drawable
{ {
public: public:
enum class Arrow enum class Arrow
@ -61,11 +70,14 @@ public:
void setPosition(coordinates position); void setPosition(coordinates position);
coordinates position() const noexcept; coordinates position() const noexcept;
microsec offset() const noexcept; microsec offset() const noexcept;
Note::Arrow type() const noexcept;
NoteGrade onTap(Arrow arrow_type, microsec tap_time_stamp); NoteGrade onTap(Arrow arrow_type, microsec tap_time_stamp);
bool isActive(microsec music_play_offset) const noexcept; bool isActive(microsec music_play_offset) const noexcept;
void resetSprite(const std::shared_ptr<Sprite>& sprite) noexcept; void resetSprite(const std::shared_ptr<Sprite>& sprite = nullptr) noexcept;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
static void resetPrecisionQualifier(microsec qualifier = 500000); static void resetPrecisionQualifier(microsec qualifier = 500000);

View File

@ -1,10 +1,12 @@
#include "timeline.h" #include "timeline.h"
#include "note.h" #include "note.h"
#include "timelineviews/timelineviewmanager.h"
#include <SFML/Graphics/RenderTarget.hpp> #include <SFML/Graphics/RenderTarget.hpp>
#include <iostream> #include <iostream>
Timeline::Timeline() Timeline::Timeline(std::unique_ptr<TimelineViewManager> view_manager) :
_view_manager(std::move(view_manager))
{ {
// BPM of METEOR is 170. // BPM of METEOR is 170.
// Length is 1:14 // Length is 1:14
@ -18,10 +20,19 @@ Timeline::Timeline()
microsec note_input_offset = 412162; microsec note_input_offset = 412162;
microsec bpm_iterator = starting_beat_offset; microsec bpm_iterator = starting_beat_offset;
microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); microsec bpm_end = starting_beat_offset + (interval * amount_of_beats);
_visibility_offset = note_input_offset * 3; _visibility_offset = note_input_offset * 12;
Note::resetPrecisionQualifier(note_input_offset / 3); Note::resetPrecisionQualifier(note_input_offset / 3);
_timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Note::Arrow::DOWN));
bpm_iterator += interval;
_timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Note::Arrow::LEFT));
bpm_iterator += interval;
_timeline.emplace_back(new Note(bpm_iterator, note_input_offset, Note::Arrow::LEFT));
bpm_iterator += interval;
while (bpm_iterator < bpm_end) while (bpm_iterator < bpm_end)
{ {
_timeline.emplace_back(new Note(bpm_iterator, note_input_offset)); _timeline.emplace_back(new Note(bpm_iterator, note_input_offset));
@ -45,6 +56,8 @@ Timeline::Timeline()
_last_visible_note = _timeline.end(); _last_visible_note = _timeline.end();
_top_note = _timeline.begin(); _top_note = _timeline.begin();
_last_visible_note = _top_note;
_view_manager->initNoteGraphics(*_top_note);
prepareNotesToDraw(0); prepareNotesToDraw(0);
} }
@ -52,8 +65,12 @@ void Timeline::prepareNotesToDraw(const microsec &music_offset)
{ {
auto note_iterator = _top_note; auto note_iterator = _top_note;
while (((*note_iterator)->offset() - _visibility_offset) >= music_offset) while (((*note_iterator)->offset() - _visibility_offset) <= music_offset)
{
++note_iterator; ++note_iterator;
if (note_iterator > _last_visible_note)
_view_manager->initNoteGraphics((*note_iterator));
}
_last_visible_note = note_iterator; _last_visible_note = note_iterator;
} }
@ -76,16 +93,6 @@ void Timeline::clear()
Note::resetPrecisionQualifier(); Note::resetPrecisionQualifier();
} }
static sf::RectangleShape createNoteGlyph(const std::vector<Note*>::const_iterator& note_to_draw)
{ // Temporary solution
sf::RectangleShape ret;
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::draw(sf::RenderTarget& target, sf::RenderStates states) const // Temporary solution void Timeline::draw(sf::RenderTarget& target, sf::RenderStates states) const // Temporary solution
{ {
if (_last_visible_note == _timeline.end() || _top_note > _last_visible_note) if (_last_visible_note == _timeline.end() || _top_note > _last_visible_note)
@ -94,7 +101,7 @@ void Timeline::draw(sf::RenderTarget& target, sf::RenderStates states) const //
auto note_to_draw = _top_note; auto note_to_draw = _top_note;
while (note_to_draw != (_last_visible_note + 1)) while (note_to_draw != (_last_visible_note + 1))
{ {
target.draw(createNoteGlyph(note_to_draw), states); target.draw(*(*note_to_draw), states);
++note_to_draw; ++note_to_draw;
} }
} }
@ -111,6 +118,7 @@ void Timeline::checkCurrentActiveNote(const microsec &music_offset)
if (_active_note && !_active_note->isActive(music_offset)) if (_active_note && !_active_note->isActive(music_offset))
{ {
_active_note = nullptr; _active_note = nullptr;
(*_top_note)->resetSprite();
++_top_note; ++_top_note;
} }
} }

View File

@ -9,11 +9,12 @@
using microsec = sf::Int64; using microsec = sf::Int64;
class Note; class Note;
class TimelineViewManager;
class Timeline : public sf::Drawable // Probably it's bad class Timeline : public sf::Drawable // Probably it's bad
{ {
public: public:
explicit Timeline(); explicit Timeline(std::unique_ptr<TimelineViewManager> view_manager);
virtual ~Timeline(); virtual ~Timeline();
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
@ -32,6 +33,8 @@ private:
std::vector<Note*>::const_iterator _last_visible_note; std::vector<Note*>::const_iterator _last_visible_note;
microsec _visibility_offset; microsec _visibility_offset;
std::unique_ptr<TimelineViewManager> _view_manager;
void checkCurrentActiveNote(const microsec &music_offset); void checkCurrentActiveNote(const microsec &music_offset);
void checkForNextActiveNote(const microsec &music_offset); void checkForNextActiveNote(const microsec &music_offset);
void prepareNotesToDraw(const microsec &music_offset); void prepareNotesToDraw(const microsec &music_offset);

View File

@ -1,6 +0,0 @@
#include "timelineviewmanager.h"
TimelineViewManager::TimelineViewManager()
{
}

View File

@ -1,11 +0,0 @@
#ifndef TIMELINEVIEWMANAGER_H
#define TIMELINEVIEWMANAGER_H
class TimelineViewManager
{
public:
TimelineViewManager();
};
#endif // TIMELINEVIEWMANAGER_H

View File

@ -9,20 +9,56 @@ ClassicViewManager::ClassicViewManager()
for (std::size_t i = ARROW_UP; i < AMOUNT_OF_KINDS; ++i) for (std::size_t i = ARROW_UP; i < AMOUNT_OF_KINDS; ++i)
{ {
SpritePoll &poll = _sprite_dispatcher.at(i); SpritePoll &poll = _sprite_dispatcher.at(i);
poll.reserve(RESERVED_SIZE); poll.resize(RESERVED_SIZE);
for (auto &sprite : poll) for (auto &sprite : poll)
{ {
sprite = createSprite(static_cast<Button>(i));
} }
} }
} }
ClassicViewManager::~ClassicViewManager()
{}
std::shared_ptr<Sprite> ClassicViewManager::createSprite(Button kind_of_button) const std::shared_ptr<Sprite> ClassicViewManager::createSprite(Button kind_of_button) const
{ {
auto sprite = std::make_shared<sf::RectangleShape>(); sf::RectangleShape sprite;
sprite->setSize({20.f, 20.f}); sprite.setSize({20.f, 20.f});
switch (kind_of_button) switch (kind_of_button)
{ {
return case ARROW_UP:
sprite.setFillColor(sf::Color(255, 0, 0));
break;
case ARROW_DOWN:
sprite.setFillColor(sf::Color(0, 255, 0));
break;
case ARROW_LEFT:
sprite.setFillColor(sf::Color(0, 0, 255));
break;
case ARROW_RIGHT:
sprite.setFillColor(sf::Color(255, 0, 255));
break;
default: // yellow
sprite.setFillColor(sf::Color(255, 239, 0));
}
return std::make_shared<Sprite>(sprite);
}
void ClassicViewManager::initNoteGraphics(Note *note)
{
const auto type = note->type();
for (const auto sprite : _sprite_dispatcher.at(static_cast<int>(type)))
{
if (!sprite->isAttached())
{
sprite->setCoordinates(note->position());
note->resetSprite(sprite);
return;
}
} }
} }

View File

@ -14,8 +14,6 @@ public:
explicit ClassicViewManager(); explicit ClassicViewManager();
virtual ~ClassicViewManager() override; virtual ~ClassicViewManager() override;
virtual void update() override;
virtual void draw() override;
virtual void initNoteGraphics(Note *note) override; virtual void initNoteGraphics(Note *note) override;
private: private:
@ -23,9 +21,9 @@ private:
enum Button enum Button
{ {
ARROW_UP, ARROW_UP,
ARROW_RIGHT,
ARROW_DOWN, ARROW_DOWN,
ARROW_LEFT, ARROW_LEFT,
ARROW_RIGHT,
SHOULDER_RIGHT, SHOULDER_RIGHT,
SHOULDER_LEFT, SHOULDER_LEFT,

View File

@ -9,8 +9,6 @@ public:
explicit TimelineViewManager(); explicit TimelineViewManager();
virtual ~TimelineViewManager(); virtual ~TimelineViewManager();
virtual void update() = 0;
virtual void draw() = 0;
virtual void initNoteGraphics(Note *note) = 0; virtual void initNoteGraphics(Note *note) = 0;
}; };