|
|
@ -6,43 +6,254 @@
|
|
|
|
#include "core/timeline.h"
|
|
|
|
#include "core/timeline.h"
|
|
|
|
#include "core/spritecontainer.h"
|
|
|
|
#include "core/spritecontainer.h"
|
|
|
|
|
|
|
|
|
|
|
|
class ClassicSprite;
|
|
|
|
#include "editor/mockelement.h"
|
|
|
|
|
|
|
|
#include "game/arrowelement.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "graphics/animations/classicflyinganimationscenario.h"
|
|
|
|
|
|
|
|
#include "graphics/animations/classicdyinganimationscenario.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <class TNote, class = std::enable_if_t<std::is_base_of<kku::Note, TNote>::value>>
|
|
|
|
class ClassicSceneGraphicsManager : public ClassicGraphicsManager
|
|
|
|
class ClassicSceneGraphicsManager : public ClassicGraphicsManager
|
|
|
|
{
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
explicit ClassicSceneGraphicsManager(const std::shared_ptr<kku::Timeline<ClassicNote>>& timeline,
|
|
|
|
explicit ClassicSceneGraphicsManager(const std::shared_ptr<kku::Timeline<TNote>>& timeline,
|
|
|
|
const std::shared_ptr<ClassicGraphicsFactory>& factory,
|
|
|
|
const std::shared_ptr<ClassicGraphicsFactory>& factory,
|
|
|
|
const kku::microsec& visibility_offset);
|
|
|
|
const kku::microsec& visibility_offset) :
|
|
|
|
|
|
|
|
ClassicGraphicsManager(visibility_offset),
|
|
|
|
|
|
|
|
_sprite_container({Type::UP, Type::DOWN,
|
|
|
|
|
|
|
|
Type::LEFT, Type::RIGHT},
|
|
|
|
|
|
|
|
factory),
|
|
|
|
|
|
|
|
_factory(factory),
|
|
|
|
|
|
|
|
_timeline(timeline)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_timeline->expire(_first);
|
|
|
|
|
|
|
|
_timeline->expire(_last);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void input(kku::GameEvent&& input) override
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (auto it = _first; it != _last; ++it)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(*it)->input(std::move(input));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void display() const override
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (auto it = _first; it != _last; ++it)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
display((*it)->getElements());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void update(const kku::microsec& offset) override
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fetchLastNote(offset);
|
|
|
|
|
|
|
|
fetchFirstNote(offset);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateVisibleNotes(offset);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void display(const std::vector<ArrowElement>& elements) const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < elements.size(); ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const auto& sprite = elements[i].sprite;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (i >= 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//const auto& neighbor_sprite = elements[i - 1].sprite;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//const auto c1 = neighbor_sprite->trailPosition();
|
|
|
|
|
|
|
|
//const auto c2 = sprite->trailPosition();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//_render_target->draw(makeLine(c1, c2));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sprite->display();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void setGraphics(std::vector<ArrowElement>& elements, kku::TimeRange&& range)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (auto& element : elements)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
element.sprite = _sprite_container.getSprite(element.type);
|
|
|
|
|
|
|
|
element.sprite->setPosition(element.position);
|
|
|
|
|
|
|
|
element.sprite->setTrailPosition(kku::Point( 0.f, 9.f ));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::NONE] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DEAD] = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::FLYING]->launch(element.sprite, range.begin, range.end);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void removeGraphics(std::vector<ArrowElement>& elements)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (auto& element : elements)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_sprite_container.resetSprite(element.sprite, element.type);
|
|
|
|
|
|
|
|
element.sprite = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::NONE] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::FLYING] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DYING] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DEAD] = nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void display(const std::vector<MockElement>& elements) const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < elements.size(); ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const auto& sprite = elements[i].sprite;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void input(kku::GameEvent&& input) override;
|
|
|
|
if (i >= 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//const auto& neighbor_sprite = elements[i - 1].sprite;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void display() const override;
|
|
|
|
//const auto c1 = neighbor_sprite->trailPosition();
|
|
|
|
virtual void update(const kku::microsec& offset) override;
|
|
|
|
//const auto c2 = sprite->trailPosition();
|
|
|
|
|
|
|
|
|
|
|
|
virtual void display(const std::vector<ArrowElement>& elements) const override;
|
|
|
|
//_render_target->draw(makeLine(c1, c2));
|
|
|
|
virtual void setGraphics(std::vector<ArrowElement>& elements, kku::TimeRange&& range) override;
|
|
|
|
}
|
|
|
|
virtual void removeGraphics(std::vector<ArrowElement>& elements) override;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void display(const std::vector<MockElement>& elements) const override;
|
|
|
|
sprite->display();
|
|
|
|
virtual void setGraphics(std::vector<MockElement>& elements, kku::TimeRange&& range) override;
|
|
|
|
}
|
|
|
|
virtual void removeGraphics(std::vector<MockElement>& elements) override;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void setGraphics(std::vector<MockElement>& elements, kku::TimeRange&& range)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (auto& element : elements)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
element.sprite = _sprite_container.getSprite(element.type);
|
|
|
|
|
|
|
|
element.sprite->setPosition(element.position);
|
|
|
|
|
|
|
|
element.sprite->setTrailPosition(kku::Point( 0.f, 9.f ));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
element.selection = _factory->createSelection();
|
|
|
|
|
|
|
|
element.selection->adjustTo(element.sprite);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::NONE] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DEAD] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::FLYING]->launch(element.sprite, range.begin, range.end);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void removeGraphics(std::vector<MockElement>& elements)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (auto& element : elements)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_sprite_container.resetSprite(element.sprite, element.type);
|
|
|
|
|
|
|
|
element.sprite = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::NONE] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::FLYING] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DYING] = nullptr;
|
|
|
|
|
|
|
|
element.animations[ClassicNote::State::DEAD] = nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
protected:
|
|
|
|
kku::SpriteContainer<Type, ClassicGraphicsFactory, ClassicSprite> _sprite_container;
|
|
|
|
kku::SpriteContainer<Type, ClassicGraphicsFactory, ClassicSprite> _sprite_container;
|
|
|
|
const std::shared_ptr<const ClassicGraphicsFactory> _factory;
|
|
|
|
const std::shared_ptr<const ClassicGraphicsFactory> _factory;
|
|
|
|
using Iterator = kku::Timeline<ClassicNote>::Iterator;
|
|
|
|
|
|
|
|
|
|
|
|
typedef typename std::set<TNote*>::const_iterator Iterator;
|
|
|
|
|
|
|
|
|
|
|
|
Iterator _first;
|
|
|
|
Iterator _first;
|
|
|
|
Iterator _last;
|
|
|
|
Iterator _last;
|
|
|
|
|
|
|
|
|
|
|
|
const std::shared_ptr<kku::Timeline<ClassicNote>> _timeline;
|
|
|
|
const std::shared_ptr<kku::Timeline<TNote>> _timeline;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline bool nothingToDraw() const noexcept
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return _timeline->isExpired(_first)
|
|
|
|
|
|
|
|
|| _timeline->isExpired(_last);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline bool isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return ((*iterator)->getPerfectOffset() - _visibility_offset) <= music_offset;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void fetchFirstNote(const kku::microsec& offset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (offset < (*_first)->getPerfectOffset())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Iterator note_iterator = _first;
|
|
|
|
|
|
|
|
while (note_iterator != _timeline->begin() && isVisiblyClose(note_iterator, offset))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
--note_iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_first = note_iterator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto note = *_first;
|
|
|
|
|
|
|
|
if (note->getState() != ClassicNote::State::FLYING
|
|
|
|
|
|
|
|
&& note->getState() != ClassicNote::State::DYING
|
|
|
|
|
|
|
|
&& offset <= note->getPerfectOffset())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
note->setState(ClassicNote::State::FLYING);
|
|
|
|
|
|
|
|
setGraphics(note, kku::TimeRange{note->getPerfectOffset() - _visibility_offset, note->getPerfectOffset()});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Iterator note_iterator = _first;
|
|
|
|
|
|
|
|
while (note_iterator != _last)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto note = *note_iterator;
|
|
|
|
|
|
|
|
if (note->getState() == ClassicNote::State::DEAD)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// note->removeGraphics(this);
|
|
|
|
|
|
|
|
++_first;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
++note_iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void fetchLastNote(const kku::microsec& offset)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Iterator note_iterator = _timeline->getTopNote();
|
|
|
|
|
|
|
|
while (!_timeline->isExpired(note_iterator) && isVisiblyClose(note_iterator, offset))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (nothingToDraw())
|
|
|
|
|
|
|
|
_first = note_iterator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto note = *note_iterator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (note->getState() != ClassicNote::State::FLYING
|
|
|
|
|
|
|
|
&& note->getState() != ClassicNote::State::DYING
|
|
|
|
|
|
|
|
&& offset <= note->getPerfectOffset())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
note->setState(ClassicNote::State::FLYING);
|
|
|
|
|
|
|
|
note->setGraphics(this, kku::TimeRange{note->getPerfectOffset() - _visibility_offset, note->getPerfectOffset()});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
++note_iterator;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline bool nothingToDraw() const noexcept;
|
|
|
|
_last = note_iterator;
|
|
|
|
inline bool isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept;
|
|
|
|
}
|
|
|
|
//inline sf::VertexArray makeLine(const kku::Point& c1, const kku::Point& c2) const;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void fetchFirstNote(const kku::microsec& offset);
|
|
|
|
void updateVisibleNotes(const kku::microsec& offset)
|
|
|
|
void fetchLastNote(const kku::microsec& offset);
|
|
|
|
{
|
|
|
|
void updateVisibleNotes(const kku::microsec& offset);
|
|
|
|
for (auto it = _first; it != _last; ++it)
|
|
|
|
|
|
|
|
(*it)->update(offset);
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|