forked from NaiJi/project-kyoku
Implement multinotes
This commit is contained in:
parent
206ad5c84a
commit
bf409c0a61
|
@ -1,5 +1,5 @@
|
||||||
#include "classicgraphicsmanager.h"
|
#include "classicgraphicsmanager.h"
|
||||||
#include "classicnote.h"
|
#include "classicsprite.h"
|
||||||
|
|
||||||
ClassicGraphicsManager::ClassicGraphicsManager(sf::RenderTarget& target) :
|
ClassicGraphicsManager::ClassicGraphicsManager(sf::RenderTarget& target) :
|
||||||
_sprite_container({Type::UP, Type::DOWN,
|
_sprite_container({Type::UP, Type::DOWN,
|
||||||
|
@ -8,19 +8,22 @@ ClassicGraphicsManager::ClassicGraphicsManager(sf::RenderTarget& target) :
|
||||||
_render_target(target)
|
_render_target(target)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void ClassicGraphicsManager::initGraphics(ClassicNote* note)
|
std::shared_ptr<ClassicSprite> ClassicGraphicsManager::getSprite(Type type)
|
||||||
{
|
{
|
||||||
note->setSprite(_sprite_container.getSprite(note->type()));
|
return _sprite_container.getSprite(type);
|
||||||
note->sprite()->setCoordinates(note->getCoordinates(), 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicGraphicsManager::resetGraphics(ClassicNote* note)
|
void ClassicGraphicsManager::draw(const std::shared_ptr<ClassicSprite>& sprite)
|
||||||
{
|
{
|
||||||
_sprite_container.resetSprite(note->sprite(), note->type());
|
_render_target.draw(*sprite);
|
||||||
note->setSprite(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicGraphicsManager::draw(const ClassicNote *note)
|
void ClassicGraphicsManager::drawLine(const Coordinates &p1, const Coordinates &p2)
|
||||||
{
|
{
|
||||||
_render_target.draw(*note->sprite());
|
sf::VertexArray line(sf::LinesStrip, 2);
|
||||||
|
line[0].color = sf::Color::Yellow;
|
||||||
|
line[0].position = {p1.x + 10, p1.y};
|
||||||
|
line[1].color = sf::Color::Blue;
|
||||||
|
line[1].position = {p2.x + 10, p2.y};
|
||||||
|
_render_target.draw(line);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ class ClassicGraphicsManager
|
||||||
public:
|
public:
|
||||||
explicit ClassicGraphicsManager(sf::RenderTarget& target);
|
explicit ClassicGraphicsManager(sf::RenderTarget& target);
|
||||||
|
|
||||||
void initGraphics(ClassicNote* note);
|
std::shared_ptr<ClassicSprite> getSprite(Type type);
|
||||||
void resetGraphics(ClassicNote* note);
|
void draw(const std::shared_ptr<ClassicSprite> &sprite);
|
||||||
void draw(const ClassicNote *note);
|
void drawLine(const Coordinates &p1, const Coordinates &p2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpriteContainer<Type, ClassicSpriteFactory, ClassicSprite> _sprite_container;
|
SpriteContainer<Type, ClassicSpriteFactory, ClassicSprite> _sprite_container;
|
||||||
|
|
|
@ -25,9 +25,36 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const
|
||||||
|
|
||||||
float x = 90.;
|
float x = 90.;
|
||||||
|
|
||||||
|
int counter = 3;
|
||||||
|
|
||||||
while (bpm_iterator < bpm_end)
|
while (bpm_iterator < bpm_end)
|
||||||
{
|
{
|
||||||
notes.emplace_back(new ClassicNote(input_intervals, bpm_iterator, Type::UP, {x, 390.}, _graphics_manager));
|
ClassicNote::ClassicNoteInitializer init;
|
||||||
|
ClassicNote::ClassicNoteInitializer::Element element, element2;
|
||||||
|
init.intervals = input_intervals;
|
||||||
|
init.perfect_offset = bpm_iterator;
|
||||||
|
|
||||||
|
element.coordinates = {x, 390.};
|
||||||
|
element.falling_curve_interpolation = {};
|
||||||
|
element.keys = {sf::Keyboard::W, sf::Keyboard::Up};
|
||||||
|
element.type = Type::UP;
|
||||||
|
|
||||||
|
if (counter == 0)
|
||||||
|
{
|
||||||
|
counter = 3;
|
||||||
|
element2.coordinates = {x, 300.};
|
||||||
|
element2.falling_curve_interpolation = {};
|
||||||
|
element2.keys = {sf::Keyboard::A, sf::Keyboard::Left};
|
||||||
|
element2.type = Type::LEFT;
|
||||||
|
|
||||||
|
init.elements = {element, element2};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
init.elements = {element};
|
||||||
|
|
||||||
|
--counter;
|
||||||
|
|
||||||
|
notes.emplace_back(new ClassicNote(std::move(init), _graphics_manager));
|
||||||
bpm_iterator += tempo_interval;
|
bpm_iterator += tempo_interval;
|
||||||
x += 70;
|
x += 70;
|
||||||
|
|
||||||
|
|
|
@ -4,21 +4,25 @@
|
||||||
#include "classicflyinganimationscenario.h"
|
#include "classicflyinganimationscenario.h"
|
||||||
#include "classicdyinganimationscenario.h"
|
#include "classicdyinganimationscenario.h"
|
||||||
|
|
||||||
ClassicNote::ClassicNote(const std::vector<microsec>& intervals, microsec perfect_offset,
|
ClassicNote::ClassicNote(ClassicNoteInitializer &&init, const std::unique_ptr<ClassicGraphicsManager> &manager) :
|
||||||
Type type, const Coordinates& coord, const std::unique_ptr<ClassicGraphicsManager> &manager) :
|
Note(init.perfect_offset),
|
||||||
Note(perfect_offset),
|
_evaluator(init.intervals, _perfect_offset),
|
||||||
_coordinates(coord),
|
|
||||||
_evaluator(intervals, _perfect_offset),
|
|
||||||
_keys({sf::Keyboard::W, sf::Keyboard::Up}),
|
|
||||||
_graphics_manager(manager),
|
_graphics_manager(manager),
|
||||||
_type(type),
|
|
||||||
_state(State::NONE)
|
_state(State::NONE)
|
||||||
{
|
{
|
||||||
_animations[State::NONE] = nullptr;
|
_elements.resize(init.elements.size());
|
||||||
_animations[State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
for (std::size_t i = 0; i < _elements.size(); ++i)
|
||||||
_animations[State::ACTIVE] = _animations[State::FLYING];
|
{
|
||||||
_animations[State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
_elements[i].keys = init.elements[i].keys;
|
||||||
_animations[State::DEAD] = nullptr;
|
_elements[i].coordinates = init.elements[i].coordinates;
|
||||||
|
_elements[i].type = init.elements[i].type;
|
||||||
|
|
||||||
|
_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
|
bool ClassicNote::isActive() const
|
||||||
|
@ -28,9 +32,14 @@ bool ClassicNote::isActive() const
|
||||||
|
|
||||||
void ClassicNote::putToGame(const microsec &music_offset)
|
void ClassicNote::putToGame(const microsec &music_offset)
|
||||||
{
|
{
|
||||||
_graphics_manager->initGraphics(this);
|
|
||||||
_state = State::FLYING;
|
_state = State::FLYING;
|
||||||
_animations[_state]->launch(_sprite, music_offset, offset());
|
|
||||||
|
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
|
bool ClassicNote::isInGame() const
|
||||||
|
@ -58,7 +67,7 @@ void ClassicNote::update(const microsec& music_offset)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::DYING:
|
case State::DYING:
|
||||||
if (_animations[_state]->isDone())
|
if (_elements[0].animations[_state]->isDone())
|
||||||
_state = State::DEAD;
|
_state = State::DEAD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -66,49 +75,63 @@ void ClassicNote::update(const microsec& music_offset)
|
||||||
if (!_evaluator.isActive(music_offset))
|
if (!_evaluator.isActive(music_offset))
|
||||||
{
|
{
|
||||||
_state = State::DYING;
|
_state = State::DYING;
|
||||||
_animations[_state]->launch(_sprite, music_offset, offset());
|
for (auto& element : _elements)
|
||||||
|
element.animations[_state]->launch(element.sprite, music_offset, offset());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_animations[_state])
|
for (auto& element : _elements)
|
||||||
_animations[_state]->update(music_offset);
|
if (element.animations[_state])
|
||||||
|
element.animations[_state]->update(music_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicNote::input(PlayerInput&& inputdata)
|
void ClassicNote::input(PlayerInput&& inputdata)
|
||||||
{
|
{
|
||||||
auto grade = ClassicNote::Grade::BAD;
|
auto grade = ClassicNote::Grade::BAD;
|
||||||
|
|
||||||
if (std::find(_keys.begin(), _keys.end(), inputdata.event.key.code) != _keys.end())
|
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 = std::all_of(_elements.begin(), _elements.end(),
|
||||||
|
[](const auto& element)
|
||||||
|
{
|
||||||
|
return element.pressed;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (all_pressed)
|
||||||
grade = _evaluator.calculatePrecision(inputdata.timestamp);
|
grade = _evaluator.calculatePrecision(inputdata.timestamp);
|
||||||
|
|
||||||
|
if (all_pressed || !input_valid)
|
||||||
|
{
|
||||||
_state = State::DYING;
|
_state = State::DYING;
|
||||||
_animations[_state]->launch(_sprite, inputdata.timestamp, offset());
|
for (auto& element : _elements)
|
||||||
|
element.animations[_state]->launch(element.sprite, inputdata.timestamp, offset());
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ClassicSprite> ClassicNote::sprite() const noexcept
|
|
||||||
{
|
|
||||||
return _sprite;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::setSprite(const std::shared_ptr<ClassicSprite>& sprite) noexcept
|
|
||||||
{
|
|
||||||
_sprite = sprite;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Coordinates& ClassicNote::getCoordinates() const noexcept
|
|
||||||
{
|
|
||||||
return _coordinates;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type ClassicNote::type() const noexcept
|
|
||||||
{
|
|
||||||
return _type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::draw() const
|
void ClassicNote::draw() const
|
||||||
{
|
{
|
||||||
_graphics_manager->draw(this);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,23 @@ public:
|
||||||
DEAD
|
DEAD
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ClassicNote(const std::vector<microsec>& intervals, microsec perfect_offset,
|
struct ClassicNoteInitializer
|
||||||
Type type, const Coordinates& coord,
|
{
|
||||||
const std::unique_ptr<ClassicGraphicsManager>& manager);
|
std::vector<microsec> intervals;
|
||||||
|
microsec perfect_offset;
|
||||||
|
|
||||||
|
struct Element
|
||||||
|
{
|
||||||
|
Type type;
|
||||||
|
Coordinates coordinates;
|
||||||
|
std::vector<Coordinates> falling_curve_interpolation;
|
||||||
|
std::array<sf::Keyboard::Key, 2> keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Element> elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit ClassicNote(ClassicNoteInitializer&& init, const std::unique_ptr<ClassicGraphicsManager>& manager);
|
||||||
virtual ~ClassicNote() = default;
|
virtual ~ClassicNote() = default;
|
||||||
|
|
||||||
virtual bool isActive() const override;
|
virtual bool isActive() const override;
|
||||||
|
@ -45,22 +59,16 @@ public:
|
||||||
virtual bool isExpired() const override;
|
virtual bool isExpired() const override;
|
||||||
virtual void draw() const override;
|
virtual void draw() const override;
|
||||||
|
|
||||||
Type type() const noexcept;
|
|
||||||
|
|
||||||
std::shared_ptr<ClassicSprite> sprite() const noexcept;
|
|
||||||
void setSprite(const std::shared_ptr<ClassicSprite>& sprite) noexcept;
|
|
||||||
const Coordinates& getCoordinates() const noexcept;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct NoteElement
|
struct NoteElement
|
||||||
{
|
{
|
||||||
std::shared_ptr<ClassicSprite> _sprite;
|
std::shared_ptr<ClassicSprite> sprite;
|
||||||
std::array<std::shared_ptr<ClassicAnimationScenario>, 5> _animations;
|
std::array<std::shared_ptr<ClassicAnimationScenario>, 5> animations;
|
||||||
|
|
||||||
const std::array<const sf::Keyboard::Key, 2> _keys;
|
std::array<sf::Keyboard::Key, 2> keys;
|
||||||
const Coordinates _coordinates;
|
Coordinates coordinates;
|
||||||
const Type _type;
|
Type type;
|
||||||
|
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
sf::Keyboard::Key pressed_as;
|
sf::Keyboard::Key pressed_as;
|
||||||
|
|
|
@ -41,6 +41,11 @@ Coordinates ClassicSprite::coordinates() const
|
||||||
return {_shape.getPosition().x, _shape.getPosition().y};
|
return {_shape.getPosition().x, _shape.getPosition().y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Coordinates ClassicSprite::trailCoordinates() const
|
||||||
|
{
|
||||||
|
return {_trail.getPosition().x, _trail.getPosition().y};
|
||||||
|
}
|
||||||
|
|
||||||
void ClassicSprite::update(float trail_x, float trail_y) noexcept
|
void ClassicSprite::update(float trail_x, float trail_y) noexcept
|
||||||
{
|
{
|
||||||
_trail.setPosition(trail_x, trail_y);
|
_trail.setPosition(trail_x, trail_y);
|
||||||
|
|
|
@ -14,6 +14,7 @@ public:
|
||||||
|
|
||||||
void setCoordinates(const Coordinates &coordinates, float trail_x, float trail_y) noexcept;
|
void setCoordinates(const Coordinates &coordinates, float trail_x, float trail_y) noexcept;
|
||||||
Coordinates coordinates() const;
|
Coordinates coordinates() const;
|
||||||
|
Coordinates trailCoordinates() const;
|
||||||
void update(float trail_x, float trail_y) noexcept;
|
void update(float trail_x, float trail_y) noexcept;
|
||||||
void update() noexcept;
|
void update() noexcept;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue