forked from NaiJi/project-kyoku
Separate ClassicNote from its logic to ClassicNoteManager
This commit is contained in:
parent
cf1119c742
commit
a223b7253c
|
@ -11,7 +11,7 @@ set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||||
set(CMAKE_USE_WIN32_THREADS_INIT 0)
|
set(CMAKE_USE_WIN32_THREADS_INIT 0)
|
||||||
set(CMAKE_USE_PTHREADS_INIT 1)
|
set(CMAKE_USE_PTHREADS_INIT 1)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h")
|
file(GLOB_RECURSE SOURCES "include/*.h" "src/*.cpp" "src/*.h")
|
||||||
|
|
||||||
# STATIC #
|
# STATIC #
|
||||||
# You need to build SFML from sources with cmake
|
# You need to build SFML from sources with cmake
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "game/inputtype.h"
|
|
||||||
|
|
||||||
class Note
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Note(microsec perfect_offset) :
|
|
||||||
_perfect_offset(perfect_offset) {}
|
|
||||||
virtual ~Note() = default;
|
|
||||||
|
|
||||||
virtual bool isActive() const = 0;
|
|
||||||
virtual void update(const microsec& music_offset) = 0;
|
|
||||||
virtual void input(PlayerInput&& inputdata) = 0;
|
|
||||||
virtual void draw() const = 0;
|
|
||||||
|
|
||||||
virtual void putToGame(const microsec &offset) = 0;
|
|
||||||
virtual bool isInGame() const = 0;
|
|
||||||
virtual bool shouldRemove() const = 0;
|
|
||||||
|
|
||||||
microsec offset() const
|
|
||||||
{
|
|
||||||
return _perfect_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
microsec _perfect_offset;
|
|
||||||
};
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
_sprite_dispatcher[action].push(sprite);
|
_sprite_dispatcher[action].push(sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SpriteContainer(){}
|
~SpriteContainer() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void reallocatePoll(Type sprite_type)
|
inline void reallocatePoll(Type sprite_type)
|
||||||
|
|
|
@ -5,8 +5,8 @@ using microsec = sf::Int64;
|
||||||
|
|
||||||
struct Coordinates
|
struct Coordinates
|
||||||
{
|
{
|
||||||
float x;
|
float x = 0.;
|
||||||
float y;
|
float y = 0.;
|
||||||
|
|
||||||
constexpr inline Coordinates operator+(const Coordinates& right) const noexcept
|
constexpr inline Coordinates operator+(const Coordinates& right) const noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
#include "classictimeline.h"
|
#include "classictimeline.h"
|
||||||
#include "classicnote.h"
|
#include "classicnote.h"
|
||||||
#include "classicmapcreator.h"
|
#include "classicmapcreator.h"
|
||||||
|
#include "classicnotemanager.h"
|
||||||
#include "tools/music.h"
|
#include "tools/music.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
ClassicGame::ClassicGame(std::unique_ptr<ClassicGraphicsManager>&& manager, std::unique_ptr<Music>&& music) :
|
ClassicGame::ClassicGame(std::shared_ptr<ClassicGraphicsManager>&& manager, std::unique_ptr<Music>&& music) :
|
||||||
_timeline(std::make_unique<ClassicTimeline>()),
|
_timeline(std::make_unique<ClassicTimeline>()),
|
||||||
_graphics_manager(std::move(manager)),
|
_graphics_manager(std::move(manager)),
|
||||||
|
_note_manager(std::make_unique<ClassicNoteManager>(_graphics_manager)),
|
||||||
_music(std::move(music)),
|
_music(std::move(music)),
|
||||||
_is_paused(false)
|
_is_paused(false)
|
||||||
{
|
{
|
||||||
|
@ -100,10 +102,10 @@ void ClassicGame::input(PlayerInput&& inputdata)
|
||||||
if (!_timeline->isExpired(note_it))
|
if (!_timeline->isExpired(note_it))
|
||||||
{
|
{
|
||||||
auto note = (*note_it);
|
auto note = (*note_it);
|
||||||
note->input(std::move(inputdata));
|
_note_manager->input(note, std::move(inputdata));
|
||||||
_slap.play();
|
_slap.play();
|
||||||
|
|
||||||
if (note->isHold() && note->allElementsPressed()) // also check for Type
|
if (note->hold && _note_manager->allElementsPressed(note)) // also check for Type
|
||||||
{
|
{
|
||||||
_notes_on_hold.emplace_back(note);
|
_notes_on_hold.emplace_back(note);
|
||||||
std::cout << "HOLD initited by " << inputdata.event.key.code << '\n';
|
std::cout << "HOLD initited by " << inputdata.event.key.code << '\n';
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define CLASSICGAME_H
|
#define CLASSICGAME_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include "game/game.h"
|
#include "game/game.h"
|
||||||
#include "classicactions.h"
|
#include "classicactions.h"
|
||||||
#include <SFML/Audio/SoundBuffer.hpp>
|
#include <SFML/Audio/SoundBuffer.hpp>
|
||||||
|
@ -11,11 +12,12 @@ class Music;
|
||||||
class ClassicNote;
|
class ClassicNote;
|
||||||
class ClassicTimeline;
|
class ClassicTimeline;
|
||||||
class ClassicGraphicsManager;
|
class ClassicGraphicsManager;
|
||||||
|
class ClassicNoteManager;
|
||||||
|
|
||||||
class ClassicGame final : public Game
|
class ClassicGame final : public Game
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ClassicGame(std::unique_ptr<ClassicGraphicsManager>&& manager, std::unique_ptr<Music>&& music);
|
explicit ClassicGame(std::shared_ptr<ClassicGraphicsManager>&& manager, std::unique_ptr<Music>&& music);
|
||||||
virtual ~ClassicGame() override;
|
virtual ~ClassicGame() override;
|
||||||
|
|
||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
|
@ -32,7 +34,9 @@ private:
|
||||||
std::vector<ClassicNote*> _notes_on_hold;
|
std::vector<ClassicNote*> _notes_on_hold;
|
||||||
|
|
||||||
std::unique_ptr<ClassicTimeline> _timeline;
|
std::unique_ptr<ClassicTimeline> _timeline;
|
||||||
std::unique_ptr<ClassicGraphicsManager> _graphics_manager;
|
std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
||||||
|
std::shared_ptr<ClassicNoteManager> _note_manager;
|
||||||
|
|
||||||
sf::SoundBuffer _slap_buffer;
|
sf::SoundBuffer _slap_buffer;
|
||||||
sf::Sound _slap;
|
sf::Sound _slap;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "classicmapcreator.h"
|
#include "classicmapcreator.h"
|
||||||
#include "classicnote.h"
|
#include "classicnote.h"
|
||||||
|
|
||||||
ClassicMapCreator::ClassicMapCreator(const std::unique_ptr<ClassicGraphicsManager>& manager) :
|
ClassicMapCreator::ClassicMapCreator(const std::shared_ptr<ClassicGraphicsManager>& manager) :
|
||||||
_graphics_manager(manager)
|
_graphics_manager(manager)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ struct Beatmap
|
||||||
class ClassicMapCreator
|
class ClassicMapCreator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ClassicMapCreator(const std::unique_ptr<ClassicGraphicsManager>& manager);
|
explicit ClassicMapCreator(const std::shared_ptr<ClassicGraphicsManager>& manager);
|
||||||
|
|
||||||
Beatmap createBeatmap(const std::string& filepath) const;
|
Beatmap createBeatmap(const std::string& filepath) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unique_ptr<ClassicGraphicsManager>& _graphics_manager;
|
const std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLASSICMAPCREATOR_H
|
#endif // CLASSICMAPCREATOR_H
|
||||||
|
|
|
@ -1,162 +0,0 @@
|
||||||
#include "classicnote.h"
|
|
||||||
#include "classicsprite.h"
|
|
||||||
#include "classicgraphicsmanager.h"
|
|
||||||
|
|
||||||
// Replace with interface by dependency injection
|
|
||||||
#include "classicflyinganimationscenario.h"
|
|
||||||
#include "classicdyinganimationscenario.h"
|
|
||||||
//
|
|
||||||
|
|
||||||
ClassicNote::ClassicNote(ClassicNoteInitializer &&init, const std::unique_ptr<ClassicGraphicsManager> &manager) :
|
|
||||||
Note(init.perfect_offset),
|
|
||||||
_evaluator(init.intervals, _perfect_offset),
|
|
||||||
_graphics_manager(manager),
|
|
||||||
_state(State::NONE)
|
|
||||||
{
|
|
||||||
_elements.resize(init.elements.size());
|
|
||||||
_isHold = init.hold;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < _elements.size(); ++i)
|
|
||||||
{
|
|
||||||
_elements[i].keys = init.elements[i].keys;
|
|
||||||
_elements[i].coordinates = init.elements[i].coordinates;
|
|
||||||
_elements[i].type = init.elements[i].type;
|
|
||||||
|
|
||||||
// Animations will be injected into note.
|
|
||||||
_elements[i].animations[State::NONE] = nullptr;
|
|
||||||
_elements[i].animations[State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
|
||||||
_elements[i].animations[State::ACTIVE] = _elements[i].animations[State::FLYING];
|
|
||||||
_elements[i].animations[State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
|
||||||
_elements[i].animations[State::DEAD] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::isActive() const
|
|
||||||
{
|
|
||||||
return _state == State::ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::putToGame(const microsec &music_offset)
|
|
||||||
{
|
|
||||||
_state = State::FLYING;
|
|
||||||
|
|
||||||
for (auto& element : _elements)
|
|
||||||
{
|
|
||||||
element.sprite = _graphics_manager->getSprite(element.type);
|
|
||||||
element.sprite->setCoordinates(element.coordinates, 0., 9.);
|
|
||||||
element.animations[_state]->launch(element.sprite, music_offset, offset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::isInGame() const
|
|
||||||
{
|
|
||||||
return _state == State::FLYING
|
|
||||||
|| _state == State::ACTIVE
|
|
||||||
|| _state == State::DYING;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::shouldRemove() const
|
|
||||||
{
|
|
||||||
return _state == State::DEAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::update(const microsec& music_offset)
|
|
||||||
{
|
|
||||||
switch (_state)
|
|
||||||
{
|
|
||||||
default: return;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::FLYING:
|
|
||||||
if (_evaluator.isActive(music_offset))
|
|
||||||
_state = State::ACTIVE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::DYING:
|
|
||||||
if (_elements[0].animations[_state]->isDone())
|
|
||||||
_state = State::DEAD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::ACTIVE:
|
|
||||||
if (!_evaluator.isActive(music_offset))
|
|
||||||
{
|
|
||||||
_state = State::DYING;
|
|
||||||
for (auto& element : _elements)
|
|
||||||
element.animations[_state]->launch(element.sprite, music_offset, offset());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& element : _elements)
|
|
||||||
if (element.animations[_state])
|
|
||||||
element.animations[_state]->update(music_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::input(PlayerInput&& inputdata)
|
|
||||||
{
|
|
||||||
auto grade = ClassicNote::Grade::BAD;
|
|
||||||
|
|
||||||
bool input_valid = std::any_of(_elements.begin(), _elements.end(),
|
|
||||||
[inputdata=inputdata](auto& element)
|
|
||||||
{
|
|
||||||
if (element.pressed)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto key_iterator = std::find(element.keys.begin(), element.keys.end(), inputdata.event.key.code);
|
|
||||||
bool found_key = key_iterator != element.keys.end();
|
|
||||||
if (found_key)
|
|
||||||
{
|
|
||||||
element.pressed = true;
|
|
||||||
element.pressed_as = inputdata.event.key.code;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found_key;
|
|
||||||
});
|
|
||||||
|
|
||||||
bool all_pressed = allElementsPressed();
|
|
||||||
|
|
||||||
if (all_pressed)
|
|
||||||
grade = _evaluator.calculatePrecision(inputdata.timestamp);
|
|
||||||
|
|
||||||
if (all_pressed || !input_valid)
|
|
||||||
{
|
|
||||||
_state = State::DYING;
|
|
||||||
for (auto& element : _elements)
|
|
||||||
element.animations[_state]->launch(element.sprite, inputdata.timestamp, offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::draw() const
|
|
||||||
{
|
|
||||||
for (std::size_t i = 0; i < _elements.size(); ++i)
|
|
||||||
{
|
|
||||||
if (i >= 1)
|
|
||||||
_graphics_manager->drawLine(_elements[i-1].sprite->trailCoordinates(), _elements[i].sprite->trailCoordinates());
|
|
||||||
_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;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,28 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "game/note.h"
|
|
||||||
#include "game/precisionevaluator.h"
|
|
||||||
#include "classicactions.h"
|
#include "classicactions.h"
|
||||||
|
#include "game/precisionevaluator.h"
|
||||||
|
|
||||||
|
#include "SFML/Window/Keyboard.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
class ClassicSprite;
|
enum class ClassicGrade
|
||||||
class ClassicGraphicsManager;
|
|
||||||
class ClassicAnimationScenario;
|
|
||||||
|
|
||||||
class ClassicNote : public Note
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum class Grade
|
|
||||||
{
|
{
|
||||||
PERFECT,
|
PERFECT,
|
||||||
GOOD,
|
GOOD,
|
||||||
BAD
|
BAD
|
||||||
};
|
};
|
||||||
|
|
||||||
enum State
|
enum ClassicNoteState
|
||||||
{
|
{
|
||||||
NONE,
|
NONE,
|
||||||
|
|
||||||
|
@ -32,58 +26,31 @@ public:
|
||||||
DEAD
|
DEAD
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClassicNoteInitializer
|
class ClassicSprite;
|
||||||
|
class ClassicAnimationScenario;
|
||||||
|
|
||||||
|
struct ClassicNote
|
||||||
{
|
{
|
||||||
|
PrecisionEvaluator<ClassicGrade> evaluator;
|
||||||
std::vector<microsec> intervals;
|
std::vector<microsec> intervals;
|
||||||
microsec perfect_offset;
|
bool hold = false;
|
||||||
bool hold;
|
|
||||||
|
ClassicNoteState state = ClassicNoteState::NONE;
|
||||||
|
|
||||||
struct Element
|
struct Element
|
||||||
{
|
{
|
||||||
Type type;
|
Coordinates coordinates; // Each note may consist of several buttons.
|
||||||
Coordinates coordinates;
|
// For example, ↑ → or ↓ → ←
|
||||||
|
// Note Element represents this idea.
|
||||||
|
bool pressed = false; // Each ending button in such sequence
|
||||||
|
sf::Keyboard::Key pressed_as; // is an element.
|
||||||
|
|
||||||
|
Type type = Type::NONE;
|
||||||
std::vector<Coordinates> falling_curve_interpolation;
|
std::vector<Coordinates> falling_curve_interpolation;
|
||||||
std::array<sf::Keyboard::Key, 2> keys;
|
std::array<sf::Keyboard::Key, 2> available_keys;
|
||||||
|
std::shared_ptr<ClassicSprite> sprite;
|
||||||
|
std::array<std::shared_ptr<ClassicAnimationScenario>, 5> animations;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Element> elements;
|
std::vector<Element> elements;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ClassicNote(ClassicNoteInitializer&& init, const std::unique_ptr<ClassicGraphicsManager>& manager);
|
|
||||||
virtual ~ClassicNote() = default;
|
|
||||||
|
|
||||||
virtual bool isActive() const override;
|
|
||||||
virtual void update(const microsec &music_offset) override;
|
|
||||||
virtual void input(PlayerInput&& inputdata) override;
|
|
||||||
virtual void putToGame(const microsec &music_offset) override;
|
|
||||||
virtual bool isInGame() const override;
|
|
||||||
virtual bool shouldRemove() const override;
|
|
||||||
virtual void draw() const override;
|
|
||||||
|
|
||||||
bool isHold() const;
|
|
||||||
bool allElementsPressed() const;
|
|
||||||
bool isPressedAs(sf::Keyboard::Key key) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct NoteElement
|
|
||||||
{
|
|
||||||
std::shared_ptr<ClassicSprite> sprite;
|
|
||||||
std::array<std::shared_ptr<ClassicAnimationScenario>, 5> animations;
|
|
||||||
|
|
||||||
std::array<sf::Keyboard::Key, 2> keys;
|
|
||||||
Coordinates coordinates; // Each note may consist of several buttons.
|
|
||||||
Type type; // For example, ↑ → or ↓ → ←
|
|
||||||
// Note Element represents this idea.
|
|
||||||
bool pressed = false; // Each ending button in such sequence
|
|
||||||
sf::Keyboard::Key pressed_as; // is an element.
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<NoteElement> _elements;
|
|
||||||
|
|
||||||
const PrecisionEvaluator<Grade> _evaluator;
|
|
||||||
const std::unique_ptr<ClassicGraphicsManager>& _graphics_manager;
|
|
||||||
|
|
||||||
State _state;
|
|
||||||
bool _isHold;
|
|
||||||
};
|
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
#include "classicnotemanager.h"
|
||||||
|
#include "classicsprite.h"
|
||||||
|
#include "classicgraphicsmanager.h"
|
||||||
|
|
||||||
|
// Replace with interface by dependency injection
|
||||||
|
#include "classicflyinganimationscenario.h"
|
||||||
|
#include "classicdyinganimationscenario.h"
|
||||||
|
//
|
||||||
|
|
||||||
|
ClassicNoteManager::ClassicNoteManager(const std::shared_ptr<ClassicGraphicsManager>& manager) :
|
||||||
|
_graphics_manager(manager)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ClassicNoteManager::~ClassicNoteManager()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool ClassicNoteManager::isActive(const ClassicNote* note) const
|
||||||
|
{
|
||||||
|
return note->state == ClassicNoteState::ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicNoteManager::putToGame(ClassicNote* note, const microsec &music_offset)
|
||||||
|
{
|
||||||
|
note->state = ClassicNoteState::FLYING;
|
||||||
|
|
||||||
|
for (auto& element : note->elements)
|
||||||
|
{
|
||||||
|
element.sprite = _graphics_manager->getSprite(element.type);
|
||||||
|
element.sprite->setCoordinates(element.coordinates, 0., 9.);
|
||||||
|
element.animations[note->state]->launch(element.sprite, music_offset, note->evaluator.offset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicNoteManager::isInGame(const ClassicNote* note) const
|
||||||
|
{
|
||||||
|
return note->state == ClassicNoteState::FLYING
|
||||||
|
|| note->state == ClassicNoteState::ACTIVE
|
||||||
|
|| note->state == ClassicNoteState::DYING;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicNoteManager::shouldRemove(const ClassicNote* note) const
|
||||||
|
{
|
||||||
|
return note->state == ClassicNoteState::DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicNoteManager::update(ClassicNote* note, const microsec& music_offset)
|
||||||
|
{
|
||||||
|
switch (note->state)
|
||||||
|
{
|
||||||
|
default: return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ClassicNoteState::FLYING:
|
||||||
|
if (note->evaluator.isActive(music_offset))
|
||||||
|
note->state = ClassicNoteState::ACTIVE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ClassicNoteState::DYING:
|
||||||
|
if (note->elements[0].animations[note->state]->isDone())
|
||||||
|
note->state = ClassicNoteState::DEAD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ClassicNoteState::ACTIVE:
|
||||||
|
if (!note->evaluator.isActive(music_offset))
|
||||||
|
{
|
||||||
|
note->state = ClassicNoteState::DYING;
|
||||||
|
for (auto& element : note->elements)
|
||||||
|
element.animations[note->state]->launch(element.sprite, music_offset, note->evaluator.offset());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& element : note->elements)
|
||||||
|
if (element.animations[note->state])
|
||||||
|
element.animations[note->state]->update(music_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicNoteManager::input(ClassicNote* note, PlayerInput&& inputdata)
|
||||||
|
{
|
||||||
|
auto grade = ClassicGrade::BAD;
|
||||||
|
|
||||||
|
bool input_valid = std::any_of(note->elements.begin(), note->elements.end(),
|
||||||
|
[inputdata=inputdata](auto& element)
|
||||||
|
{
|
||||||
|
if (element.pressed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto key_iterator = std::find(element.keys.begin(), element.keys.end(), inputdata.event.key.code);
|
||||||
|
bool found_key = key_iterator != element.keys.end();
|
||||||
|
if (found_key)
|
||||||
|
{
|
||||||
|
element.pressed = true;
|
||||||
|
element.pressed_as = inputdata.event.key.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_key;
|
||||||
|
});
|
||||||
|
|
||||||
|
bool all_pressed = allElementsPressed(note);
|
||||||
|
|
||||||
|
if (all_pressed)
|
||||||
|
grade = note->evaluator.calculatePrecision(inputdata.timestamp);
|
||||||
|
|
||||||
|
if (all_pressed || !input_valid)
|
||||||
|
{
|
||||||
|
note->state = ClassicNoteState::DYING;
|
||||||
|
for (auto& element : note->elements)
|
||||||
|
element.animations[note->state]->launch(element.sprite, inputdata.timestamp, note->evaluator.offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicNoteManager::draw(const ClassicNote* note) const
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < note->elements.size(); ++i)
|
||||||
|
{
|
||||||
|
if (i >= 1)
|
||||||
|
_graphics_manager->drawLine(note->elements[i-1].sprite->trailCoordinates(), note->elements[i].sprite->trailCoordinates());
|
||||||
|
_graphics_manager->draw(note->elements[i].sprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicNoteManager::allElementsPressed(const ClassicNote* note) const
|
||||||
|
{
|
||||||
|
return std::all_of(note->elements.begin(), note->elements.end(),
|
||||||
|
[](const auto& element)
|
||||||
|
{
|
||||||
|
return element.pressed;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicNoteManager::isPressedAs(const ClassicNote* note, sf::Keyboard::Key key) const
|
||||||
|
{
|
||||||
|
return std::any_of(note->elements.begin(), note->elements.end(),
|
||||||
|
[key=key](const auto& element)
|
||||||
|
{
|
||||||
|
return key == element.pressed_as;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicNoteManager::setDefaultAnimations(std::array<std::shared_ptr<ClassicAnimationScenario>, 5>& animations) const
|
||||||
|
{
|
||||||
|
animations[ClassicNoteState::NONE] = nullptr;
|
||||||
|
animations[ClassicNoteState::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
||||||
|
animations[ClassicNoteState::ACTIVE] = animations[ClassicNoteState::FLYING];
|
||||||
|
animations[ClassicNoteState::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
||||||
|
animations[ClassicNoteState::DEAD] = nullptr;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "game/inputtype.h"
|
||||||
|
#include "classicnote.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class ClassicGraphicsManager;
|
||||||
|
|
||||||
|
class ClassicNoteManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ClassicNoteManager(const std::shared_ptr<ClassicGraphicsManager>& manager);
|
||||||
|
~ClassicNoteManager();
|
||||||
|
|
||||||
|
bool isActive(const ClassicNote* note) const;
|
||||||
|
void update(ClassicNote* note, const microsec &music_offset);
|
||||||
|
void input(ClassicNote* note, PlayerInput&& inputdata);
|
||||||
|
void putToGame(ClassicNote* note, const microsec &music_offset);
|
||||||
|
bool isInGame(const ClassicNote* note) const;
|
||||||
|
bool shouldRemove(const ClassicNote* note) const;
|
||||||
|
void draw(const ClassicNote* note) const;
|
||||||
|
|
||||||
|
bool allElementsPressed(const ClassicNote* note) const;
|
||||||
|
bool isPressedAs(const ClassicNote* note, sf::Keyboard::Key key) const;
|
||||||
|
|
||||||
|
void setDefaultAnimations(std::array<std::shared_ptr<ClassicAnimationScenario>, 5>& animations) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
||||||
|
};
|
|
@ -94,7 +94,7 @@ void ClassicTimeline::expire(Iterator& iterator)
|
||||||
|
|
||||||
bool ClassicTimeline::isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const
|
bool ClassicTimeline::isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const
|
||||||
{
|
{
|
||||||
return ((*iterator)->offset() - _visibility_offset) <= music_offset;
|
return ((*iterator)->evaluator.offset() - _visibility_offset) <= music_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicTimeline::fetchVisibleNotes()
|
void ClassicTimeline::fetchVisibleNotes()
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class ClassicNote;
|
class ClassicNote;
|
||||||
|
class ClassicNoteManager;
|
||||||
|
class ClassicGraphicsManager;
|
||||||
|
|
||||||
class ClassicTimeline : public Timeline
|
class ClassicTimeline : public Timeline
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue