Implement hold for notes

This commit is contained in:
NaiJi ✨ 2021-07-21 21:15:56 +03:00
parent 80d2c97766
commit 00360f6c8d
9 changed files with 89 additions and 43 deletions

View File

@ -10,13 +10,9 @@ class Note;
class Timeline class Timeline
{ {
public: public:
using Iterator = std::vector<Note*>::const_iterator;
virtual ~Timeline() = default; virtual ~Timeline() = default;
virtual void update() = 0; virtual void update() = 0;
virtual void run(std::vector<Note*>&& notes, const microsec& visibility) = 0;
virtual void clear() = 0; virtual void clear() = 0;
virtual microsec currentMusicOffset() const = 0; virtual microsec currentMusicOffset() const = 0;

View File

@ -1,6 +1,8 @@
#include "classicgame.h" #include "classicgame.h"
#include "classictimeline.h" #include "classictimeline.h"
#include "classicnote.h"
#include "classicmapcreator.h" #include "classicmapcreator.h"
#include <iostream>
ClassicGame::ClassicGame(std::unique_ptr<ClassicGraphicsManager>&& manager) : ClassicGame::ClassicGame(std::unique_ptr<ClassicGraphicsManager>&& manager) :
_timeline(std::make_unique<ClassicTimeline>()), _timeline(std::make_unique<ClassicTimeline>()),
@ -67,19 +69,43 @@ void ClassicGame::input(PlayerInput&& inputdata)
{ {
default: default:
return; return;
break; break;
case sf::Event::KeyPressed:
case sf::Event::KeyReleased:
{
auto note = _timeline->getActiveNote();
if (!_timeline->isExpired(note)) case sf::Event::KeyPressed:
{
auto note_it = _timeline->getActiveNote();
if (!_timeline->isExpired(note_it))
{
auto note = (*note_it);
note->input(std::move(inputdata));
_slap.play();
if (note->isHold() && note->allElementsPressed()) // also check for Type
{ {
(*note)->input(std::move(inputdata)); _notes_on_hold.emplace_back(note);
_slap.play(); std::cout << "HOLD initited by " << inputdata.event.key.code << '\n';
} }
} }
break; }
break;
case sf::Event::KeyReleased:
{
bool key_match = std::any_of(_notes_on_hold.begin(), _notes_on_hold.end(),
[key=inputdata.event.key.code](const auto& note)
{
return note->isPressedAs(key);
});
if (key_match)
{
_notes_on_hold.clear();
std::cout << "HOLD released by " << inputdata.event.key.code << '\n';
}
}
break;
} }
} }

View File

@ -7,6 +7,7 @@
#include <SFML/Audio/SoundBuffer.hpp> #include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/Sound.hpp> #include <SFML/Audio/Sound.hpp>
class ClassicNote;
class ClassicTimeline; class ClassicTimeline;
class ClassicGraphicsManager; class ClassicGraphicsManager;
@ -27,6 +28,8 @@ private:
std::map<Type, Action> _buttons_to_pressed_actions; std::map<Type, Action> _buttons_to_pressed_actions;
std::map<Type, Action> _buttons_to_released_actions; std::map<Type, Action> _buttons_to_released_actions;
std::vector<ClassicNote*> _notes_on_hold;
std::unique_ptr<ClassicTimeline> _timeline; std::unique_ptr<ClassicTimeline> _timeline;
std::unique_ptr<ClassicGraphicsManager> _graphics_manager; std::unique_ptr<ClassicGraphicsManager> _graphics_manager;
sf::SoundBuffer _slap_buffer; sf::SoundBuffer _slap_buffer;

View File

@ -14,12 +14,12 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const
microsec interval = 1412162; microsec interval = 1412162;
microsec tempo_interval = interval / 2; microsec tempo_interval = interval / 2;
microsec note_input_offset = 412162 / 2; microsec note_input_offset = 412162 / 2;
microsec note_input_offset_fast = 412162 / 6; //microsec note_input_offset_fast = 412162 / 6;
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);
std::vector<microsec> input_intervals = {note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset}; std::vector<microsec> input_intervals = {note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset};
std::vector<Note*> notes; std::vector<ClassicNote*> notes;
input_intervals.shrink_to_fit(); input_intervals.shrink_to_fit();
bpm_iterator += tempo_interval; bpm_iterator += tempo_interval;
@ -34,35 +34,26 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const
ClassicNote::ClassicNoteInitializer::Element element; ClassicNote::ClassicNoteInitializer::Element element;
init.intervals = input_intervals; init.intervals = input_intervals;
init.perfect_offset = bpm_iterator; init.perfect_offset = bpm_iterator;
init.hold = false;
element.coordinates = {x, 390.}; element.coordinates = {x, 390.};
element.falling_curve_interpolation = {}; element.falling_curve_interpolation = {};
element.keys = {sf::Keyboard::W, sf::Keyboard::Up}; element.keys = {sf::Keyboard::W, sf::Keyboard::Up};
element.type = Type::UP; element.type = Type::UP;
init.elements = {element};
notes.emplace_back(new ClassicNote(std::move(init), _graphics_manager));
if (counter == 0) if (counter == 0)
{ {
ClassicNote::ClassicNoteInitializer init2; init.hold = true;
ClassicNote::ClassicNoteInitializer::Element element2; element.keys = {sf::Keyboard::D, sf::Keyboard::Right};
init2.intervals = input_intervals; element.type = Type::RIGHT;
init2.perfect_offset = bpm_iterator + note_input_offset_fast;
element2.coordinates = {x + 35, 390. + 50.};
element2.falling_curve_interpolation = {};
element2.keys = {sf::Keyboard::D, sf::Keyboard::Right};
element2.type = Type::RIGHT;
init2.elements = {element2};
notes.emplace_back(new ClassicNote(std::move(init2), _graphics_manager));
counter = 3;
} }
--counter; --counter;
init.elements = {element};
notes.emplace_back(new ClassicNote(std::move(init), _graphics_manager));
bpm_iterator += tempo_interval; bpm_iterator += tempo_interval;
x += 70; x += 70;

View File

@ -8,7 +8,7 @@
struct Beatmap struct Beatmap
{ {
std::vector<Note*> notes; std::vector<ClassicNote*> notes;
microsec visibility_offset; microsec visibility_offset;
}; };

View File

@ -14,6 +14,8 @@ ClassicNote::ClassicNote(ClassicNoteInitializer &&init, const std::unique_ptr<Cl
_state(State::NONE) _state(State::NONE)
{ {
_elements.resize(init.elements.size()); _elements.resize(init.elements.size());
_isHold = init.hold;
for (std::size_t i = 0; i < _elements.size(); ++i) for (std::size_t i = 0; i < _elements.size(); ++i)
{ {
_elements[i].keys = init.elements[i].keys; _elements[i].keys = init.elements[i].keys;
@ -111,11 +113,7 @@ void ClassicNote::input(PlayerInput&& inputdata)
return found_key; return found_key;
}); });
bool all_pressed = std::all_of(_elements.begin(), _elements.end(), bool all_pressed = allElementsPressed();
[](const auto& element)
{
return element.pressed;
});
if (all_pressed) if (all_pressed)
grade = _evaluator.calculatePrecision(inputdata.timestamp); grade = _evaluator.calculatePrecision(inputdata.timestamp);
@ -139,3 +137,26 @@ void ClassicNote::draw() const
_graphics_manager->draw(_elements[i].sprite); _graphics_manager->draw(_elements[i].sprite);
} }
} }
bool ClassicNote::isHold() const
{
return _isHold;
}
bool ClassicNote::allElementsPressed() const
{
return std::all_of(_elements.begin(), _elements.end(),
[](const auto& element)
{
return element.pressed;
});
}
bool ClassicNote::isPressedAs(sf::Keyboard::Key key) const
{
return std::any_of(_elements.begin(), _elements.end(),
[key=key](const auto& element)
{
return key == element.pressed_as;
});
}

View File

@ -36,6 +36,7 @@ public:
{ {
std::vector<microsec> intervals; std::vector<microsec> intervals;
microsec perfect_offset; microsec perfect_offset;
bool hold;
struct Element struct Element
{ {
@ -59,6 +60,10 @@ public:
virtual bool shouldRemove() const override; virtual bool shouldRemove() const override;
virtual void draw() const override; virtual void draw() const override;
bool isHold() const;
bool allElementsPressed() const;
bool isPressedAs(sf::Keyboard::Key key) const;
private: private:
struct NoteElement struct NoteElement
@ -80,4 +85,5 @@ private:
const std::unique_ptr<ClassicGraphicsManager>& _graphics_manager; const std::unique_ptr<ClassicGraphicsManager>& _graphics_manager;
State _state; State _state;
bool _isHold;
}; };

View File

@ -1,4 +1,4 @@
#include "note.h" #include "classicnote.h"
#include "classictimeline.h" #include "classictimeline.h"
#include <iostream> #include <iostream>
@ -17,7 +17,7 @@ ClassicTimeline::ClassicTimeline() :
_music.setVolume(10); _music.setVolume(10);
} }
void ClassicTimeline::run(std::vector<Note*>&& notes, const microsec& visibility) void ClassicTimeline::run(std::vector<ClassicNote*>&& notes, const microsec& visibility)
{ {
_visibility_offset = visibility; _visibility_offset = visibility;
_timeline = std::move(notes); _timeline = std::move(notes);

View File

@ -7,7 +7,7 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
class Note; class ClassicNote;
class ClassicTimeline : public Timeline class ClassicTimeline : public Timeline
{ {
@ -15,16 +15,19 @@ public:
explicit ClassicTimeline(); explicit ClassicTimeline();
virtual ~ClassicTimeline(); virtual ~ClassicTimeline();
virtual void update() override; virtual void update() override;
virtual void run(std::vector<Note*>&& notes, const microsec& visibility) override;
virtual void clear() override; virtual void clear() override;
virtual microsec currentMusicOffset() const override; virtual microsec currentMusicOffset() const override;
virtual void drawVisibleNotes() const override; virtual void drawVisibleNotes() const override;
void run(std::vector<ClassicNote*>&& notes, const microsec& visibility);
void fetchVisibleNotes(); void fetchVisibleNotes();
void findLastVisibleNote(const microsec& music_offset); void findLastVisibleNote(const microsec& music_offset);
void findFirstVisibleNote(); void findFirstVisibleNote();
using Iterator = std::vector<ClassicNote*>::const_iterator;
Iterator getActiveNote() noexcept; Iterator getActiveNote() noexcept;
bool isExpired(const Iterator& iterator) const; bool isExpired(const Iterator& iterator) const;
@ -32,7 +35,7 @@ public:
private: private:
std::vector<microsec> _input_intervals; std::vector<microsec> _input_intervals;
std::vector<Note*> _timeline; std::vector<ClassicNote*> _timeline;
microsec _visibility_offset; microsec _visibility_offset;
sf::Music _music; sf::Music _music;