2021-09-28 05:48:06 +02:00
|
|
|
#pragma once
|
|
|
|
|
2022-03-15 18:11:17 +01:00
|
|
|
#include "core/precisionevaluator.h"
|
2022-02-10 00:30:49 +01:00
|
|
|
#include "classicmode/classicnote.h"
|
2022-03-15 18:11:17 +01:00
|
|
|
#include "graphics/animations/classicanimationscenario.h"
|
2022-02-10 00:30:49 +01:00
|
|
|
|
2022-03-15 18:11:17 +01:00
|
|
|
#include <algorithm>
|
2021-09-28 05:48:06 +02:00
|
|
|
|
2022-03-15 18:11:17 +01:00
|
|
|
template <class Element>
|
2021-09-28 05:48:06 +02:00
|
|
|
class ClassicArrowNote : public ClassicNote
|
|
|
|
{
|
|
|
|
public:
|
2022-03-15 18:11:17 +01:00
|
|
|
|
|
|
|
struct Init
|
|
|
|
{
|
|
|
|
const kku::microsec perfect_offset = 0;
|
|
|
|
|
|
|
|
const std::vector<kku::microsec>& intervals = {};
|
|
|
|
const std::vector<Element>& elements = {};
|
|
|
|
};
|
|
|
|
|
2022-02-06 02:33:09 +01:00
|
|
|
enum class Grade
|
|
|
|
{
|
|
|
|
PERFECT,
|
|
|
|
GOOD,
|
|
|
|
BAD
|
|
|
|
};
|
|
|
|
|
2022-03-15 18:11:17 +01:00
|
|
|
explicit ClassicArrowNote(Init&& init) :
|
|
|
|
ClassicNote(init.perfect_offset),
|
|
|
|
_evaluator(init.intervals, init.perfect_offset)
|
|
|
|
{
|
|
|
|
_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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool isActive(const kku::microsec& offset) const override
|
|
|
|
{
|
|
|
|
return _evaluator.isActive(offset)
|
|
|
|
&& _state != State::DYING;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2021-09-28 05:48:06 +02:00
|
|
|
|
2022-03-15 18:11:17 +01:00
|
|
|
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);
|
|
|
|
}
|
2021-09-28 05:48:06 +02:00
|
|
|
|
2022-03-15 18:11:17 +01:00
|
|
|
if (all_pressed || !input_valid)
|
|
|
|
{
|
|
|
|
_state = State::DYING;
|
|
|
|
for (auto& element : _elements)
|
|
|
|
element.animations[_state]->launch(element.sprite, input.timestamp, getPerfectOffset());
|
|
|
|
}
|
2021-09-28 05:48:06 +02:00
|
|
|
|
2022-03-15 18:11:17 +01:00
|
|
|
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;
|
|
|
|
});
|
|
|
|
}
|
2022-02-23 23:45:43 +01:00
|
|
|
|
2021-12-23 18:33:24 +01:00
|
|
|
private:
|
2022-02-06 02:33:09 +01:00
|
|
|
const kku::PrecisionEvaluator<Grade> _evaluator;
|
2022-03-15 18:11:17 +01:00
|
|
|
std::vector<Element> _elements;
|
2021-09-28 05:48:06 +02:00
|
|
|
};
|