forked from NaiJi/project-kyoku
Turn ArrowNote into a template with T for note element
This commit is contained in:
parent
70d3284eeb
commit
41541e0757
|
@ -27,9 +27,8 @@ std::unique_ptr<kku::Editor> classic::getEditor(const std::shared_ptr<kku::CoreF
|
|||
const kku::microsec visibility_offset = 1648648;
|
||||
|
||||
const auto factory = std::make_shared<ClassicGraphicsFactory>(core_factory);
|
||||
const auto timeline = std::make_shared<kku::Timeline<ClassicMockNote>>();
|
||||
const auto selection_manager = std::make_shared<SelectionManager<ClassicMockNote>>();
|
||||
const auto graphics_manager = std::make_shared<ClassicSceneGraphicsManager<ClassicMockNote>>(timeline, factory, visibility_offset);
|
||||
const auto timeline = std::make_shared<kku::Timeline<ClassicNote>>();
|
||||
const auto graphics_manager = std::make_shared<ClassicSceneGraphicsManager<ClassicNote>>(timeline, factory, visibility_offset);
|
||||
|
||||
return std::make_unique<ClassicEditor>(timeline, graphics_manager, selection_manager);
|
||||
return std::make_unique<ClassicEditor>(timeline, graphics_manager);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "classicmode/classicnote.h"
|
||||
|
||||
ClassicNote::ClassicNote(NoteInitializer &&init) :
|
||||
Note(init.perfect_offset),
|
||||
ClassicNote::ClassicNote(const kku::microsec& perfect_offset) :
|
||||
Note(perfect_offset),
|
||||
_state(State::NONE)
|
||||
{}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "classiceditor.h"
|
||||
|
||||
#include "classicmocknote.h"
|
||||
#include "graphics/classicgraphicsmanager.h"
|
||||
#include "editor/selectionmanager.h"
|
||||
|
||||
|
@ -11,9 +10,9 @@
|
|||
|
||||
#include "callbacks/callbacksimple.h"
|
||||
|
||||
ClassicEditor::ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicMockNote>>& timeline,
|
||||
ClassicEditor::ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicNote>>& timeline,
|
||||
const std::shared_ptr<ClassicGraphicsManager>& graphics_manager,
|
||||
const std::shared_ptr<SelectionManager<ClassicMockNote>>& selection_manager) :
|
||||
const std::shared_ptr<SelectionManager<ClassicNote>>& selection_manager) :
|
||||
_timeline(timeline),
|
||||
_graphics_manager(graphics_manager),
|
||||
_selection_manager(selection_manager),
|
||||
|
@ -31,7 +30,7 @@ ClassicEditor::ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicMockNote
|
|||
kku::microsec bpm_end = starting_beat_offset + (interval * amount_of_beats);
|
||||
|
||||
std::vector<kku::microsec> input_intervals = {note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset};
|
||||
std::set<ClassicMockNote*, kku::NotePtrComparator> notes;
|
||||
std::set<ClassicNote*, kku::NotePtrComparator> notes;
|
||||
input_intervals.shrink_to_fit();
|
||||
|
||||
bpm_iterator += tempo_interval;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "core/timeline.h"
|
||||
#include "selectionmanager.h"
|
||||
|
||||
#include "classicmocknote.h"
|
||||
#include "classicmode/classicnote.h"
|
||||
#include "classicmode/classicactions.h"
|
||||
|
||||
class ClassicGraphicsManager;
|
||||
|
@ -14,9 +14,9 @@ class ClassicGraphicsManager;
|
|||
class ClassicEditor : public kku::Editor
|
||||
{
|
||||
public:
|
||||
explicit ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicMockNote>>& timeline,
|
||||
explicit ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicNote>>& timeline,
|
||||
const std::shared_ptr<ClassicGraphicsManager>& graphics_manager,
|
||||
const std::shared_ptr<SelectionManager<ClassicMockNote>>& selection_manager);
|
||||
const std::shared_ptr<SelectionManager<ClassicNote>>& selection_manager);
|
||||
|
||||
virtual void input(kku::GameEvent&& input) override;
|
||||
virtual void update(kku::UpdateData&& updatedata) override;
|
||||
|
@ -28,9 +28,9 @@ public:
|
|||
private:
|
||||
inline kku::microsec adjustOffset(kku::microsec offset) const noexcept;
|
||||
|
||||
const std::shared_ptr<kku::Timeline<ClassicMockNote>> _timeline;
|
||||
const std::shared_ptr<kku::Timeline<ClassicNote>> _timeline;
|
||||
const std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
||||
const std::shared_ptr<SelectionManager<ClassicMockNote>> _selection_manager;
|
||||
const std::shared_ptr<SelectionManager<ClassicNote>> _selection_manager;
|
||||
|
||||
Type _selected_type;
|
||||
kku::microsec _current_time;
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
#include "classicmocknote.h"
|
||||
#include "graphics/classicscenegraphicsmanager.h"
|
||||
#include "graphics/animations/classicanimationscenario.h"
|
||||
#include "editor/selectionmanager.h"
|
||||
|
||||
ClassicMockNote::ClassicMockNote(ArrowNoteInitializer&& init, const std::shared_ptr<SelectionManager<ClassicMockNote>>& selection_manager) :
|
||||
ClassicNote(std::move(init.initializer)),
|
||||
_selection_manager(selection_manager)
|
||||
{
|
||||
_elements.resize(init.elements.size());
|
||||
|
||||
for (std::size_t i = 0; i < _elements.size(); ++i)
|
||||
{
|
||||
_elements[i].position = init.elements[i].element.position;
|
||||
_elements[i].type = init.elements[i].element.type;
|
||||
}
|
||||
}
|
||||
|
||||
bool ClassicMockNote::isActive(const kku::microsec &offset) const
|
||||
{
|
||||
(void)offset;
|
||||
return _state != State::DEAD
|
||||
&& _state != State::NONE;
|
||||
}
|
||||
|
||||
void ClassicMockNote::input(kku::GameEvent&& input)
|
||||
{
|
||||
switch (input.event.type)
|
||||
{
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
case kku::SystemEvent::Type::MousePress:
|
||||
{
|
||||
bool selection_changed = false;
|
||||
std::size_t amount_selected = 0;
|
||||
|
||||
const auto position = std::get<kku::SystemEvent::Mouse>(input.event.data).position;
|
||||
for (auto& element : _elements)
|
||||
{
|
||||
if (element.sprite->getRectangle()->contains(position))
|
||||
{
|
||||
element.selected = !element.selected;
|
||||
selection_changed = true;
|
||||
if (element.selected)
|
||||
++amount_selected;
|
||||
}
|
||||
}
|
||||
|
||||
if (selection_changed)
|
||||
{
|
||||
if (amount_selected > 0)
|
||||
_selection_manager->fetch(this);
|
||||
else
|
||||
_selection_manager->remove(this);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicMockNote::update(const kku::microsec& music_offset)
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
default: return;
|
||||
break;
|
||||
|
||||
case State::FLYING:
|
||||
if (music_offset >= getPerfectOffset())
|
||||
{
|
||||
_state = State::DYING;
|
||||
for (auto& element : _elements)
|
||||
element.animations[_state]->launch(element.sprite, music_offset, getPerfectOffset());
|
||||
}
|
||||
break;
|
||||
|
||||
case State::DYING:
|
||||
if (_elements[0].animations[_state]->isDone())
|
||||
_state = State::DEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto& element : _elements)
|
||||
if (element.animations[_state])
|
||||
element.animations[_state]->update(music_offset);
|
||||
}
|
||||
|
||||
std::vector<MockElement>& ClassicMockNote::getElements()
|
||||
{
|
||||
return _elements;
|
||||
}
|
||||
|
||||
void ClassicMockNote::deselect()
|
||||
{
|
||||
for (auto& element : _elements)
|
||||
element.selected = false;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "classicmode/classicnote.h"
|
||||
|
||||
#include "mockelement.h"
|
||||
#include "classicmode/arrownoteinitializer.h"
|
||||
#include "selectionmanager.h"
|
||||
|
||||
class ClassicMockNote : public ClassicNote
|
||||
{
|
||||
public:
|
||||
explicit ClassicMockNote(ArrowNoteInitializer&& init, const std::shared_ptr<SelectionManager<ClassicMockNote>>& selection_manager);
|
||||
virtual ~ClassicMockNote() = default;
|
||||
|
||||
virtual bool isActive(const kku::microsec& offset) const override;
|
||||
virtual void update(const kku::microsec &music_offset) override;
|
||||
virtual void input(kku::GameEvent&& input) override;
|
||||
|
||||
std::vector<MockElement>& getElements();
|
||||
void deselect();
|
||||
|
||||
private:
|
||||
const std::shared_ptr<SelectionManager<ClassicMockNote>> _selection_manager;
|
||||
std::vector<MockElement> _elements;
|
||||
};
|
||||
|
||||
using MockElements = std::vector<MockElement>;
|
|
@ -1,124 +0,0 @@
|
|||
#include "classicarrownote.h"
|
||||
#include "graphics/animations/classicanimationscenario.h"
|
||||
#include "holdmanager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
ClassicArrowNote::ClassicArrowNote(ArrowNoteInitializer&& init, const std::shared_ptr<HoldManager>& hold_manager) :
|
||||
ClassicNote(std::move(init.initializer)),
|
||||
_evaluator(init.initializer.intervals, _perfect_offset),
|
||||
_hold_manager(hold_manager),
|
||||
_is_hold(init.hold)
|
||||
{
|
||||
_elements.resize(init.elements.size());
|
||||
|
||||
for (std::size_t i = 0; i < _elements.size(); ++i)
|
||||
{
|
||||
_elements[i].keys = init.elements[i].keys;
|
||||
_elements[i].position = init.elements[i].element.position;
|
||||
_elements[i].type = init.elements[i].element.type;
|
||||
}
|
||||
}
|
||||
|
||||
bool ClassicArrowNote::isActive(const kku::microsec& offset) const
|
||||
{
|
||||
return _evaluator.isActive(offset)
|
||||
&& _state != State::DYING;
|
||||
}
|
||||
|
||||
void ClassicArrowNote::input(kku::GameEvent&& input)
|
||||
{
|
||||
auto grade = Grade::BAD;
|
||||
|
||||
bool input_valid = std::any_of(_elements.begin(), _elements.end(),
|
||||
[input=input](auto& element)
|
||||
{
|
||||
if (element.pressed)
|
||||
return false;
|
||||
|
||||
const auto code = std::get<kku::SystemEvent::Key>(input.event.data).view;
|
||||
auto key_iterator = std::find(element.keys.begin(), element.keys.end(), code);
|
||||
|
||||
bool found_key = key_iterator != element.keys.end();
|
||||
if (found_key)
|
||||
{
|
||||
element.pressed = true;
|
||||
element.pressed_as = code;
|
||||
}
|
||||
|
||||
return found_key;
|
||||
});
|
||||
|
||||
bool all_pressed = allElementsPressed();
|
||||
|
||||
if (all_pressed)
|
||||
{
|
||||
grade = _evaluator.calculatePrecision(input.timestamp);
|
||||
if (isHold())
|
||||
_hold_manager->emplace(this);
|
||||
}
|
||||
|
||||
if (all_pressed || !input_valid)
|
||||
{
|
||||
_state = State::DYING;
|
||||
for (auto& element : _elements)
|
||||
element.animations[_state]->launch(element.sprite, input.timestamp, getPerfectOffset());
|
||||
}
|
||||
|
||||
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
||||
}
|
||||
|
||||
void ClassicArrowNote::update(const kku::microsec& music_offset)
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
default: return;
|
||||
break;
|
||||
|
||||
case State::FLYING:
|
||||
if (!_evaluator.isActive(music_offset) && music_offset > getPerfectOffset())
|
||||
{
|
||||
_state = State::DYING;
|
||||
for (auto& element : _elements)
|
||||
element.animations[_state]->launch(element.sprite, music_offset, getPerfectOffset());
|
||||
}
|
||||
break;
|
||||
|
||||
case State::DYING:
|
||||
if (_elements[0].animations[_state]->isDone())
|
||||
_state = State::DEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto& element : _elements)
|
||||
if (element.animations[_state])
|
||||
element.animations[_state]->update(music_offset);
|
||||
}
|
||||
|
||||
bool ClassicArrowNote::allElementsPressed() const
|
||||
{
|
||||
return std::all_of(_elements.begin(), _elements.end(),
|
||||
[](const auto& element)
|
||||
{
|
||||
return element.pressed;
|
||||
});
|
||||
}
|
||||
|
||||
bool ClassicArrowNote::isPressedAs(kku::SystemEvent::Key::Code key) const
|
||||
{
|
||||
return std::any_of(_elements.begin(), _elements.end(),
|
||||
[key](const auto& element)
|
||||
{
|
||||
return key == element.pressed_as;
|
||||
});
|
||||
}
|
||||
|
||||
bool ClassicArrowNote::isHold() const
|
||||
{
|
||||
return _is_hold;
|
||||
}
|
||||
|
||||
std::vector<ArrowElement>& ClassicArrowNote::getElements()
|
||||
{
|
||||
return _elements;
|
||||
}
|
|
@ -1,14 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "arrowelement.h"
|
||||
#include "core/precisionevaluator.h"
|
||||
#include "classicmode/classicnote.h"
|
||||
#include "classicmode/arrownoteinitializer.h"
|
||||
#include "graphics/animations/classicanimationscenario.h"
|
||||
|
||||
class HoldManager;
|
||||
#include <algorithm>
|
||||
|
||||
template <class Element>
|
||||
class ClassicArrowNote : public ClassicNote
|
||||
{
|
||||
public:
|
||||
|
||||
struct Init
|
||||
{
|
||||
const kku::microsec perfect_offset = 0;
|
||||
|
||||
const std::vector<kku::microsec>& intervals = {};
|
||||
const std::vector<Element>& elements = {};
|
||||
};
|
||||
|
||||
enum class Grade
|
||||
{
|
||||
PERFECT,
|
||||
|
@ -16,25 +26,114 @@ public:
|
|||
BAD
|
||||
};
|
||||
|
||||
explicit ClassicArrowNote(ArrowNoteInitializer&& init, const std::shared_ptr<HoldManager>& hold_manager);
|
||||
virtual ~ClassicArrowNote() = default;
|
||||
explicit ClassicArrowNote(Init&& init) :
|
||||
ClassicNote(init.perfect_offset),
|
||||
_evaluator(init.intervals, init.perfect_offset)
|
||||
{
|
||||
_elements.resize(init.elements.size());
|
||||
|
||||
virtual bool isActive(const kku::microsec& offset) const override;
|
||||
virtual void update(const kku::microsec &music_offset) override;
|
||||
virtual void input(kku::GameEvent&& input) override;
|
||||
for (std::size_t i = 0; i < _elements.size(); ++i)
|
||||
{
|
||||
_elements[i].keys = init.elements[i].keys;
|
||||
_elements[i].position = init.elements[i].element.position;
|
||||
_elements[i].type = init.elements[i].element.type;
|
||||
}
|
||||
}
|
||||
|
||||
bool allElementsPressed() const;
|
||||
bool isPressedAs(kku::SystemEvent::Key::Code key) const;
|
||||
inline bool isHold() const;
|
||||
virtual bool isActive(const kku::microsec& offset) const override
|
||||
{
|
||||
return _evaluator.isActive(offset)
|
||||
&& _state != State::DYING;
|
||||
}
|
||||
|
||||
std::vector<ArrowElement>& getElements();
|
||||
virtual void update(const kku::microsec &music_offset) override
|
||||
{
|
||||
switch (_state)
|
||||
{
|
||||
default: return;
|
||||
break;
|
||||
|
||||
case State::FLYING:
|
||||
if (!_evaluator.isActive(music_offset) && music_offset > getPerfectOffset())
|
||||
{
|
||||
_state = State::DYING;
|
||||
for (auto& element : _elements)
|
||||
element.animations[_state]->launch(element.sprite, music_offset, getPerfectOffset());
|
||||
}
|
||||
break;
|
||||
|
||||
case State::DYING:
|
||||
if (_elements[0].animations[_state]->isDone())
|
||||
_state = State::DEAD;
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto& element : _elements)
|
||||
if (element.animations[_state])
|
||||
element.animations[_state]->update(music_offset);
|
||||
}
|
||||
|
||||
virtual void input(kku::GameEvent&& input) override
|
||||
{
|
||||
auto grade = Grade::BAD;
|
||||
|
||||
bool input_valid = std::any_of(_elements.begin(), _elements.end(),
|
||||
[input=input](auto& element)
|
||||
{
|
||||
if (element.pressed)
|
||||
return false;
|
||||
|
||||
const auto code = std::get<kku::SystemEvent::Key>(input.event.data).view;
|
||||
auto key_iterator = std::find(element.keys.begin(), element.keys.end(), code);
|
||||
|
||||
bool found_key = key_iterator != element.keys.end();
|
||||
if (found_key)
|
||||
{
|
||||
element.pressed = true;
|
||||
element.pressed_as = code;
|
||||
}
|
||||
|
||||
return found_key;
|
||||
});
|
||||
|
||||
bool all_pressed = allElementsPressed();
|
||||
|
||||
if (all_pressed)
|
||||
{
|
||||
grade = _evaluator.calculatePrecision(input.timestamp);
|
||||
//if (isHold())
|
||||
//_hold_manager->emplace(this);
|
||||
}
|
||||
|
||||
if (all_pressed || !input_valid)
|
||||
{
|
||||
_state = State::DYING;
|
||||
for (auto& element : _elements)
|
||||
element.animations[_state]->launch(element.sprite, input.timestamp, getPerfectOffset());
|
||||
}
|
||||
|
||||
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
||||
}
|
||||
|
||||
bool allElementsPressed() const
|
||||
{
|
||||
return std::all_of(_elements.begin(), _elements.end(),
|
||||
[](const auto& element)
|
||||
{
|
||||
return element.pressed;
|
||||
});
|
||||
}
|
||||
|
||||
bool isPressedAs(kku::SystemEvent::Key::Code key) const
|
||||
{
|
||||
return std::any_of(_elements.begin(), _elements.end(),
|
||||
[key](const auto& element)
|
||||
{
|
||||
return key == element.pressed_as;
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
const kku::PrecisionEvaluator<Grade> _evaluator;
|
||||
const std::shared_ptr<HoldManager> _hold_manager;
|
||||
|
||||
std::vector<ArrowElement> _elements;
|
||||
bool _is_hold;
|
||||
std::vector<Element> _elements;
|
||||
};
|
||||
|
||||
using ArrowElements = std::vector<ArrowElement>;
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "classicarrownote.h"
|
||||
#include "game/arrowelement.h"
|
||||
#include "core/gameevent.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class ClassicArrowNote;
|
||||
class ClassicGraphicsManager;
|
||||
|
||||
class HoldManager
|
||||
{
|
||||
public:
|
||||
void emplace(ClassicArrowNote* note);
|
||||
void emplace(ClassicArrowNote<ArrowElement>* note);
|
||||
void checkRelease(kku::SystemEvent::Key::Code released_key);
|
||||
|
||||
void drawHoldBar();
|
||||
|
||||
private:
|
||||
std::vector<ClassicArrowNote*> _notes_on_hold;
|
||||
std::vector<ClassicArrowNote<ArrowElement>*> _notes_on_hold;
|
||||
std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
||||
};
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "classicmode/elementinitializer.h"
|
||||
|
||||
struct ArrowElementInitializer
|
||||
{
|
||||
ElementInitializer element;
|
||||
std::array<kku::SystemEvent::Key::Code, 2> keys;
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "classicmode/noteinitializer.h"
|
||||
#include "arrowelementinitializer.h"
|
||||
|
||||
struct ArrowNoteInitializer
|
||||
{
|
||||
NoteInitializer initializer;
|
||||
bool hold = false;
|
||||
|
||||
std::vector<ArrowElementInitializer> elements;
|
||||
};
|
|
@ -1,10 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/note.h"
|
||||
#include "core/precisionevaluator.h"
|
||||
#include "classicmode/noteinitializer.h"
|
||||
|
||||
class ClassicGraphicsManager;
|
||||
|
||||
class ClassicNote : public kku::Note
|
||||
{
|
||||
|
@ -19,7 +15,7 @@ public:
|
|||
DEAD
|
||||
};
|
||||
|
||||
explicit ClassicNote(NoteInitializer&& init);
|
||||
explicit ClassicNote(const kku::microsec& perfect_offset);
|
||||
virtual ~ClassicNote() override = default;
|
||||
|
||||
virtual bool isActive(const kku::microsec& offset) const override = 0;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "classicactions.h"
|
||||
#include "core/gameevent.h"
|
||||
#include "core/point.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct ElementInitializer
|
||||
{
|
||||
Type type = Type::NONE;
|
||||
|
||||
kku::Point position;
|
||||
std::vector<kku::Point> falling_curve_interpolation;
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "core/time.h"
|
||||
|
||||
struct NoteInitializer
|
||||
{
|
||||
std::vector<kku::microsec> intervals;
|
||||
kku::microsec perfect_offset = 0;
|
||||
};
|
Loading…
Reference in New Issue