forked from NaiJi/project-kyoku
Implement hold for notes
This commit is contained in:
parent
80d2c97766
commit
00360f6c8d
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
struct Beatmap
|
struct Beatmap
|
||||||
{
|
{
|
||||||
std::vector<Note*> notes;
|
std::vector<ClassicNote*> notes;
|
||||||
microsec visibility_offset;
|
microsec visibility_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue