Compare commits

..

10 Commits

96 changed files with 1403 additions and 1155 deletions

18
.clang-format Normal file
View File

@ -0,0 +1,18 @@
IndentWidth: 4
BreakBeforeBraces: Allman
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Right
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: None
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: true

2
.envrc Normal file
View File

@ -0,0 +1,2 @@
use flake
watch_file shell.nix

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# project-kyoku
I am just trying to create a rhythm game inspired by project-diva
### Initial setup
- Make sure you have a compiler supporting c++17 and cmake
- Make sure you have [sfml](https://www.sfml-dev.org/) installed, either static or not, just make sure to edit impl/ CMake file, you'll see it.
- Now clone it
```
git clone https://dev.udongein.xyz/NaiJi/project-kyoku
```
- Go to the project folder
```
cd project-kyoku/
```
- Now build it!
```
cmake CMakeLists.txt -B ./build
cd ./build
make
```
### Conventional commits
This project follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
`<type>(optional scope): <description>`
Example: `feat(classic-mode): Implement something great`

40
flake.lock Normal file
View File

@ -0,0 +1,40 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1663491030,
"narHash": "sha256-MVsfBhE9US5DvLtBAaTRjwYdv1tLO8xjahM8qLXTgTo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "767542707d394ff15ac1981e903e005ba69528b5",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

14
flake.nix Normal file
View File

@ -0,0 +1,14 @@
{
description = "Project Kyoku";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShell = import ./shell.nix { inherit pkgs; };
}
);
}

View File

@ -27,8 +27,10 @@ struct Area
inline kku::Point position() const noexcept
{
return kku::Point{static_cast<float>(left),
static_cast<float>(top) };
return kku::Point{
static_cast<float>(left),
static_cast<float>(top),
};
}
inline void moveBy(const kku::Vector2<T> &vector)
@ -43,4 +45,4 @@ struct Area
}
};
}
} // namespace kku

View File

@ -40,4 +40,4 @@ struct BPMSectionComparator
}
};
}
} // namespace kku

View File

@ -14,4 +14,4 @@ struct Color
unsigned char alpha = 0;
};
}
} // namespace kku

View File

@ -2,13 +2,13 @@
#include <memory>
#include "core/music.h"
#include "core/text.h"
#include "core/resourceholder.h"
#include "core/rectangle.h"
#include "core/vector.h"
#include "core/line.h"
#include "core/music.h"
#include "core/rectangle.h"
#include "core/resourceholder.h"
#include "core/sprite.h"
#include "core/text.h"
#include "core/vector.h"
namespace kku
{
@ -25,8 +25,9 @@ public:
virtual std::shared_ptr<kku::Text> getText(kku::Font::Id id) const = 0;
virtual std::shared_ptr<kku::Rectangle> getRectangle() const = 0;
virtual std::shared_ptr<kku::Line> getLine() const = 0;
virtual std::shared_ptr<kku::Sprite> getSprite(kku::GUISprite::Id id) const = 0;
virtual std::shared_ptr<kku::Sprite>
getSprite(kku::GUISprite::Id id) const = 0;
virtual kku::Vector2<std::size_t> getRenderSize() const = 0;
};
}
} // namespace kku

View File

@ -1,11 +1,11 @@
#pragma once
#include <set>
#include <algorithm>
#include <set>
#include "core/bpmsection.h"
#include "core/gameevent.h"
#include "core/updatedata.h"
#include "core/bpmsection.h"
namespace kku
{
@ -24,12 +24,14 @@ public:
virtual void display() const = 0;
virtual void recalculate(const microsec &timestamp) = 0;
void setBPMSections(const std::set<BPMSection, BPMSectionComparator>& sections) noexcept
void setBPMSections(
const std::set<BPMSection, BPMSectionComparator> &sections) noexcept
{
_bpm_sections = sections;
}
void setBPMSections(std::set<BPMSection, BPMSectionComparator>&& sections) noexcept
void setBPMSections(
std::set<BPMSection, BPMSectionComparator> &&sections) noexcept
{
_bpm_sections = std::move(sections);
}
@ -46,11 +48,10 @@ public:
bool removeBPMSectionAt(const microsec &offset)
{
auto section_it = std::find_if(_bpm_sections.rbegin(), _bpm_sections.rend(),
auto section_it =
std::find_if(_bpm_sections.rbegin(), _bpm_sections.rend(),
[offset](const auto &section)
{
return section.offset_start < offset;
});
{ return section.offset_start < offset; });
if (section_it != _bpm_sections.rend())
{
@ -65,11 +66,10 @@ public:
BPMSection getBPMSectionAt(const microsec &offset) const
{
auto section_it = std::find_if(_bpm_sections.rbegin(), _bpm_sections.rend(),
auto section_it =
std::find_if(_bpm_sections.rbegin(), _bpm_sections.rend(),
[offset](const auto &section)
{
return section.offset_start < offset;
});
{ return section.offset_start < offset; });
if (section_it != _bpm_sections.rend())
{
@ -80,13 +80,10 @@ public:
return BPMSection();
}
void clearBPMSections() noexcept
{
_bpm_sections.clear();
}
void clearBPMSections() noexcept { _bpm_sections.clear(); }
protected:
std::set<BPMSection, BPMSectionComparator> _bpm_sections;
};
}
} // namespace kku

View File

@ -1,6 +1,5 @@
#pragma once
#include "core/systemevent.h"
#include <string>
namespace kku
@ -23,4 +22,4 @@ public:
virtual Metadata getMetadata() const = 0;
};
}
} // namespace kku

View File

@ -8,4 +8,4 @@ namespace kku
using lambda = std::function<void(void)>;
using predicate = std::function<bool(void)>;
}
} // namespace kku

View File

@ -21,4 +21,4 @@ public:
virtual void display() const = 0;
};
}
} // namespace kku

View File

@ -12,4 +12,4 @@ struct GameEvent
const SystemEvent event;
};
}
} // namespace kku

View File

@ -1,7 +1,7 @@
#pragma once
#include "core/point.h"
#include "core/color.h"
#include "core/point.h"
namespace kku
{
@ -18,4 +18,4 @@ public:
virtual void display() = 0;
};
}
} // namespace kku

View File

@ -32,4 +32,4 @@ public:
virtual kku::microsec getDuration() const = 0;
};
}
} // namespace kku

View File

@ -1,7 +1,7 @@
#pragma once
#include "core/time.h"
#include "core/gameevent.h"
#include "core/time.h"
namespace kku
{
@ -9,8 +9,7 @@ namespace kku
class Note
{
public:
explicit Note(microsec perfect_offset) :
_perfect_offset(perfect_offset) {}
explicit Note(microsec perfect_offset) : _perfect_offset(perfect_offset) {}
virtual ~Note() = default;
virtual bool isActive(const microsec &offset) const = 0;
@ -50,6 +49,4 @@ struct NotePtrComparator
}
};
}
} // namespace kku

View File

@ -8,17 +8,11 @@ struct Point
float x;
float y;
constexpr inline explicit Point() noexcept :
x(0.), y(0.)
{}
constexpr inline explicit Point() noexcept : x(0.), y(0.) {}
constexpr inline explicit Point(int x, int y) noexcept :
x(x), y(y)
{}
constexpr inline explicit Point(int x, int y) noexcept : x(x), y(y) {}
constexpr inline explicit Point(float x, float y) noexcept :
x(x), y(y)
{}
constexpr inline explicit Point(float x, float y) noexcept : x(x), y(y) {}
constexpr inline Point operator+(const Point &right) const noexcept
{
@ -43,4 +37,4 @@ struct Point
}
};
}
} // namespace kku

View File

@ -1,37 +1,34 @@
#pragma once
#include <cmath>
#include <iostream>
#include <numeric>
#include <type_traits>
#include <vector>
#include <cmath>
#include <iostream>
#include "core/time.h"
namespace kku
{
template<typename Grade, typename = std::enable_if_t<std::is_enum<Grade>::value>>
template <typename Grade,
typename = std::enable_if_t<std::is_enum<Grade>::value>>
class PrecisionEvaluator
{
public:
PrecisionEvaluator(const std::vector<microsec>& intervals, microsec offset) :
_offset(offset),
_intervals(intervals)
PrecisionEvaluator(const std::vector<microsec> &intervals, microsec offset)
: _offset(offset), _intervals(intervals)
{
_start_handling_offset = _offset - intervals.back();
_end_handling_offset = _offset + intervals.back();
}
inline microsec offset() const noexcept
{
return _offset;
}
inline microsec offset() const noexcept { return _offset; }
inline bool isActive(microsec music_play_offset) const noexcept
{
return music_play_offset > _start_handling_offset
&& music_play_offset < _end_handling_offset;
return music_play_offset > _start_handling_offset &&
music_play_offset < _end_handling_offset;
}
Grade calculatePrecision(microsec odds) const
@ -66,4 +63,4 @@ private:
const std::vector<microsec> _intervals;
};
}
} // namespace kku

View File

@ -24,4 +24,4 @@ public:
virtual void display() = 0;
};
}
} // namespace kku

View File

@ -1,13 +1,12 @@
#pragma once
#include <memory>
#include <map>
#include <memory>
namespace kku
{
template <typename Resource, typename Id>
class ResourceHolder
template <typename Resource, typename Id> class ResourceHolder
{
public:
inline void load(Id id, std::unique_ptr<Resource> &&resource) noexcept
@ -49,4 +48,4 @@ namespace GUISprite
};
}
}
} // namespace kku

View File

@ -1,6 +1,7 @@
#pragma once
#include "core/area.h"
#include "core/point.h"
#include "core/vector.h"
namespace kku
{
@ -17,4 +18,4 @@ public:
virtual void display() const = 0;
};
}
} // namespace kku

View File

@ -1,7 +1,9 @@
#pragma once
#include <map>
#include <memory>
#include <stack>
#include <map>
namespace kku
{
@ -12,9 +14,8 @@ class SpriteContainer
public:
explicit SpriteContainer(std::initializer_list<Type> &&types,
const std::shared_ptr<SpriteFactory> &factory,
std::size_t reserve_size = 20) :
_sprite_factory(factory),
_poll_reserve_size(reserve_size)
std::size_t reserve_size = 20)
: _sprite_factory(factory), _poll_reserve_size(reserve_size)
{
for (const Type &type : types)
reallocatePoll(type);
@ -33,7 +34,8 @@ public:
return sprite;
}
inline void resetSprite(const std::shared_ptr<Sprite> &sprite, Type action) noexcept
inline void resetSprite(const std::shared_ptr<Sprite> &sprite,
Type action) noexcept
{
sprite->reset();
_sprite_dispatcher[action].push(sprite);
@ -59,4 +61,4 @@ private:
std::size_t _poll_reserve_size;
};
}
} // namespace kku

View File

@ -162,10 +162,11 @@ struct SystemEvent
};
struct None
{};
{
};
Type type = Type::None;
std::variant<Size, Key, Mouse, None> data;
};
}
} // namespace kku

View File

@ -1,9 +1,9 @@
#pragma once
#include <string>
#include "core/color.h"
#include "core/point.h"
#include "core/vector.h"
#include <string>
namespace kku
{
@ -21,4 +21,4 @@ public:
virtual void display() = 0;
};
}
} // namespace kku

View File

@ -3,20 +3,41 @@
namespace kku
{
/// microsec
///
/// Primitive alias representing microseconds, which
/// is the main time measure in-game.
/// 1 second is 1000000 microseconds.
using microsec = long long;
/// TimeRange
///
/// Object representing a section of time.
/// To ensure order safety use
/// static produceValidated function.
struct TimeRange
{
const microsec begin = 0;
const microsec end = 0;
constexpr inline explicit TimeRange() noexcept :
begin(0), end(0)
{}
constexpr inline explicit TimeRange() noexcept : begin(0), end(0)
{
}
constexpr inline explicit TimeRange(microsec x, microsec y) noexcept :
begin(x), end(y)
{}
constexpr inline explicit TimeRange(microsec x, microsec y) noexcept
: begin(x), end(y)
{
}
/// produceValidated
///
/// Creates an object of TimeRange, but
/// also makes sure to place begin and end
/// in the right order to avoid confusion.
static inline TimeRange produceValidated(microsec x, microsec y) noexcept
{
return (x < y) ? TimeRange(x, y) : TimeRange(y, x);
}
};
}
} // namespace kku

View File

@ -1,22 +1,23 @@
#pragma once
#include <set>
#include <memory>
#include <algorithm>
#include <memory>
#include <set>
#include "core/time.h"
#include "core/note.h"
#include "core/time.h"
namespace kku
{
template <class TNote, class = std::enable_if_t<std::is_base_of<Note, TNote>::value>>
template <class TNote,
class = std::enable_if_t<std::is_base_of<Note, TNote>::value>>
class Timeline
{
public:
explicit Timeline() :
_current_offset(0)
{}
explicit Timeline() : _current_offset(0)
{
}
typedef typename std::set<TNote *>::const_iterator Iterator;
@ -25,8 +26,9 @@ public:
_current_offset = offset;
expire(_top_note);
if (!_timeline.empty())
{
if (_timeline.empty())
return;
Iterator head_iterator = _timeline.begin();
while (!isExpired(head_iterator))
@ -36,7 +38,8 @@ public:
Iterator pre_head = head_iterator;
--pre_head;
_top_note = !isExpired(pre_head) && (*pre_head)->isActive(offset)
_top_note =
!isExpired(pre_head) && (*pre_head)->isActive(offset)
? pre_head
: head_iterator;
break;
@ -48,7 +51,6 @@ public:
if (isExpired(_top_note))
_top_note = _timeline.begin();
}
}
void setNotes(const std::set<TNote *, NotePtrComparator> &notes)
{
@ -72,7 +74,6 @@ public:
_timeline.insert(notes.begin(), notes.end());
recalculate(_current_offset);
update(_current_offset);
}
inline void clear()
@ -114,8 +115,7 @@ public:
inline Iterator getNoteBy(const microsec &music_offset) noexcept
{
return std::find_if(_timeline.begin(), _timeline.end(),
[music_offset](const auto& note)
{
[music_offset](const auto &note) {
return note->getPerfectOffset() == music_offset;
});
}
@ -156,8 +156,8 @@ private:
const auto &top_note = *_top_note;
bool already_played = top_note->getPerfectOffset() < music_offset
&& !top_note->isActive(music_offset);
bool already_played = top_note->getPerfectOffset() < music_offset &&
!top_note->isActive(music_offset);
if (already_played)
++_top_note;
@ -166,6 +166,4 @@ private:
Iterator _top_note;
};
}
} // namespace kku

View File

@ -11,6 +11,4 @@ struct UpdateData
const microsec dt;
};
}
} // namespace kku

View File

@ -9,8 +9,7 @@ namespace kku
///
/// Meaning an element of a vector space in math.
/// Don't mistake for std::vector<T>
template <typename T>
using Vector2 = std::pair<T, T>;
template <typename T> using Vector2 = std::pair<T, T>;
template <typename T>
inline constexpr auto makeVector(T &&l, T &&r) -> Vector2<T>
@ -18,4 +17,4 @@ inline constexpr auto makeVector(T&& l, T&& r) -> Vector2<T>
return std::make_pair(std::forward<T>(l), std::forward<T>(r));
}
}
} // namespace kku

10
shell.nix Normal file
View File

@ -0,0 +1,10 @@
{
pkgs ? import <nixpkgs> {},
unstable ? import <nixos-unstable> {},
}:
with pkgs;
mkShell {
buildInputs = [ sfml ];
nativeBuildInputs = [ ccls cmake ];
}

View File

@ -7,18 +7,22 @@
class Group;
class PushButton;
namespace kku { class Sprite; class Text; }
namespace kku
{
class Sprite;
class Text;
} // namespace kku
class About : public GUIState
{
public:
struct Callbacks
{
kku::lambda onLeaveAboutState;
};
explicit About(const std::shared_ptr<kku::CoreFactory>& factory, Callbacks&& callbacks);
explicit About(const std::shared_ptr<kku::CoreFactory> &factory,
Callbacks &&callbacks);
virtual void input(const kku::SystemEvent &event) override;
virtual void update(const kku::microsec &dt) override;
virtual void display() const override;
@ -36,4 +40,3 @@ private:
std::shared_ptr<Group> _buttons;
std::shared_ptr<PushButton> _exit_button;
};

View File

@ -2,24 +2,28 @@
#include "application/state.h"
#include "core/corefactory.h"
#include "core/music.h"
#include "core/functional.h"
#include "core/music.h"
class BPMCalculator;
class Group;
namespace kku { class Editor; }
namespace kku
{
class Editor;
}
class EditorState : public GUIState
{
public:
struct Callbacks
{
kku::lambda onLeaveEditorState;
};
explicit EditorState(const std::shared_ptr<kku::CoreFactory>& core_factory, std::unique_ptr<kku::Editor>&& editor, Callbacks&& callbacks);
explicit EditorState(const std::shared_ptr<kku::CoreFactory> &core_factory,
std::unique_ptr<kku::Editor> &&editor,
Callbacks &&callbacks);
virtual ~EditorState() override;
virtual void input(const kku::SystemEvent &event) override;
virtual void update(const kku::microsec &dt) override;
@ -38,4 +42,3 @@ private:
std::unique_ptr<kku::Editor> _editor;
};

View File

@ -1,24 +1,24 @@
#pragma once
#include "state.h"
#include "core/music.h"
#include "core/game.h"
#include "core/corefactory.h"
#include "core/functional.h"
#include "core/game.h"
#include "core/music.h"
#include "state.h"
class Group;
class GameState : public GUIState
{
public:
struct Callbacks
{
kku::lambda onLeaveGame;
};
explicit GameState(const std::shared_ptr<kku::CoreFactory>& core_factory, const std::shared_ptr<kku::Game>& game, Callbacks&& callbacks);
explicit GameState(const std::shared_ptr<kku::CoreFactory> &core_factory,
const std::shared_ptr<kku::Game> &game,
Callbacks &&callbacks);
virtual void input(const kku::SystemEvent &event) override;
virtual void update(const kku::microsec &dt) override;
@ -35,4 +35,3 @@ private:
kku::lambda _onEnterGameCallback;
kku::lambda _onLeaveGameCallback;
};

View File

@ -9,7 +9,6 @@ class Group;
class MainMenu : public GUIState
{
public:
struct Callbacks
{
kku::lambda onAppendGameState;
@ -17,7 +16,8 @@ public:
kku::lambda onAppendAboutState;
};
explicit MainMenu(const std::shared_ptr<kku::CoreFactory>& factory, Callbacks&& callbacks);
explicit MainMenu(const std::shared_ptr<kku::CoreFactory> &factory,
Callbacks &&callbacks);
virtual void input(const kku::SystemEvent &event) override;
virtual void update(const kku::microsec &dt) override;
virtual void display() const override;
@ -31,4 +31,3 @@ private:
std::shared_ptr<Group> _buttons;
};

View File

@ -1,17 +1,17 @@
#pragma once
#include <stack>
#include <memory>
#include <stack>
#include "core/systemevent.h"
#include "core/vector.h"
#include "core/time.h"
#include "core/vector.h"
class GUIState
{
public:
enum Tag {
enum Tag
{
SPLASH_SCREEN,
MAIN_MENU,
GAME_PICKER,

View File

@ -1,8 +1,8 @@
#pragma once
#include <vector>
#include <memory>
#include <array>
#include <memory>
#include <vector>
#include "../../include/application/state.h" // HOW? WHY DOESN'T "application/state.h" LINK ON BY ITSELF
#include "core/corefactory.h"

View File

@ -0,0 +1,64 @@
#pragma once
#include <string>
/**
* @brief Basic logging class
*
* Defines helper functions for logging facility. Configured in
* Application::init()
*
*/
class Log
{
public:
enum LogLevel
{
FATAL,
ERROR,
WARN,
INFO,
DEBUG,
};
LogLevel level = WARN; ///< Default logging level
/**
* @brief Prints message to stdout
*
* TODO: write to configurable stream, be it stdout, stderr or even a file
*
* @param level the message level
* @param fmt the message format
* @param ... variable parameters
*/
void log(LogLevel level, const std::string &fmt, ...);
private:
inline std::string _getLabel(LogLevel level)
{
switch (level)
{
case DEBUG:
return "DEBUG";
case INFO:
return "INFO ";
case WARN:
return "WARN ";
case ERROR:
return "ERROR";
case FATAL:
return "FATAL";
default:
return "UNK ";
}
}
};
extern Log LOG; /// Global variable :(
#define INFO(fmt, ...) LOG.log(Log::INFO, fmt, ##__VA_ARGS__)
#define WARN(fmt, ...) LOG.log(Log::WARN, fmt, ##__VA_ARGS__)
#define ERROR(fmt, ...) LOG.log(Log::ERROR, fmt, ##__VA_ARGS__)
#define FATAL(fmt, ...) LOG.log(Log::FATAL, fmt, ##__VA_ARGS__)
#define DEBUG(fmt, ...) LOG.log(Log::DEBUG, fmt, ##__VA_ARGS__)

View File

@ -1,10 +1,10 @@
#include "application/about.h"
#include "widgets/pushbutton.h"
#include "widgets/group.h"
#include "widgets/pushbutton.h"
About::About(const std::shared_ptr<kku::CoreFactory>& factory, About::Callbacks&& callbacks) :
_callbacks(std::move(callbacks)),
_core_factory(factory),
About::About(const std::shared_ptr<kku::CoreFactory> &factory,
About::Callbacks &&callbacks)
: _callbacks(std::move(callbacks)), _core_factory(factory),
_sfml_logo(factory->getSprite(kku::GUISprite::Id::SFML_LOGO)),
_cryptopp_logo(factory->getSprite(kku::GUISprite::Id::CRYPTOPP_LOGO)),
_powered_by_text(factory->getText(kku::Font::Id::GUI)),
@ -42,12 +42,14 @@ void About::enter()
if (!_exit_button)
{
_exit_button = std::make_shared<PushButton>("Return", _core_factory, 48);
_exit_button =
std::make_shared<PushButton>("Return", _core_factory, 48);
_exit_button->setCallback(_callbacks.onLeaveAboutState);
_buttons->addChild(_exit_button);
}
_exit_button->setRect(kku::Area<float>{window_width / 3.f, window_height / 7.f * 4,
_exit_button->setRect(
kku::Area<float>{window_width / 3.f, window_height / 7.f * 4,
window_width / 3.f, window_height / 7.f});
_buttons->setVisibility();
}
@ -56,4 +58,3 @@ void About::leave()
{
_buttons->setVisibility(false);
}

View File

@ -1,30 +1,41 @@
#include "application/application.h"
#include "core/gameevent.h"
#include "application/log.h"
#include "core/editor.h"
#include "core/gameevent.h"
#include "application/mainmenu.h"
#include "application/gamestate.h"
#include "application/editorstate.h"
#include "application/about.h"
#include "application/editorstate.h"
#include "application/gamestate.h"
#include "application/mainmenu.h"
#include "classicmode/classicfactory.h"
Log LOG;
bool Application::init()
{
LOG.level = Log::DEBUG;
DEBUG("Initializing Application");
if (!_core_factory)
return false;
MainMenu::Callbacks callbacks =
{
MainMenu::Callbacks callbacks = {
[&]() { pushState(GUIState::Tag::GAME); },
[&]() { pushState(GUIState::Tag::EDITOR); },
[&]() { pushState(GUIState::Tag::ABOUT); },
};
const auto main_menu = std::make_shared<MainMenu>(_core_factory, std::move(callbacks));
const auto game_state = std::make_shared<GameState>(_core_factory, classic::getGame(_core_factory), GameState::Callbacks{[&](){ popState(); }});
const auto editor = std::make_shared<EditorState>(_core_factory, classic::getEditor(_core_factory), EditorState::Callbacks{[&](){ popState(); }});
const auto about = std::make_shared<About>(_core_factory, About::Callbacks{[&](){ popState(); }});
const auto main_menu =
std::make_shared<MainMenu>(_core_factory, std::move(callbacks));
const auto game_state = std::make_shared<GameState>(
_core_factory, classic::getGame(_core_factory),
GameState::Callbacks{[&]() { popState(); }});
const auto editor = std::make_shared<EditorState>(
_core_factory, classic::getEditor(_core_factory),
EditorState::Callbacks{[&]() { popState(); }});
const auto about = std::make_shared<About>(
_core_factory, About::Callbacks{[&]() { popState(); }});
_states[GUIState::Tag::MAIN_MENU] = main_menu;
_states[GUIState::Tag::GAME] = game_state;
@ -48,6 +59,8 @@ void Application::update(const kku::microsec& dt)
void Application::pushState(GUIState::Tag new_state)
{
DEBUG("Pushing state %d", new_state);
if (!_state_stack.empty())
_state_stack.back()->leave();
@ -57,6 +70,7 @@ void Application::pushState(GUIState::Tag new_state)
void Application::popState()
{
DEBUG("Popping state");
_state_stack.back()->leave();
_state_stack.pop_back();
_state_stack.back()->enter();

View File

@ -1,24 +1,25 @@
#include "application/editorstate.h"
#include "tools/bpmcalculator.h"
#include "widgets/bpmcalculatorwidget.h"
#include "widgets/button.h"
#include "widgets/editorwidget.h"
#include "widgets/group.h"
#include "widgets/menubar.h"
#include "widgets/window.h"
#include "widgets/editorwidget.h"
#include "widgets/bpmcalculatorwidget.h"
#include "tools/bpmcalculator.h"
#include "core/editor.h"
EditorState::EditorState(const std::shared_ptr<kku::CoreFactory> &core_factory,
std::unique_ptr<kku::Editor> &&editor,
Callbacks&& callbacks) :
_callbacks(std::move(callbacks)),
_core_factory(core_factory),
Callbacks &&callbacks)
: _callbacks(std::move(callbacks)), _core_factory(core_factory),
_editor(std::move(editor))
{}
{
}
EditorState::~EditorState()
{}
{
}
void EditorState::input(const kku::SystemEvent &event)
{
@ -47,13 +48,15 @@ void EditorState::enter()
_bpm_calculator = std::make_shared<BPMCalculator>();
auto &bpm_calculator = _bpm_calculator;
std::shared_ptr<BPMCalculatorWidget> bpm_widget = std::make_shared<BPMCalculatorWidget>(_bpm_calculator, _core_factory);
std::shared_ptr<BPMCalculatorWidget> bpm_widget =
std::make_shared<BPMCalculatorWidget>(_bpm_calculator, _core_factory);
auto button_start = std::make_shared<PushButton>("Start", _core_factory);
auto button_stop = std::make_shared<PushButton>("Stop", _core_factory);
auto button_apply = std::make_shared<PushButton>("Apply", _core_factory);
button_start->setCallback([bpm_calculator, button_start, button_stop, &music]()
button_start->setCallback(
[bpm_calculator, button_start, button_stop, &music]()
{
music->play();
bpm_calculator->start();
@ -61,7 +64,8 @@ void EditorState::enter()
button_stop->setVisibility(true);
});
button_stop->setCallback([bpm_calculator, button_start, button_stop, &music]()
button_stop->setCallback(
[bpm_calculator, button_start, button_stop, &music]()
{
music->stop();
bpm_calculator->stop();
@ -69,7 +73,8 @@ void EditorState::enter()
button_stop->setVisibility(false);
});
button_apply->setCallback([&editor, bpm_calculator]()
button_apply->setCallback(
[&editor, bpm_calculator]()
{
kku::BPMSection section;
const auto &info = bpm_calculator->fetchApproximatedInfo();
@ -85,7 +90,8 @@ void EditorState::enter()
bpm_widget_init.stop = button_stop;
bpm_widget_init.apply = button_apply;
bpm_widget_init.start = button_start;
bpm_widget_init.current_time = [&music]() -> kku::microsec { return music->fetchOffset(); };
bpm_widget_init.current_time = [&music]() -> kku::microsec
{ return music->fetchOffset(); };
bpm_widget->init(std::move(bpm_widget_init));
const auto bpm_widget_callback = [&group, bpm_widget = bpm_widget, &music]()
@ -100,15 +106,18 @@ void EditorState::enter()
auto menu_bar = std::make_shared<MenuBar>(_core_factory);
auto bpm_button = std::make_shared<PushButton>("Calculate BPM", _core_factory);
auto bpm_button =
std::make_shared<PushButton>("Calculate BPM", _core_factory);
bpm_button->setCallback([&group, bpm_widget=bpm_widget]()
bpm_button->setCallback(
[&group, bpm_widget = bpm_widget]()
{
group->blockBy(bpm_widget);
bpm_widget->setVisibility(true);
});
bpm_widget->setRect(kku::Area<float>{render_size.first / 3.f, render_size.second / 3.f,
bpm_widget->setRect(
kku::Area<float>{render_size.first / 3.f, render_size.second / 3.f,
render_size.first / 3.f, render_size.second / 3.f});
bpm_widget->addBarButton("X", bpm_widget_callback);
@ -120,9 +129,11 @@ void EditorState::enter()
auto test_menu_3 = std::make_shared<MenuDrop>(_core_factory);
test_menu_3->setRect(kku::Area<float>{0., 0., 200., 27. * 5.});
auto test_cascade_button = std::make_shared<CascadeMenuButton>("Show submenu", _core_factory);
auto test_cascade_button =
std::make_shared<CascadeMenuButton>("Show submenu", _core_factory);
auto test_cascade_button_2 = std::make_shared<CascadeMenuButton>("Show submenu 2", _core_factory);
auto test_cascade_button_2 =
std::make_shared<CascadeMenuButton>("Show submenu 2", _core_factory);
auto quit_button = std::make_shared<PushButton>("Quit", _core_factory);
quit_button->setCallback(_callbacks.onLeaveEditorState);
@ -150,19 +161,18 @@ void EditorState::enter()
menu_bar->setVisibility(true);
EditorWidget::Callbacks callbacks;
callbacks.onDisplay = [&editor]()
{
editor->display();
};
callbacks.onDisplay = [&editor]() { editor->display(); };
callbacks.onInput = [&editor, &music](const kku::SystemEvent &event)
{
if (event.type == kku::SystemEvent::Type::KeyRelease
&& std::get<kku::SystemEvent::Key>(event.data).view == kku::SystemEvent::Key::Code::Space)
if (event.type == kku::SystemEvent::Type::KeyRelease &&
std::get<kku::SystemEvent::Key>(event.data).view ==
kku::SystemEvent::Key::Code::Space)
music->isPlaying() ? music->pause() : music->play();
else if (event.type == kku::SystemEvent::Type::MouseWheelScroll)
{
const auto& up = std::get<kku::SystemEvent::Mouse>(event.data).scrolled_up;
const auto &up =
std::get<kku::SystemEvent::Mouse>(event.data).scrolled_up;
music->moveOffset(up ? 500000 : -500000);
editor->recalculate(music->fetchOffset());
}
@ -170,8 +180,7 @@ void EditorState::enter()
editor->input(kku::GameEvent{music->fetchOffset(), event});
};
callbacks.onUpdate = [&editor, &music](const kku::microsec& dt)
{
callbacks.onUpdate = [&editor, &music](const kku::microsec &dt) {
editor->update(kku::UpdateData{music->fetchOffset(), dt});
};

View File

@ -4,9 +4,10 @@
#include "core/game.h"
GameState::GameState(const std::shared_ptr<kku::CoreFactory>& core_factory, const std::shared_ptr<kku::Game>& game, Callbacks&& callbacks) :
_core_factory(core_factory),
_game(game),
GameState::GameState(const std::shared_ptr<kku::CoreFactory> &core_factory,
const std::shared_ptr<kku::Game> &game,
Callbacks &&callbacks)
: _core_factory(core_factory), _game(game),
_onLeaveGameCallback(callbacks.onLeaveGame)
{
}

View File

@ -0,0 +1,27 @@
#include <cstdarg>
#include <iostream>
#include <vector>
#include "application/log.h"
void Log::log(LogLevel level, const std::string &fmt, ...)
{
if (level > this->level)
return;
va_list args;
// First va_start: count how many characters are needed for formatting
va_start(args, fmt);
size_t len = std::vsnprintf(NULL, 0, fmt.c_str(), args);
va_end(args);
std::vector<char> buf(len + 1);
// Second va_start: actually write formatted message to buffer
va_start(args, fmt);
std::vsnprintf(&buf[0], len + 1, fmt.c_str(), args);
va_end(args);
std::cout << this->_getLabel(level) << " " << &buf[0] << std::endl;
}

View File

@ -1,10 +1,10 @@
#include "application/mainmenu.h"
#include "widgets/pushbutton.h"
#include "widgets/group.h"
#include "widgets/pushbutton.h"
MainMenu::MainMenu(const std::shared_ptr<kku::CoreFactory>& factory, MainMenu::Callbacks&& callbacks) :
_callbacks(std::move(callbacks)),
_core_factory(factory),
MainMenu::MainMenu(const std::shared_ptr<kku::CoreFactory> &factory,
MainMenu::Callbacks &&callbacks)
: _callbacks(std::move(callbacks)), _core_factory(factory),
_buttons(std::make_shared<Group>())
{
}
@ -30,18 +30,24 @@ void MainMenu::enter()
const float window_width = render_size.first;
const float window_height = render_size.second;
auto button_start = std::make_shared<PushButton>("Start", _core_factory, 48);
button_start->setRect(kku::Area<float>{window_width / 3.f, window_height / 7.f,
auto button_start =
std::make_shared<PushButton>("Start", _core_factory, 48);
button_start->setRect(
kku::Area<float>{window_width / 3.f, window_height / 7.f,
window_width / 3.f, window_height / 7.f});
button_start->setCallback(_callbacks.onAppendGameState);
auto button_editor = std::make_shared<PushButton>("Editor", _core_factory, 48);
button_editor->setRect(kku::Area<float>{window_width / 3.f, window_height / 7.f * 3,
auto button_editor =
std::make_shared<PushButton>("Editor", _core_factory, 48);
button_editor->setRect(
kku::Area<float>{window_width / 3.f, window_height / 7.f * 3,
window_width / 3.f, window_height / 7.f});
button_editor->setCallback(_callbacks.onAppendEditorState);
auto button_about = std::make_shared<PushButton>("About", _core_factory, 48);
button_about->setRect(kku::Area<float>{window_width / 3.f, window_height / 7.f * 5,
auto button_about =
std::make_shared<PushButton>("About", _core_factory, 48);
button_about->setRect(
kku::Area<float>{window_width / 3.f, window_height / 7.f * 5,
window_width / 3.f, window_height / 7.f});
button_about->setCallback(_callbacks.onAppendAboutState);
@ -56,4 +62,3 @@ void MainMenu::leave()
{
_buttons->setVisibility(false);
}

View File

@ -1,14 +1,14 @@
#include "bpmcalculatorwidget.h"
#include "tools/bpmcalculator.h"
#include "core/editor.h"
#include "tools/bpmcalculator.h"
#include <iostream>
BPMCalculatorWidget::BPMCalculatorWidget(const std::shared_ptr<BPMCalculator>& bpm_calculator, const std::shared_ptr<kku::CoreFactory>& factory) :
Window(factory, "BPM Calculation"),
_bpm_calculator(bpm_calculator),
_slider(std::make_shared<BPMSlider>(factory)),
_core_factory(factory),
BPMCalculatorWidget::BPMCalculatorWidget(
const std::shared_ptr<BPMCalculator> &bpm_calculator,
const std::shared_ptr<kku::CoreFactory> &factory)
: Window(factory, "BPM Calculation"), _bpm_calculator(bpm_calculator),
_slider(std::make_shared<BPMSlider>(factory)), _core_factory(factory),
_ticked(false)
{
_bpm_value = _core_factory->getText(kku::Font::Id::GUI);
@ -29,7 +29,8 @@ void BPMCalculatorWidget::input(const kku::SystemEvent& event)
case kku::SystemEvent::Type::KeyPress:
{
if (std::get<kku::SystemEvent::Key>(event.data).view == kku::SystemEvent::Key::Code::Space)
if (std::get<kku::SystemEvent::Key>(event.data).view ==
kku::SystemEvent::Key::Code::Space)
{
_bpm_calculator->click(_current_time());
}
@ -49,8 +50,11 @@ void BPMCalculatorWidget::update(const kku::microsec& dt)
{
_bpm_value->setString(std::to_string(static_cast<int>(beat_info.BPM)));
const kku::microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(_current_time());
const auto time_relation = static_cast<long double>(beat_info.interval) / static_cast<long double>(until_beat);
const kku::microsec until_beat =
_bpm_calculator->fetchTimeUntilNextBeat(_current_time());
const auto time_relation =
static_cast<long double>(beat_info.interval) /
static_cast<long double>(until_beat);
const auto slider_path_left = _slider->getRect().width / time_relation;
if (slider_path_left < 50)
{
@ -83,22 +87,30 @@ void BPMCalculatorWidget::setRect(const kku::Area<float>& rect)
{
Window::setRect(rect);
_slider->setRect(kku::Area<float>{0, 0, rect.width / 8 * 6, 100});
_slider->setPosition(kku::Point{_window_content->getRect().left + rect.width / 8,
_slider->setPosition(
kku::Point{_window_content->getRect().left + rect.width / 8,
_window_content->getRect().top + rect.height / 8 * 3});
_button_start->setRect(kku::Area<float>{0, 0, rect.width / 10 * 3, 30});
_button_start->setPosition(kku::Point{_window_content->getRect().left + rect.width / 7,
_window_content->getRect().top + _window_content->getRect().height - 40});
_button_start->setPosition(
kku::Point{_window_content->getRect().left + rect.width / 7,
_window_content->getRect().top +
_window_content->getRect().height - 40});
_button_stop->setRect(kku::Area<float>{0, 0, rect.width / 10 * 3, 30});
_button_stop->setPosition(kku::Point{_window_content->getRect().left + rect.width / 7,
_window_content->getRect().top + _window_content->getRect().height - 40});
_button_stop->setPosition(
kku::Point{_window_content->getRect().left + rect.width / 7,
_window_content->getRect().top +
_window_content->getRect().height - 40});
_button_apply->setRect(kku::Area<float>{0, 0, rect.width / 10 * 3, 30});
_button_apply->setPosition(kku::Point{_window_content->getRect().left + 50 + (2 * (rect.width / 7)),
_window_content->getRect().top + _window_content->getRect().height - 40});
_button_apply->setPosition(kku::Point{
_window_content->getRect().left + 50 + (2 * (rect.width / 7)),
_window_content->getRect().top + _window_content->getRect().height -
40});
_bpm_value->setPosition(kku::Point{_window_content->getRect().left + rect.width / 8,
_bpm_value->setPosition(
kku::Point{_window_content->getRect().left + rect.width / 8,
_window_content->getRect().top + rect.height / 8});
}

View File

@ -29,10 +29,8 @@ void BPMSlider::display() const
void BPMSlider::setRect(const kku::Area<float> &rect)
{
_slider_background->setRect(rect);
_slider_tick->setRect(kku::Area<float>{rect.left,
rect.top,
rect.width / 30.f,
rect.height});
_slider_tick->setRect(
kku::Area<float>{rect.left, rect.top, rect.width / 30.f, rect.height});
}
void BPMSlider::setPosition(const kku::Point &position)
@ -64,6 +62,7 @@ kku::Point BPMSlider::getPosition() const
void BPMSlider::setTickPosition(float x_position)
{
_slider_tick->setPosition(kku::Point{_slider_background->getPosition().x + x_position,
_slider_tick->setPosition(
kku::Point{_slider_background->getPosition().x + x_position,
_slider_tick->getPosition().y});
}

View File

@ -1,8 +1,10 @@
#include "button.h"
#include <iostream>
Button::Button(const std::string &text, const std::shared_ptr<kku::CoreFactory>& factory, unsigned int font_size) :
_core_factory(factory)
Button::Button(const std::string &text,
const std::shared_ptr<kku::CoreFactory> &factory,
unsigned int font_size)
: _core_factory(factory)
{
_button_text = _core_factory->getText(kku::Font::Id::GUI);
_button_text->setString(text);
@ -29,8 +31,7 @@ void Button::display() const
void Button::setRect(const kku::Area<float> &rect)
{
_button_content->setRect(rect);
_button_text->setPosition(kku::Point{rect.left + 5,
rect.top + 5});
_button_text->setPosition(kku::Point{rect.left + 5, rect.top + 5});
}
void Button::setPosition(const kku::Point &position)

View File

@ -1,8 +1,10 @@
#include "cascademenubutton.h"
#include "menudrop.h"
CascadeMenuButton::CascadeMenuButton(const std::string& text, const std::shared_ptr<kku::CoreFactory>& factory, unsigned int font_size) :
Button(text, factory, font_size)
CascadeMenuButton::CascadeMenuButton(
const std::string &text, const std::shared_ptr<kku::CoreFactory> &factory,
unsigned int font_size)
: Button(text, factory, font_size)
{
_color_idle = kku::Color{230, 230, 230, 255};
_color_hover = kku::Color{84, 158, 253, 255};
@ -23,7 +25,8 @@ void CascadeMenuButton::input(const kku::SystemEvent& event)
case kku::SystemEvent::Type::MouseMove:
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
if (isUnderMouse(position))
{
_button_content->setColor(_color_hover);
@ -40,7 +43,6 @@ void CascadeMenuButton::input(const kku::SystemEvent& event)
}
break;
}
}
}
@ -65,12 +67,14 @@ void CascadeMenuButton::resetRect()
{
if (_submenu)
{
_submenu->setPosition(kku::Point{_button_content->getPosition().x + _button_content->getRect().width,
_submenu->setPosition(kku::Point{_button_content->getPosition().x +
_button_content->getRect().width,
_button_content->getPosition().y});
}
}
void CascadeMenuButton::setFillColors(kku::Color&& idle_color, kku::Color&& hover_color)
void CascadeMenuButton::setFillColors(kku::Color &&idle_color,
kku::Color &&hover_color)
{
_color_idle = idle_color;
_color_hover = hover_color;

View File

@ -1,11 +1,12 @@
#include "editorwidget.h"
#include "core/editor.h"
EditorWidget::EditorWidget(Callbacks&& callbacks) :
_input(std::move(callbacks.onInput)),
EditorWidget::EditorWidget(Callbacks &&callbacks)
: _input(std::move(callbacks.onInput)),
_update(std::move(callbacks.onUpdate)),
_draw(std::move(callbacks.onDisplay))
{}
{
}
void EditorWidget::input(const kku::SystemEvent &event)
{

View File

@ -46,10 +46,5 @@ kku::Area<float> Group::getRect() const
kku::Point Group::getPosition() const
{
return kku::Point
{
_rect.top,
_rect.left
};
return kku::Point{_rect.top, _rect.left};
}

View File

@ -1,10 +1,8 @@
#include "menubar.h"
MenuBar::MenuBar(const std::shared_ptr<kku::CoreFactory>& factory) :
_core_factory(factory),
_bar_rect(factory->getRectangle()),
_amount_buttons(0),
_button_width(170)
MenuBar::MenuBar(const std::shared_ptr<kku::CoreFactory> &factory)
: _core_factory(factory), _bar_rect(factory->getRectangle()),
_amount_buttons(0), _button_width(170)
{
_bar_rect->setColor(kku::Color{88, 57, 107, 255});
}
@ -18,7 +16,8 @@ void MenuBar::input(const kku::SystemEvent &event)
case kku::SystemEvent::Type::MouseRelease:
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
if (!isUnderMouse(position))
{
for (auto &submenu : _submenus)
@ -72,29 +71,29 @@ bool MenuBar::isUnderMouse(const kku::Point& position) const
bool submenus_under_mouse = std::any_of(_children.begin(), _children.end(),
[p = position](const auto &child)
{
return child->isUnderMouse(p);
});
{ return child->isUnderMouse(p); });
return bar_under_mouse || submenus_under_mouse;
}
void MenuBar::addRootSubMenu(std::string name, const std::shared_ptr<MenuDrop>& submenu)
void MenuBar::addRootSubMenu(std::string name,
const std::shared_ptr<MenuDrop> &submenu)
{
const auto new_button = std::make_shared<PushButton>(name, _core_factory);
std::size_t current_index = _amount_buttons;
new_button->setRect(kku::Area<float>{static_cast<float>(current_index * _button_width),
0.f,
static_cast<float>(_button_width),
_bar_rect->getRect().height});
new_button->setCallback([submenu=submenu]()
new_button->setRect(kku::Area<float>{
static_cast<float>(current_index * _button_width), 0.f,
static_cast<float>(_button_width), _bar_rect->getRect().height});
new_button->setCallback(
[submenu = submenu]()
{
submenu->setVisibility(true);
submenu->lock();
});
submenu->setPosition(kku::Point{static_cast<float>(current_index * _button_width),
submenu->setPosition(
kku::Point{static_cast<float>(current_index * _button_width),
_bar_rect->getRect().height});
new_button->setColors(kku::Color{171, 141, 189, 255},

View File

@ -1,10 +1,8 @@
#include "menudrop.h"
#include "core/corefactory.h"
MenuDrop::MenuDrop(const std::shared_ptr<kku::CoreFactory>& factory) :
_is_locked(false),
_button_height(27),
_button_index(0)
MenuDrop::MenuDrop(const std::shared_ptr<kku::CoreFactory> &factory)
: _is_locked(false), _button_height(27), _button_index(0)
{
_is_visible = false;
_content_rect = factory->getRectangle();
@ -25,7 +23,8 @@ void MenuDrop::input(const kku::SystemEvent& event)
case kku::SystemEvent::Type::MouseRelease:
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
if (isUnderMouse(position))
{
setVisibility(false);
@ -40,7 +39,8 @@ void MenuDrop::input(const kku::SystemEvent& event)
case kku::SystemEvent::Type::MouseMove:
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
if (!isUnderMouse(position))
{
if (!isLocked() && !hasActiveSubmenus())
@ -55,9 +55,7 @@ bool MenuDrop::hasActiveSubmenus() const
{
return std::any_of(_submenus.begin(), _submenus.end(),
[](const auto &submenu) -> bool
{
return submenu->_is_visible;
});
{ return submenu->_is_visible; });
}
void MenuDrop::update(const kku::microsec &dt)
@ -111,7 +109,8 @@ void MenuDrop::addPushButton(const std::shared_ptr<PushButton>& button)
add(button);
}
void MenuDrop::addCascadeButton(const std::shared_ptr<CascadeMenuButton>& button)
void MenuDrop::addCascadeButton(
const std::shared_ptr<CascadeMenuButton> &button)
{
auto &submenu = button->submenu();
_submenus.emplace_back(submenu);
@ -129,10 +128,10 @@ void MenuDrop::add(const std::shared_ptr<Widget> &widget)
{
const auto &parent_rect = _content_rect->getRect();
widget->setRect(kku::Area<float>{parent_rect.left,
widget->setRect(kku::Area<float>{
parent_rect.left,
parent_rect.top + (parent_rect.height * _button_index),
parent_rect.width,
static_cast<float>(_button_height)});
parent_rect.width, static_cast<float>(_button_height)});
addChild(widget);
++_button_index;

View File

@ -1,8 +1,9 @@
#include "pushbutton.h"
PushButton::PushButton(const std::string& text, const std::shared_ptr<kku::CoreFactory>& factory, unsigned int font_size) :
Button(text, factory, font_size),
_pressed(false)
PushButton::PushButton(const std::string &text,
const std::shared_ptr<kku::CoreFactory> &factory,
unsigned int font_size)
: Button(text, factory, font_size), _pressed(false)
{
_color_idle = kku::Color{230, 230, 230, 255};
_color_pressed = kku::Color{200, 200, 200, 255};
@ -19,7 +20,8 @@ void PushButton::input(const kku::SystemEvent& event)
case kku::SystemEvent::Type::MousePress:
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
if (isUnderMouse(position))
{
_pressed = true;
@ -32,7 +34,8 @@ void PushButton::input(const kku::SystemEvent& event)
{
if (_pressed)
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
_button_content->setColor(_color_idle);
_pressed = false;
if (isUnderMouse(position))

View File

@ -1,8 +1,8 @@
#include "window.h"
Window::Window(const std::shared_ptr<kku::CoreFactory>& factory, const std::string& title) :
_core_factory(factory),
_is_dragging(false)
Window::Window(const std::shared_ptr<kku::CoreFactory> &factory,
const std::string &title)
: _core_factory(factory), _is_dragging(false)
{
_bar_title = _core_factory->getText(kku::Font::Id::GUI);
_bar_title->setString(title);
@ -27,7 +27,8 @@ void Window::input(const kku::SystemEvent& event)
case kku::SystemEvent::Type::MousePress:
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
if (_bar->contains(position))
{
_is_dragging = true;
@ -42,7 +43,8 @@ void Window::input(const kku::SystemEvent& event)
case kku::SystemEvent::Type::MouseMove:
{
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
const auto position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
if (_is_dragging)
{
float x_mouse_diff = position.x - _previous_click_position.x;
@ -80,8 +82,7 @@ void Window::setRect(const kku::Area<float>& rect)
kku::Area<float> bar_rect = {rect.left, rect.top, rect.width, 30};
_bar->setRect(bar_rect);
_bar_title->setPosition(kku::Point{rect.left + 5,
rect.top + 5});
_bar_title->setPosition(kku::Point{rect.left + 5, rect.top + 5});
}
void Window::setPosition(const kku::Point &position)
@ -114,8 +115,7 @@ void Window::addBarButton(const std::string &text, kku::lambda callback)
auto b = std::make_shared<PushButton>(text, _core_factory, 20);
b->setCallback(callback);
b->setRect({area.left + area.width - 35,
area.top, 30, 30});
b->setRect({area.left + area.width - 35, area.top, 30, 30});
Widget::addChild(b);
}

View File

@ -1,13 +1,13 @@
#include "applicationsfml.h"
#include "sfml/corefactorysfml.h"
#include "sfml/application/inputconvertersfml.h"
#include "sfml/corefactorysfml.h"
#include <SFML/System/Clock.hpp>
const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 90.f);
ApplicationSFML::ApplicationSFML(sf::RenderWindow * const render_window) :
_render_window(render_window)
ApplicationSFML::ApplicationSFML(sf::RenderWindow *const render_window)
: _render_window(render_window)
{
_render_window->setFramerateLimit(60);
_render_window->setKeyRepeatEnabled(false);

View File

@ -19,120 +19,64 @@ constexpr kku::SystemEvent convert(const sf::Event& event) noexcept
break;
case sf::Event::Resized:
return kku::SystemEvent
{
return kku::SystemEvent{
kku::SystemEvent::Type::Resize,
kku::SystemEvent::Size
{
event.size.width,
event.size.height
}
};
kku::SystemEvent::Size{event.size.width, event.size.height}};
case sf::Event::KeyPressed:
return kku::SystemEvent
{
return kku::SystemEvent{
kku::SystemEvent::Type::KeyPress,
kku::SystemEvent::Key
{
kku::convert(event.key.code),
event.key.alt,
event.key.control,
event.key.shift
}
};
kku::SystemEvent::Key{kku::convert(event.key.code), event.key.alt,
event.key.control, event.key.shift}};
case sf::Event::KeyReleased:
return kku::SystemEvent
{
return kku::SystemEvent{
kku::SystemEvent::Type::KeyRelease,
kku::SystemEvent::Key
{
kku::convert(event.key.code),
event.key.alt,
event.key.control,
event.key.shift
}
};
kku::SystemEvent::Key{kku::convert(event.key.code), event.key.alt,
event.key.control, event.key.shift}};
case sf::Event::MouseWheelScrolled:
return kku::SystemEvent
{
return kku::SystemEvent{
kku::SystemEvent::Type::MouseWheelScroll,
kku::SystemEvent::Mouse
{
kku::Point
{
event.mouseWheelScroll.x,
event.mouseWheelScroll.y
},
kku::SystemEvent::Mouse{
kku::Point{event.mouseWheelScroll.x, event.mouseWheelScroll.y},
(event.mouseWheelScroll.delta > 0),
kku::SystemEvent::Mouse::Button::Wheel
}
};
kku::SystemEvent::Mouse::Button::Wheel}};
case sf::Event::MouseMoved:
return kku::SystemEvent
{
return kku::SystemEvent{
kku::SystemEvent::Type::MouseMove,
kku::SystemEvent::Mouse
{
kku::Point
{
event.mouseMove.x,
event.mouseMove.y
},
kku::SystemEvent::Mouse{
kku::Point{event.mouseMove.x, event.mouseMove.y},
false,
kku::SystemEvent::Mouse::Button::None
}
};
false, kku::SystemEvent::Mouse::Button::None}};
case sf::Event::MouseButtonPressed:
return kku::SystemEvent
{
return kku::SystemEvent{
kku::SystemEvent::Type::MousePress,
kku::SystemEvent::Mouse
{
kku::Point
{
event.mouseButton.x,
event.mouseButton.y
},
kku::SystemEvent::Mouse{
kku::Point{event.mouseButton.x, event.mouseButton.y},
false,
((event.mouseButton.button == sf::Mouse::Button::Left)
? kku::SystemEvent::Mouse::Button::Left
: kku::SystemEvent::Mouse::Button::Right)
}
};
: kku::SystemEvent::Mouse::Button::Right)}};
case sf::Event::MouseButtonReleased:
return kku::SystemEvent
{
return kku::SystemEvent{
kku::SystemEvent::Type::MouseRelease,
kku::SystemEvent::Mouse
{
kku::Point
{
event.mouseButton.x,
event.mouseButton.y
},
kku::SystemEvent::Mouse{
kku::Point{event.mouseButton.x, event.mouseButton.y},
false,
((event.mouseButton.button == sf::Mouse::Button::Left)
? kku::SystemEvent::Mouse::Button::Left
: kku::SystemEvent::Mouse::Button::Right)
}
};
: kku::SystemEvent::Mouse::Button::Right)}};
}
return kku::SystemEvent
{
kku::SystemEvent::Type::None,
kku::SystemEvent::None{}
};
return kku::SystemEvent{kku::SystemEvent::Type::None,
kku::SystemEvent::None{}};
}
}
} // namespace kku

View File

@ -1,13 +1,13 @@
#include "corefactorysfml.h"
#include "rectanglesfml.h"
#include "musicsfml.h"
#include "textsfml.h"
#include "linesfml.h"
#include "musicsfml.h"
#include "rectanglesfml.h"
#include "spritesfml.h"
#include "textsfml.h"
CoreFactorySFML::CoreFactorySFML(sf::RenderTarget * const render_target) :
_render_target(render_target)
CoreFactorySFML::CoreFactorySFML(sf::RenderTarget *const render_target)
: _render_target(render_target)
{
auto gui_font = std::make_unique<sf::Font>();
gui_font->loadFromFile("resources/SourceCodePro-Regular.ttf");
@ -38,7 +38,8 @@ std::shared_ptr<kku::Rectangle> CoreFactorySFML::getRectangle() const
return std::make_unique<LineSFML>(_render_target);
}
std::shared_ptr<kku::Sprite> CoreFactorySFML::getSprite(kku::GUISprite::Id id) const
std::shared_ptr<kku::Sprite>
CoreFactorySFML::getSprite(kku::GUISprite::Id id) const
{
const auto texture = _texture_holder.get(kku::Texture::Id::GUI);
switch (id)
@ -48,12 +49,14 @@ std::shared_ptr<kku::Rectangle> CoreFactorySFML::getRectangle() const
break;
case kku::GUISprite::Id::SFML_LOGO:
return std::make_unique<SpriteSFML>(_render_target, _texture_holder.get(kku::Texture::Id::GUI),
return std::make_unique<SpriteSFML>(
_render_target, _texture_holder.get(kku::Texture::Id::GUI),
kku::Area<unsigned int>{0, 0, 252, 81});
break;
case kku::GUISprite::Id::CRYPTOPP_LOGO:
return std::make_unique<SpriteSFML>(_render_target, _texture_holder.get(kku::Texture::Id::GUI),
return std::make_unique<SpriteSFML>(
_render_target, _texture_holder.get(kku::Texture::Id::GUI),
kku::Area<unsigned int>{252, 0, 135, 36});
break;
}

View File

@ -1,8 +1,8 @@
#pragma once
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Texture.hpp>
@ -16,7 +16,8 @@ public:
virtual std::shared_ptr<kku::Text> getText(kku::Font::Id id) const override;
virtual std::shared_ptr<kku::Rectangle> getRectangle() const override;
virtual std::shared_ptr<kku::Line> getLine() const override;
virtual std::shared_ptr<kku::Sprite> getSprite(kku::GUISprite::Id id) const override;
virtual std::shared_ptr<kku::Sprite>
getSprite(kku::GUISprite::Id id) const override;
virtual kku::Vector2<std::size_t> getRenderSize() const override;
private:

View File

@ -1,7 +1,7 @@
#include "linesfml.h"
LineSFML::LineSFML(sf::RenderTarget * const render_target) :
_render_target(render_target)
LineSFML::LineSFML(sf::RenderTarget *const render_target)
: _render_target(render_target)
{
_vertex = sf::VertexArray(sf::LinesStrip, 2);
}

View File

@ -10,7 +10,8 @@ class LineSFML : public kku::Line
{
public:
explicit LineSFML(sf::RenderTarget *const render_target);
virtual void setPosition(const kku::Point& p1, const kku::Point& p2) override;
virtual void setPosition(const kku::Point &p1,
const kku::Point &p2) override;
virtual void setColor(const kku::Color &c1, const kku::Color &c2) override;
virtual void display() override;

View File

@ -1,10 +1,9 @@
#include "musicsfml.h"
MusicSFML::MusicSFML() :
_sfml_music_offset(0),
_previous_frame_offset(0),
_absolute_offset(0)
{}
MusicSFML::MusicSFML()
: _sfml_music_offset(0), _previous_frame_offset(0), _absolute_offset(0)
{
}
bool MusicSFML::open(const std::string &filepath)
{
@ -48,7 +47,8 @@ kku::microsec MusicSFML::fetchOffset()
if (_music.getStatus() != sf::Music::Status::Playing)
return _absolute_offset;
const auto interpolator_timestamp = _offset_interpolator.getElapsedTime().asMicroseconds();
const auto interpolator_timestamp =
_offset_interpolator.getElapsedTime().asMicroseconds();
const auto sfml_new_offset = _music.getPlayingOffset().asMicroseconds();
_absolute_offset += (interpolator_timestamp - _previous_frame_offset);
@ -86,4 +86,3 @@ kku::microsec MusicSFML::getDuration() const
{
return _music.getDuration().asMicroseconds();
}

View File

@ -1,8 +1,9 @@
#include "rectanglesfml.h"
RectangleSFML::RectangleSFML(sf::RenderTarget * const render_target) :
_render_target(render_target)
{}
RectangleSFML::RectangleSFML(sf::RenderTarget *const render_target)
: _render_target(render_target)
{
}
void RectangleSFML::setRect(const kku::Area<float> &rect)
{
@ -36,8 +37,8 @@ kku::Point RectangleSFML::getPosition() const
void RectangleSFML::setColor(const kku::Color &color)
{
_rectangle.setFillColor(sf::Color{color.red, color.green,
color.blue, color.alpha});
_rectangle.setFillColor(
sf::Color{color.red, color.green, color.blue, color.alpha});
}
kku::Color RectangleSFML::getColor() const

View File

@ -1,7 +1,7 @@
#pragma once
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <memory>
#include "core/rectangle.h"

View File

@ -2,10 +2,12 @@
SpriteSFML::SpriteSFML(sf::RenderTarget *const render_target,
const std::shared_ptr<sf::Texture> &texture,
const kku::Area<unsigned int> &cropping) :
_render_target(render_target),
_sprite(*texture, sf::IntRect(cropping.left, cropping.top, cropping.width, cropping.height))
{}
const kku::Area<unsigned int> &cropping)
: _render_target(render_target),
_sprite(*texture, sf::IntRect(cropping.left, cropping.top, cropping.width,
cropping.height))
{
}
void SpriteSFML::setPosition(const kku::Point &position)
{
@ -15,11 +17,7 @@ void SpriteSFML::setPosition(const kku::Point& position)
kku::Point SpriteSFML::getPosition() const
{
const auto &position = _sprite.getPosition();
return kku::Point
{
position.x,
position.y
};
return kku::Point{position.x, position.y};
}
void SpriteSFML::move(const kku::Vector2<float> &delta)

View File

@ -4,6 +4,7 @@
#include <SFML/Graphics/Sprite.hpp>
#include <memory>
#include "core/area.h"
#include "core/sprite.h"
class SpriteSFML : public kku::Sprite

View File

@ -1,8 +1,8 @@
#include "textsfml.h"
TextSFML::TextSFML(sf::RenderTarget *const render_target,
const std::shared_ptr<const sf::Font>& font) :
_render_target(render_target)
const std::shared_ptr<const sf::Font> &font)
: _render_target(render_target)
{
_text.setFont(*font);
}
@ -29,7 +29,8 @@ void TextSFML::move(const kku::Vector2<float>& delta)
void TextSFML::setColor(const kku::Color &color)
{
_text.setFillColor(sf::Color{color.red, color.green, color.blue, color.alpha});
_text.setFillColor(
sf::Color{color.red, color.green, color.blue, color.alpha});
}
void TextSFML::display()

View File

@ -1,8 +1,8 @@
#pragma once
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Font.hpp>
#include <memory>
#include "core/text.h"

View File

@ -2,7 +2,9 @@
int main()
{
sf::RenderWindow window(sf::VideoMode{1280, 720}, "Project Kyoku", sf::Style::Default);
sf::RenderWindow window(sf::VideoMode{1280, 720}, "Project Kyoku",
sf::Style::Default);
ApplicationSFML app(&window);
if (app.init())
app.run();

View File

@ -1,46 +1,53 @@
#include "classicmode/classicfactory.h"
#include "graphics/classicgraphicsfactory.h"
#include "graphics/classicscenegraphicsmanager.h"
#include "graphics/classictimelinegraphicsmanager.h"
#include "graphics/classicgraphicsfactory.h"
#include "core/timeline.h"
#include "game/classicgame.h"
#include "game/gamecontext.h"
#include "game/holdmanager.h"
#include "editor/classiceditor.h"
#include "editor/editorcontext.h"
#include "editor/selectionmanager.h"
#include "game/classicgame.h"
#include "game/gamecontext.h"
#include "game/holdmanager.h"
std::unique_ptr<kku::Game> classic::getGame(const std::shared_ptr<kku::CoreFactory>& core_factory)
std::unique_ptr<kku::Game>
classic::getGame(const std::shared_ptr<kku::CoreFactory> &core_factory)
{
// read offset from beatmap metadata
const kku::microsec visibility_offset = 1648648;
const auto factory = std::make_shared<ClassicGraphicsFactory>(core_factory);
const auto timeline = std::make_shared<kku::Timeline<ClassicNote>>();
const auto graphics_manager = std::make_shared<ClassicSceneGraphicsManager>(timeline, factory, visibility_offset);
const auto graphics_manager = std::make_shared<ClassicSceneGraphicsManager>(
timeline, factory, visibility_offset);
const auto hold_manager = std::make_shared<HoldManager>();
const auto context = std::make_shared<GameContext>(hold_manager, graphics_manager);
const auto context =
std::make_shared<GameContext>(hold_manager, graphics_manager);
return std::make_unique<ClassicGame>(timeline, context);
}
std::unique_ptr<kku::Editor> classic::getEditor(const std::shared_ptr<kku::CoreFactory>& core_factory)
std::unique_ptr<kku::Editor>
classic::getEditor(const std::shared_ptr<kku::CoreFactory> &core_factory)
{
// read offset from beatmap metadata
const kku::microsec visibility_offset = 1648648;
const auto factory = std::make_shared<ClassicGraphicsFactory>(core_factory);
const auto timeline = std::make_shared<kku::Timeline<ClassicNote>>();
const auto selection_manager = std::make_shared<SelectionManager<ClassicNote>>();
const auto selection_manager =
std::make_shared<SelectionManager<ClassicNote>>();
std::vector<std::shared_ptr<ClassicGraphicsManager>> graphics_managers;
graphics_managers.emplace_back(std::make_shared<ClassicSceneGraphicsManager>(timeline, factory, visibility_offset));
graphics_managers.emplace_back(std::make_shared<ClassicTimelineGraphicsManager>(timeline, factory, visibility_offset * 2));
graphics_managers.emplace_back(
std::make_shared<ClassicSceneGraphicsManager>(timeline, factory,
visibility_offset));
graphics_managers.emplace_back(
std::make_shared<ClassicTimelineGraphicsManager>(
timeline, factory, visibility_offset * 2));
const auto context = std::make_shared<EditorContext>(selection_manager, std::move(graphics_managers));
const auto context = std::make_shared<EditorContext>(
selection_manager, std::move(graphics_managers));
return std::make_unique<ClassicEditor>(timeline, context);
}

View File

@ -1,10 +1,9 @@
#include "classicmode/classicnote.h"
ClassicNote::ClassicNote(const kku::microsec& perfect_offset, int id) :
Note(perfect_offset),
_state(State::NONE),
_id(id)
{}
ClassicNote::ClassicNote(const kku::microsec &perfect_offset, int id)
: Note(perfect_offset), _state(State::NONE), _id(id)
{
}
void ClassicNote::setState(ClassicNote::State state) noexcept
{

View File

@ -1,10 +1,10 @@
#include "callbacksimple.h"
CallbackSimple::CallbackSimple(Init&& init, Metadata&& metadata) :
_run(std::move(init.run)),
_is_enabled(std::move(init.is_enabled)),
CallbackSimple::CallbackSimple(Init &&init, Metadata &&metadata)
: _run(std::move(init.run)), _is_enabled(std::move(init.is_enabled)),
_metadata(std::move(metadata))
{}
{
}
bool CallbackSimple::isEnabled() const
{

View File

@ -1,25 +1,22 @@
#include "classiceditor.h"
#include "graphics/classicgraphicsmanager.h"
#include "editor/selectionmanager.h"
#include "graphics/classicgraphicsmanager.h"
// Replace with interface by dependency injection
#include "graphics/animations/classicflyinganimationscenario.h"
#include "graphics/animations/classicdyinganimationscenario.h"
#include "graphics/animations/classicflyinganimationscenario.h"
//
#include "game/classicarrownote.h"
#include "editorcontext.h"
#include "callbacks/callbacksimple.h"
#include "editorcontext.h"
#include "game/classicarrownote.h"
ClassicEditor::ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicNote>>& timeline,
const std::shared_ptr<EditorContext>& context) :
_timeline(timeline),
_context(context),
_selected_type(Type::UP),
_current_time(0),
_scroll_step(500000),
_note_id(0)
ClassicEditor::ClassicEditor(
const std::shared_ptr<kku::Timeline<ClassicNote>> &timeline,
const std::shared_ptr<EditorContext> &context)
: _timeline(timeline), _context(context), _selected_type(Type::UP),
_current_time(0), _scroll_step(500000), _note_id(0)
{
kku::microsec starting_beat_offset = 402162;
int amount_of_beats = 209;
@ -30,7 +27,8 @@ ClassicEditor::ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicNote>>&
kku::microsec bpm_iterator = starting_beat_offset;
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::vector<kku::microsec> input_intervals = {
note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset};
std::set<ClassicNote *, kku::NotePtrComparator> notes;
input_intervals.shrink_to_fit();
@ -53,6 +51,14 @@ ClassicEditor::ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicNote>>&
bool hold = false;
if (_note_id == 0)
{
element.keys = {kku::SystemEvent::Key::Code::S,
kku::SystemEvent::Key::Code::Down};
element.type = Type::DOWN;
}
if (counter == 0)
{
hold = true;
@ -67,15 +73,8 @@ ClassicEditor::ClassicEditor(const std::shared_ptr<kku::Timeline<ClassicNote>>&
--counter;
ClassicArrowNote::Init init
{
_note_id++,
context,
bpm_iterator,
input_intervals,
{element},
hold
};
ClassicArrowNote::Init init{_note_id++, context, bpm_iterator,
input_intervals, {element}, hold};
notes.insert(new ClassicArrowNote(std::move(init)));
@ -131,11 +130,13 @@ void ClassicEditor::input(kku::GameEvent&& input)
case kku::SystemEvent::Type::MousePress:
{
const auto note = _timeline->getNoteBy(_current_time);
if (_timeline->isExpired(note) && !_bpm_sections.empty() && _current_time >= (*_bpm_sections.begin()).offset_start)
if (_timeline->isExpired(note) && !_bpm_sections.empty() &&
_current_time >= (*_bpm_sections.begin()).offset_start)
{
ArrowElement element;
element.position = std::get<kku::SystemEvent::Mouse>(event.data).position;
element.position =
std::get<kku::SystemEvent::Mouse>(event.data).position;
element.falling_curve_interpolation = {};
element.keys = {kku::SystemEvent::Key::Code::W,
@ -143,15 +144,8 @@ void ClassicEditor::input(kku::GameEvent&& input)
element.type = Type::UP;
ClassicArrowNote::Init init
{
_note_id++,
_context,
_current_time,
{},
{element},
false
};
ClassicArrowNote::Init init{_note_id++, _context, _current_time,
{}, {element}, false};
_timeline->insertNote(new ClassicArrowNote(std::move(init)));
}
@ -163,8 +157,9 @@ void ClassicEditor::input(kku::GameEvent&& input)
break;
}
}
_context->inputUI(std::move(input));
}
void ClassicEditor::update(kku::UpdateData &&updatedata)

View File

@ -4,11 +4,13 @@
#include "graphics/classicgraphicsmanager.h"
#include "graphics/classicnotegraphics.h"
EditorContext::EditorContext(const std::shared_ptr<SelectionManager<ClassicNote>>& selection_manager,
std::vector<std::shared_ptr<ClassicGraphicsManager>>&& graphics_managers) :
_selection_manager(selection_manager),
EditorContext::EditorContext(
const std::shared_ptr<SelectionManager<ClassicNote>> &selection_manager,
std::vector<std::shared_ptr<ClassicGraphicsManager>> &&graphics_managers)
: _selection_manager(selection_manager),
_graphics_managers(std::move(graphics_managers))
{}
{
}
void EditorContext::input(ClassicArrowNote *note, kku::GameEvent &&input) const
{
@ -24,8 +26,9 @@ void EditorContext::input(ClassicArrowNote *note, kku::GameEvent&& input) const
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 : note->getElements())
const auto position =
std::get<kku::SystemEvent::Mouse>(input.event.data).position; for (auto&
element : note->getElements())
{
if (element.sprite->getRectangle()->contains(position))
{
@ -46,17 +49,18 @@ void EditorContext::input(ClassicArrowNote *note, kku::GameEvent&& input) const
break;
}*/
}
}
void EditorContext::update(ClassicArrowNote *note, const kku::microsec& music_offset) const
void EditorContext::update(ClassicArrowNote *note,
const kku::microsec &music_offset) const
{
auto &elements = note->getElements();
switch (note->getState())
{
default: return;
default:
return;
break;
case ClassicArrowNote::State::INITIAL:
@ -66,11 +70,13 @@ void EditorContext::update(ClassicArrowNote *note, const kku::microsec& music_of
break;
case ClassicArrowNote::State::FLYING:
if (!note->isActive(music_offset) && music_offset > note->getPerfectOffset())
if (!note->isActive(music_offset) &&
music_offset > note->getPerfectOffset())
{
note->setState(ClassicArrowNote::State::DYING);
for (auto &element : elements)
element.animations[note->getState()]->launch(element.sprite, music_offset, note->getPerfectOffset());
element.animations[note->getState()]->launch(
element.sprite, music_offset, note->getPerfectOffset());
}
break;
@ -89,11 +95,18 @@ void EditorContext::update(ClassicArrowNote *note, const kku::microsec& music_of
element.animations[note->getState()]->update(music_offset);
}
std::shared_ptr<SelectionManager<ClassicNote>> EditorContext::getSelectionManager() const
std::shared_ptr<SelectionManager<ClassicNote>>
EditorContext::getSelectionManager() const
{
return _selection_manager;
}
void EditorContext::inputUI(kku::GameEvent &&input)
{
for (auto &manager : _graphics_managers)
manager->input(std::move(input));
}
void EditorContext::updateGraphics(const kku::microsec &music_offset)
{
for (auto &manager : _graphics_managers)

View File

@ -17,6 +17,7 @@ public:
virtual void input(ClassicArrowNote *note, kku::GameEvent&& input) const override;
virtual void update(ClassicArrowNote *note, const kku::microsec &music_offset) const override;
void inputUI(kku::GameEvent&& input);
void updateGraphics(const kku::microsec& music_offset);
void displayGraphics() const;

View File

@ -2,6 +2,7 @@
#include <vector>
#include <algorithm>
#include <functional>
template <class T>
class SelectionManager

View File

@ -2,10 +2,9 @@
#include "classicmode/context.h"
#include "graphics/classicgraphicsmanager.h"
ClassicArrowNote::ClassicArrowNote(Init&& init) :
ClassicNote(init.perfect_offset, init.id),
_evaluator(init.intervals, init.perfect_offset),
_context(init.context),
ClassicArrowNote::ClassicArrowNote(Init &&init)
: ClassicNote(init.perfect_offset, init.id),
_evaluator(init.intervals, init.perfect_offset), _context(init.context),
_is_holding(init.is_holding)
{
_elements.resize(init.elements.size());
@ -20,8 +19,7 @@ ClassicArrowNote::ClassicArrowNote(Init&& init) :
bool ClassicArrowNote::isActive(const kku::microsec &offset) const
{
return _evaluator.isActive(offset)
&& _state != State::DYING;
return _evaluator.isActive(offset) && _state != State::DYING;
}
void ClassicArrowNote::update(const kku::microsec &music_offset)
@ -34,9 +32,10 @@ void ClassicArrowNote::input(kku::GameEvent&& input)
_context->input(this, std::move(input));
}
void ClassicArrowNote::draw(const std::shared_ptr<const ClassicGraphicsManager>& graphics_manager) const
void ClassicArrowNote::draw(
const std::shared_ptr<const ClassicGraphicsManager> &graphics_manager) const
{
graphics_manager->draw(_elements);
graphics_manager->draw(this);
}
bool ClassicArrowNote::isHold() const
@ -49,7 +48,13 @@ std::vector<ArrowElement>& ClassicArrowNote::getElements()
return _elements;
}
auto ClassicArrowNote::calculatePrecision(const kku::microsec& offset) const -> Grade
const std::vector<ArrowElement> &ClassicArrowNote::getElements() const
{
return _elements;
}
auto ClassicArrowNote::calculatePrecision(const kku::microsec &offset) const
-> Grade
{
return _evaluator.calculatePrecision(offset);
}
@ -58,7 +63,5 @@ 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;
});
{ return key == element.pressed_as; });
}

View File

@ -40,6 +40,7 @@ public:
bool isHold() const;
std::vector<ArrowElement>& getElements();
const std::vector<ArrowElement>& getElements() const;
Grade calculatePrecision(const kku::microsec& offset) const;
bool isPressedAs(kku::SystemEvent::Key::Code key) const;

View File

@ -1,15 +1,16 @@
#include "classicgame.h"
#include "classicmode/classicnote.h"
#include "classicmapcreator.h"
#include "classicmode/classicnote.h"
#include "gamecontext.h"
#include "holdmanager.h"
#include "graphics/classicgraphicsmanager.h"
#include "holdmanager.h"
ClassicGame::ClassicGame(const std::shared_ptr<kku::Timeline<ClassicNote>>& timeline,
const std::shared_ptr<GameContext>& context) :
_timeline(timeline),
_context(context)
{}
ClassicGame::ClassicGame(
const std::shared_ptr<kku::Timeline<ClassicNote>> &timeline,
const std::shared_ptr<GameContext> &context)
: _timeline(timeline), _context(context)
{
}
void ClassicGame::run()
{
@ -39,10 +40,10 @@ void ClassicGame::input(kku::GameEvent&& input)
case kku::SystemEvent::Type::KeyRelease:
{
_context->getHoldManager()->checkRelease(std::get<kku::SystemEvent::Key>(input.event.data).view);
_context->getHoldManager()->checkRelease(
std::get<kku::SystemEvent::Key>(input.event.data).view);
}
break;
}
}
@ -51,10 +52,12 @@ void ClassicGame::update(kku::UpdateData&& updatedata)
// UNCOMMENT TO TEST AUTOPLAY
/*auto note_it = _timeline->getActiveNote(updatedata.timestamp);
if (!_timeline->isExpired(note_it) && updatedata.timestamp >= (*note_it)->getPerfectOffset())
if (!_timeline->isExpired(note_it) && updatedata.timestamp >=
(*note_it)->getPerfectOffset())
{
auto note = (*note_it);
note->input(kku::GameEvent{updatedata.timestamp, kku::SystemEvent{kku::SystemEvent::Type::None, kku::SystemEvent::Key{}}});
note->input(kku::GameEvent{updatedata.timestamp,
kku::SystemEvent{kku::SystemEvent::Type::None, kku::SystemEvent::Key{}}});
}*/
_timeline->update(updatedata.timestamp);

View File

@ -3,11 +3,13 @@
#include "gamecontext.h"
// Replace with interface by dependency injection
#include "graphics/animations/classicflyinganimationscenario.h"
#include "graphics/animations/classicdyinganimationscenario.h"
#include "graphics/animations/classicflyinganimationscenario.h"
//
auto classic::createBeatmap(const std::string& filepath, const std::shared_ptr<GameContext>& context) -> Beatmap
auto classic::createBeatmap(const std::string &filepath,
const std::shared_ptr<GameContext> &context)
-> Beatmap
{
(void)filepath;
@ -20,7 +22,8 @@ auto classic::createBeatmap(const std::string& filepath, const std::shared_ptr<G
kku::microsec bpm_iterator = starting_beat_offset;
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::vector<kku::microsec> input_intervals = {
note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset};
std::set<ClassicNote *, kku::NotePtrComparator> notes;
input_intervals.shrink_to_fit();
@ -59,15 +62,8 @@ auto classic::createBeatmap(const std::string& filepath, const std::shared_ptr<G
--counter;
ClassicArrowNote::Init init
{
id++,
context,
bpm_iterator,
input_intervals,
{element},
hold
};
ClassicArrowNote::Init init{
id++, context, bpm_iterator, input_intervals, {element}, hold};
notes.insert(new ClassicArrowNote(std::move(init)));
@ -80,4 +76,3 @@ auto classic::createBeatmap(const std::string& filepath, const std::shared_ptr<G
return {std::move(notes), note_input_offset * 8};
}

View File

@ -4,25 +4,29 @@
#include "graphics/animations/classicanimationscenario.h"
#include "graphics/classicgraphicsmanager.h"
GameContext::GameContext(const std::shared_ptr<HoldManager>& hold_manager,
const std::shared_ptr<ClassicGraphicsManager>& graphics_manager) :
_hold_manager(hold_manager),
_graphics_manager(graphics_manager)
{}
GameContext::GameContext(
const std::shared_ptr<HoldManager> &hold_manager,
const std::shared_ptr<ClassicGraphicsManager> &graphics_manager)
: _hold_manager(hold_manager), _graphics_manager(graphics_manager)
{
}
void GameContext::input(ClassicArrowNote *note, kku::GameEvent &&input) const
{
auto grade = ClassicArrowNote::Grade::BAD;
auto &elements = note->getElements();
bool input_valid = std::any_of(elements.begin(), elements.end(),
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);
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)
@ -34,11 +38,9 @@ void GameContext::input(ClassicArrowNote *note, kku::GameEvent&& input) const
return found_key;
});
bool all_pressed = std::all_of(elements.begin(), elements.end(),
[](const auto& element)
{
return element.pressed;
});
bool all_pressed =
std::all_of(elements.begin(), elements.end(),
[](const auto &element) { return element.pressed; });
if (all_pressed)
{
@ -51,19 +53,22 @@ void GameContext::input(ClassicArrowNote *note, kku::GameEvent&& input) const
{
note->setState(ClassicArrowNote::State::DYING);
for (auto &element : elements)
element.animations[note->getState()]->launch(element.sprite, input.timestamp, note->getPerfectOffset());
element.animations[note->getState()]->launch(
element.sprite, input.timestamp, note->getPerfectOffset());
}
std::cout << "User input: " << static_cast<int>(grade) << "\n";
}
void GameContext::update(ClassicArrowNote *note, const kku::microsec& music_offset) const
void GameContext::update(ClassicArrowNote *note,
const kku::microsec &music_offset) const
{
auto &elements = note->getElements();
switch (note->getState())
{
default: return;
default:
return;
break;
case ClassicArrowNote::State::INITIAL:
@ -72,11 +77,13 @@ void GameContext::update(ClassicArrowNote *note, const kku::microsec& music_offs
break;
case ClassicArrowNote::State::FLYING:
if (!note->isActive(music_offset) && music_offset > note->getPerfectOffset())
if (!note->isActive(music_offset) &&
music_offset > note->getPerfectOffset())
{
note->setState(ClassicArrowNote::State::DYING);
for (auto &element : elements)
element.animations[note->getState()]->launch(element.sprite, music_offset, note->getPerfectOffset());
element.animations[note->getState()]->launch(
element.sprite, music_offset, note->getPerfectOffset());
}
break;

View File

@ -1,8 +1,8 @@
#include "holdmanager.h"
#include "classicarrownote.h"
#include <iostream>
#include <algorithm>
#include <iostream>
void HoldManager::emplace(ClassicArrowNote *note)
{
@ -13,9 +13,7 @@ void HoldManager::checkRelease(kku::SystemEvent::Key::Code released_key)
{
bool key_match = std::any_of(_notes_on_hold.begin(), _notes_on_hold.end(),
[released_key](const auto &note)
{
return note->isPressedAs(released_key);
});
{ return note->isPressedAs(released_key); });
if (key_match)
_notes_on_hold.clear();

View File

@ -1,7 +1,9 @@
#include "classicdyinganimationscenario.h"
#include "graphics/classicnotegraphics.h"
void ClassicDyingAnimationScenario::launch(const std::shared_ptr<ClassicNoteGraphics> sprite, const kku::microsec& time_begin, const kku::microsec &time_end)
void ClassicDyingAnimationScenario::launch(
const std::shared_ptr<ClassicNoteGraphics> sprite,
const kku::microsec &time_begin, const kku::microsec &time_end)
{
_sprite = sprite;
_time_begin = time_begin;
@ -25,7 +27,8 @@ void ClassicDyingAnimationScenario::update(const kku::microsec& music_offset)
return;
}
auto new_alpha = (int(fill_color.alpha) - 15) < 0 ? 0 : int(fill_color.alpha) - 15;
auto new_alpha =
(int(fill_color.alpha) - 15) < 0 ? 0 : int(fill_color.alpha) - 15;
fill_color.alpha = new_alpha;
_sprite->setColor(fill_color);

View File

@ -1,7 +1,9 @@
#include "classicflyinganimationscenario.h"
#include "graphics/classicnotegraphics.h"
void ClassicFlyingAnimationScenario::launch(const std::shared_ptr<ClassicNoteGraphics> sprite, const kku::microsec& time_begin, const kku::microsec &time_end)
void ClassicFlyingAnimationScenario::launch(
const std::shared_ptr<ClassicNoteGraphics> sprite,
const kku::microsec &time_begin, const kku::microsec &time_end)
{
_sprite = sprite;
_time_begin = time_begin;
@ -12,7 +14,8 @@ void ClassicFlyingAnimationScenario::launch(const std::shared_ptr<ClassicNoteGra
_sprite->setTrailColor(_sprite->getColor());
}
float ClassicFlyingAnimationScenario::getPoint(const kku::Point& point, float perc) const
float ClassicFlyingAnimationScenario::getPoint(const kku::Point &point,
float perc) const
{
return point.x + ((point.y - point.x) * perc);
}
@ -28,7 +31,8 @@ void ClassicFlyingAnimationScenario::update(const kku::microsec& music_offset)
float xb = getPoint(kku::Point{crd.x + 90, crd.x}, i);
float yb = getPoint(kku::Point{crd.y - 150, crd.y}, i);
_sprite->setTrailPosition(kku::Point(getPoint( kku::Point{xa, xb}, i ), getPoint( kku::Point{ya, yb}, i )));
_sprite->setTrailPosition(kku::Point(getPoint(kku::Point{xa, xb}, i),
getPoint(kku::Point{ya, yb}, i)));
}
bool ClassicFlyingAnimationScenario::isDone() const

View File

@ -1,8 +1,10 @@
#include "classicgraphicsfactory.h"
ClassicGraphicsFactory::ClassicGraphicsFactory(const std::shared_ptr<kku::CoreFactory>& core_factory) :
_core_factory(core_factory)
{}
ClassicGraphicsFactory::ClassicGraphicsFactory(
const std::shared_ptr<kku::CoreFactory> &core_factory)
: _core_factory(core_factory)
{
}
auto ClassicGraphicsFactory::generate(Type type) const -> SpriteData
{
@ -41,14 +43,20 @@ auto ClassicGraphicsFactory::generate(Type type) const -> SpriteData
return SpriteData{shape, trail, color};
}
std::shared_ptr<ClassicNoteGraphics> ClassicGraphicsFactory::createSprite(Type type) const
std::shared_ptr<ClassicNoteGraphics>
ClassicGraphicsFactory::createSprite(Type type) const
{
const auto data = generate(type);
return std::make_shared<ClassicNoteGraphics>(ClassicNoteGraphics::Init{data.shape, data.trail, data.color});
return std::make_shared<ClassicNoteGraphics>(
ClassicNoteGraphics::Init{data.shape, data.trail, data.color});
}
std::shared_ptr<ClassicSelectionGraphics> ClassicGraphicsFactory::createSelection() const
std::shared_ptr<ClassicSelectionGraphics>
ClassicGraphicsFactory::createSelection() const
{
const auto shape = _core_factory->getRectangle();
return std::make_shared<ClassicSelectionGraphics>(ClassicSelectionGraphics::Init{shape, kku::Color{51, 153, 255, 120}});
return std::make_shared<ClassicSelectionGraphics>(
ClassicSelectionGraphics::Init{
shape, kku::Color{51, 153, 255, 120}
});
}

View File

@ -25,7 +25,7 @@ public:
virtual void update(const kku::microsec& offset, ClassicArrowNote* note) = 0;
// virtual void update(const kku::microsec& offset, ClassicSliderNote* note) = 0;
virtual void draw(const std::vector<ArrowElement>& elements) const = 0;
virtual void draw(const ClassicArrowNote * const note) const = 0;
// virtual void draw(ClassicSliderNote* note) const = 0;
protected:

View File

@ -1,9 +1,7 @@
#include "classicnotegraphics.h"
ClassicNoteGraphics::ClassicNoteGraphics(ClassicNoteGraphics::Init&& init) :
_reset_color(init.color),
_shape(init.shape),
_trail(init.trail)
ClassicNoteGraphics::ClassicNoteGraphics(ClassicNoteGraphics::Init &&init)
: _reset_color(init.color), _shape(init.shape), _trail(init.trail)
{
_shape->setColor(init.color);
_trail->setColor(init.color);

View File

@ -3,15 +3,14 @@
#include <iostream>
ClassicSceneGraphicsManager::ClassicSceneGraphicsManager(const std::shared_ptr<kku::Timeline<ClassicNote>>& timeline,
ClassicSceneGraphicsManager::ClassicSceneGraphicsManager(
const std::shared_ptr<kku::Timeline<ClassicNote>> &timeline,
const std::shared_ptr<ClassicGraphicsFactory> &factory,
const kku::microsec& visibility_offset) :
ClassicGraphicsManager(visibility_offset),
_sprite_container({Type::UP, Type::DOWN,
Type::LEFT, Type::RIGHT},
const kku::microsec &visibility_offset)
: ClassicGraphicsManager(visibility_offset),
_sprite_container({Type::UP, Type::DOWN, Type::LEFT, Type::RIGHT},
factory),
_factory(factory),
_timeline(timeline)
_factory(factory), _timeline(timeline)
{
_timeline->expire(_first);
_timeline->expire(_last);
@ -49,14 +48,18 @@ void ClassicSceneGraphicsManager::update(const kku::microsec &offset)
updateVisibleNotes(offset);
}
void ClassicSceneGraphicsManager::update(const kku::microsec& offset, ClassicArrowNote* note)
void ClassicSceneGraphicsManager::update(const kku::microsec &offset,
ClassicArrowNote *note)
{
bool hasGraphics = (note->getElements()[0].sprite != nullptr);
if (isVisiblyClose(note, offset) && !hasGraphics)
{
std::cout << note->getId() << ": set graphics!\n" << std::flush;
setGraphics(note->getElements(), kku::TimeRange{note->getPerfectOffset() - _visibility_offset, note->getPerfectOffset()});
setGraphics(
note->getElements(),
kku::TimeRange{note->getPerfectOffset() - _visibility_offset,
note->getPerfectOffset()});
}
else
{
@ -65,8 +68,9 @@ void ClassicSceneGraphicsManager::update(const kku::microsec& offset, ClassicArr
}
}
void ClassicSceneGraphicsManager::draw(const std::vector<ArrowElement>& elements) const
void ClassicSceneGraphicsManager::draw(const ClassicArrowNote *const note) const
{
const auto elements = note->getElements();
for (std::size_t i = 0; i < elements.size(); ++i)
{
const auto &sprite = elements[i].sprite;
@ -83,7 +87,8 @@ void ClassicSceneGraphicsManager::draw(const std::vector<ArrowElement>& elements
}
}
void ClassicSceneGraphicsManager::setGraphics(std::vector<ArrowElement>& elements, kku::TimeRange&& range)
void ClassicSceneGraphicsManager::setGraphics(
std::vector<ArrowElement> &elements, kku::TimeRange &&range)
{
for (auto &element : elements)
{
@ -92,15 +97,19 @@ void ClassicSceneGraphicsManager::setGraphics(std::vector<ArrowElement>& element
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::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);
element.animations[ClassicNote::State::FLYING]->launch(
element.sprite, range.begin, range.end);
}
}
void ClassicSceneGraphicsManager::removeGraphics(std::vector<ArrowElement>& elements)
void ClassicSceneGraphicsManager::removeGraphics(
std::vector<ArrowElement> &elements)
{
for (auto &element : elements)
{
@ -116,11 +125,12 @@ void ClassicSceneGraphicsManager::removeGraphics(std::vector<ArrowElement>& elem
bool ClassicSceneGraphicsManager::nothingToDraw() const noexcept
{
return _timeline->isExpired(_first)
|| _timeline->isExpired(_last);
return _timeline->isExpired(_first) || _timeline->isExpired(_last);
}
bool ClassicSceneGraphicsManager::isVisiblyClose(const ClassicNote * const note, const kku::microsec& music_offset) const noexcept
bool ClassicSceneGraphicsManager::isVisiblyClose(
const ClassicNote *const note,
const kku::microsec &music_offset) const noexcept
{
return (note->getPerfectOffset() - _visibility_offset) <= music_offset;
}
@ -133,7 +143,8 @@ void ClassicSceneGraphicsManager::fetchFirstNote(const kku::microsec& offset)
if (offset < (*_first)->getPerfectOffset())
{
Iterator note_iterator = _first;
while (note_iterator != _timeline->begin() && isVisiblyClose(*note_iterator, offset))
while (note_iterator != _timeline->begin() &&
isVisiblyClose(*note_iterator, offset))
{
--note_iterator;
}
@ -142,10 +153,10 @@ void ClassicSceneGraphicsManager::fetchFirstNote(const kku::microsec& offset)
auto note = *_first;
const auto state = note->getState();
if (state != ClassicNote::State::FLYING
&& state != ClassicNote::State::DYING
&& state != ClassicNote::State::INITIAL
&& offset <= note->getPerfectOffset())
if (state != ClassicNote::State::FLYING &&
state != ClassicNote::State::DYING &&
state != ClassicNote::State::INITIAL &&
offset <= note->getPerfectOffset())
{
note->setState(ClassicNote::State::INITIAL);
}
@ -170,17 +181,18 @@ void ClassicSceneGraphicsManager::fetchFirstNote(const kku::microsec& offset)
void ClassicSceneGraphicsManager::fetchLastNote(const kku::microsec &offset)
{
Iterator note_iterator = _timeline->getTopNote();
while (!_timeline->isExpired(note_iterator) && isVisiblyClose(*note_iterator, offset))
while (!_timeline->isExpired(note_iterator) &&
isVisiblyClose(*note_iterator, offset))
{
if (nothingToDraw())
_first = note_iterator;
auto note = *note_iterator;
const auto state = note->getState();
if (state != ClassicNote::State::FLYING
&& state != ClassicNote::State::DYING
&& state != ClassicNote::State::INITIAL
&& offset <= note->getPerfectOffset())
if (state != ClassicNote::State::FLYING &&
state != ClassicNote::State::DYING &&
state != ClassicNote::State::INITIAL &&
offset <= note->getPerfectOffset())
{
note->setState(ClassicNote::State::INITIAL);
}
@ -191,7 +203,8 @@ void ClassicSceneGraphicsManager::fetchLastNote(const kku::microsec& offset)
_last = note_iterator;
}
void ClassicSceneGraphicsManager::updateVisibleNotes(const kku::microsec& offset)
void ClassicSceneGraphicsManager::updateVisibleNotes(
const kku::microsec &offset)
{
for (auto it = _first; it != _last; ++it)
(*it)->update(offset);

View File

@ -23,7 +23,7 @@ public:
virtual void update(const kku::microsec& offset) override;
virtual void update(const kku::microsec& offset, ClassicArrowNote* note) override;
virtual void draw(const std::vector<ArrowElement>& elements) const override;
virtual void draw(const ClassicArrowNote * const note) const override;
void setGraphics(std::vector<ArrowElement>& elements, kku::TimeRange&& range);
void removeGraphics(std::vector<ArrowElement>& elements);

View File

@ -1,9 +1,9 @@
#include "classicselectiongraphics.h"
#include "classicnotegraphics.h"
ClassicSelectionGraphics::ClassicSelectionGraphics(ClassicSelectionGraphics::Init&& init) :
_fill_color(init.color),
_shape(init.shape)
ClassicSelectionGraphics::ClassicSelectionGraphics(
ClassicSelectionGraphics::Init &&init)
: _fill_color(init.color), _shape(init.shape)
{
_shape->setColor(init.color);
}
@ -19,7 +19,8 @@ void ClassicSelectionGraphics::display() const
_shape->display();
}
void ClassicSelectionGraphics::adjustTo(const std::shared_ptr<ClassicNoteGraphics>& sprite)
void ClassicSelectionGraphics::adjustTo(
const std::shared_ptr<ClassicNoteGraphics> &sprite)
{
_shape->setRect(sprite->getRectangle()->getRect());
}

View File

@ -3,15 +3,16 @@
#include <iostream>
ClassicTimelineGraphicsManager::ClassicTimelineGraphicsManager(const std::shared_ptr<kku::Timeline<ClassicNote>>& timeline,
ClassicTimelineGraphicsManager::ClassicTimelineGraphicsManager(
const std::shared_ptr<kku::Timeline<ClassicNote>> &timeline,
const std::shared_ptr<ClassicGraphicsFactory> &factory,
const kku::microsec& visibility_offset) :
ClassicGraphicsManager(visibility_offset),
_sprite_container({Type::UP, Type::DOWN,
Type::LEFT, Type::RIGHT},
const kku::microsec &visibility_offset)
: ClassicGraphicsManager(visibility_offset),
_sprite_container({Type::UP, Type::DOWN, Type::LEFT, Type::RIGHT},
factory),
_factory(factory),
_timeline(timeline)
_factory(factory), _timeline(timeline),
_back_visibility_offset(static_cast<double>(visibility_offset) / 4.f),
_last_offset(0)
{
_timeline->expire(_first);
_timeline->expire(_last);
@ -19,37 +20,55 @@ ClassicTimelineGraphicsManager::ClassicTimelineGraphicsManager(const std::shared
void ClassicTimelineGraphicsManager::input(kku::GameEvent &&input)
{
if (nothingToDraw())
return;
for (auto it = _first; it != _last; ++it)
switch (input.event.type)
{
(*it)->input(std::move(input));
default:
break;
case kku::SystemEvent::Type::KeyPress:
{
const auto key_data = std::get<kku::SystemEvent::Key>(input.event.data);
if (key_data.view == kku::SystemEvent::Key::Code::Add)
{
_visibility_offset += 200000;
_back_visibility_offset =
static_cast<double>(_visibility_offset) / 4.f;
}
else if (key_data.view == kku::SystemEvent::Key::Code::Subtract)
{
_visibility_offset -= 200000;
_back_visibility_offset =
static_cast<double>(_visibility_offset) / 4.f;
}
break;
}
}
}
void ClassicTimelineGraphicsManager::display() const
{
if (nothingToDraw())
return;
// if (nothingToDraw())
// return;
std::cout << "displaying on tl: ";
for (auto it = _first; it != _last; ++it)
{
const auto note = *it;
if (note->getState() != ClassicNote::State::DEAD)
note->draw(shared_from_this());
std::cout << (*it)->getId() << " ";
(*it)->draw(shared_from_this());
}
std::cout << "\n" << std::flush;
}
void ClassicTimelineGraphicsManager::update(const kku::microsec &offset)
{
_last_offset = offset;
fetchLastNote(offset);
fetchFirstNote(offset);
updateVisibleNotes(offset);
}
void ClassicTimelineGraphicsManager::update(const kku::microsec& offset, ClassicArrowNote* note)
void ClassicTimelineGraphicsManager::update(const kku::microsec &offset,
ClassicArrowNote *note)
{
bool hasGraphics = (note->getElements()[0].sprite != nullptr);
@ -63,103 +82,72 @@ void ClassicTimelineGraphicsManager::update(const kku::microsec& offset, Classic
}
}
void ClassicTimelineGraphicsManager::draw(const std::vector<ArrowElement>& elements) const
void ClassicTimelineGraphicsManager::draw(
const ClassicArrowNote *const note) const
{
const double d_visibility_offset =
static_cast<double>(_last_offset + _visibility_offset);
const double d_back_visibility_offset =
static_cast<double>(_last_offset - _back_visibility_offset);
const double span = d_visibility_offset - d_back_visibility_offset;
const double note_span =
static_cast<double>(note->getPerfectOffset()) - d_visibility_offset;
const double percent = note_span / (span / 100.f);
const auto elements = note->getElements();
for (std::size_t i = 0; i < elements.size(); ++i)
{
const auto& sprite = elements[i].sprite;
auto timeline_sprite = _factory->createSprite(elements[i].type);
timeline_sprite->setPosition(
kku::Point{static_cast<int>(850 + 1280.f / 100.f * percent), 700});
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();
timeline_sprite->display();
}
}
bool ClassicTimelineGraphicsManager::nothingToDraw() const noexcept
{
return _timeline->isExpired(_first)
|| _timeline->isExpired(_last);
return _timeline->isExpired(_first) || _timeline->isExpired(_last);
}
bool ClassicTimelineGraphicsManager::isVisiblyClose(const ClassicNote * const note, const kku::microsec& music_offset) const noexcept
bool ClassicTimelineGraphicsManager::isVisiblyClose(
const ClassicNote *const note,
const kku::microsec &music_offset) const noexcept
{
return (note->getPerfectOffset() - _visibility_offset) <= music_offset;
const auto &perfect_offset = note->getPerfectOffset();
return ((perfect_offset - _visibility_offset) <= music_offset) ||
((perfect_offset + (_visibility_offset / 4.)) >= music_offset);
}
void ClassicTimelineGraphicsManager::fetchFirstNote(const kku::microsec &offset)
{
if (nothingToDraw())
return;
// if (nothingToDraw())
// return;
if (offset < (*_first)->getPerfectOffset())
{
Iterator note_iterator = _first;
while (note_iterator != _timeline->begin() && isVisiblyClose(*note_iterator, offset))
while (note_iterator != _timeline->begin() &&
isVisiblyClose(*note_iterator, offset))
{
--note_iterator;
}
_first = note_iterator;
auto note = *_first;
const auto state = note->getState();
if (state != ClassicNote::State::FLYING
&& state != ClassicNote::State::DYING
&& state != ClassicNote::State::INITIAL
&& offset <= note->getPerfectOffset())
{
note->setState(ClassicNote::State::INITIAL);
}
}
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 ClassicTimelineGraphicsManager::fetchLastNote(const kku::microsec &offset)
{
Iterator note_iterator = _timeline->getTopNote();
while (!_timeline->isExpired(note_iterator) && isVisiblyClose(*note_iterator, offset))
while (!_timeline->isExpired(note_iterator) &&
isVisiblyClose(*note_iterator, offset))
{
if (nothingToDraw())
_first = note_iterator;
auto note = *note_iterator;
const auto state = note->getState();
if (state != ClassicNote::State::FLYING
&& state != ClassicNote::State::DYING
&& state != ClassicNote::State::INITIAL
&& offset <= note->getPerfectOffset())
{
note->setState(ClassicNote::State::INITIAL);
}
++note_iterator;
}
_last = note_iterator;
}
void ClassicTimelineGraphicsManager::updateVisibleNotes(const kku::microsec& offset)
{
for (auto it = _first; it != _last; ++it)
(*it)->update(offset);
}

View File

@ -23,7 +23,7 @@ public:
virtual void update(const kku::microsec& offset) override;
virtual void update(const kku::microsec& offset, ClassicArrowNote* note) override;
virtual void draw(const std::vector<ArrowElement>& elements) const override;
virtual void draw(const ClassicArrowNote * const note) const override;
protected:
kku::SpriteContainer<Type, ClassicGraphicsFactory, ClassicNoteGraphics> _sprite_container;
@ -35,10 +35,11 @@ protected:
Iterator _last;
const std::shared_ptr<kku::Timeline<ClassicNote>> _timeline;
kku::microsec _back_visibility_offset;
kku::microsec _last_offset;
inline bool nothingToDraw() const noexcept;
inline bool isVisiblyClose(const ClassicNote * const note, const kku::microsec& music_offset) const noexcept;
void fetchFirstNote(const kku::microsec& offset);
void fetchLastNote(const kku::microsec& offset);
void updateVisibleNotes(const kku::microsec& offset);
};

View File

@ -1,23 +1,21 @@
#include "tools/beatutils.h"
#include <numeric>
#include <iostream>
#include <numeric>
auto beat_utils::calculateBeatRateInfo(const std::vector<kku::microsec>& approximate_deltas) -> BeatInfo
auto beat_utils::calculateBeatRateInfo(
const std::vector<kku::microsec> &approximate_deltas) -> BeatInfo
{
if (approximate_deltas.empty())
return {};
const long double sum = std::accumulate(approximate_deltas.begin(), approximate_deltas.end(), 0);
const long double sum = std::accumulate(approximate_deltas.begin(),
approximate_deltas.end(), 0);
const long double amount = approximate_deltas.size();
long double average = sum / amount;
const int bpm = static_cast<int>(60000000. / average);
return BeatInfo
{
bpm,
static_cast<kku::microsec>(1. / static_cast<long double>(bpm) * 60000000.)
};
return BeatInfo{bpm, static_cast<kku::microsec>(
1. / static_cast<long double>(bpm) * 60000000.)};
}

View File

@ -1,8 +1,8 @@
#include "tools/bpmcalculator.h"
#include <cmath>
#include <numeric>
#include <iostream>
#include <numeric>
BPMCalculator::BPMCalculator()
{