forked from NaiJi/project-kyoku
Implement inheritance tree for Note
This commit is contained in:
parent
8d931f7a1e
commit
00273ab2fd
|
@ -19,7 +19,7 @@ set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||||
file(GLOB_RECURSE SOURCES "src/main.cpp" "src/application/*.cpp" "src/application/*.h")
|
file(GLOB_RECURSE SOURCES "src/main.cpp" "src/application/*.cpp" "src/application/*.h")
|
||||||
add_executable(project-kyoku ${SOURCES})
|
add_executable(project-kyoku ${SOURCES})
|
||||||
|
|
||||||
option(SFML_BUILT "SFML_BUILT" ON)
|
option(SFML_BUILT "SFML_BUILT" OFF)
|
||||||
|
|
||||||
if(SFML_BUILT)
|
if(SFML_BUILT)
|
||||||
set(SFML_LIB_DIR
|
set(SFML_LIB_DIR
|
||||||
|
@ -30,25 +30,24 @@ if(SFML_BUILT)
|
||||||
set(SFML_INCL_DIR ${CMAKE_SOURCE_DIR}/SFML-2.5.1/include)
|
set(SFML_INCL_DIR ${CMAKE_SOURCE_DIR}/SFML-2.5.1/include)
|
||||||
target_link_libraries(project-kyoku ${SFML_LIB_DIR})
|
target_link_libraries(project-kyoku ${SFML_LIB_DIR})
|
||||||
else()
|
else()
|
||||||
find_package(SFML)
|
find_package(SFML REQUIRED graphics window system)
|
||||||
|
include_directories(${SFML_INCL_DIR} ${CMAKE_SOURCE_DIR}/include)
|
||||||
target_link_libraries(project-kyoku sfml-system sfml-audio sfml-graphics sfml-network)
|
target_link_libraries(project-kyoku sfml-system sfml-audio sfml-graphics sfml-network)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${SFML_INCL_DIR} ${CMAKE_SOURCE_DIR}/include)
|
include_directories(${SFML_INCL_DIR} ${CMAKE_SOURCE_DIR}/include)
|
||||||
|
|
||||||
SET(CMAKE_INSTALL_PREFIX /)
|
SET(CMAKE_INSTALL_PREFIX /)
|
||||||
|
# When new game modes appear, aggregate them into a ONE subdirectory
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modes/classicmode/CMakeLists.txt")
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modes/classicmode/CMakeLists.txt")
|
||||||
add_subdirectory(modes/classicmode)
|
add_subdirectory(modes/classicmode)
|
||||||
target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/modes/classicmode/shared)
|
|
||||||
target_link_libraries(project-kyoku classicmode)
|
target_link_libraries(project-kyoku classicmode)
|
||||||
endif()
|
endif()
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tools/CMakeLists.txt")
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tools/CMakeLists.txt")
|
||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared)
|
|
||||||
target_link_libraries(project-kyoku tools)
|
target_link_libraries(project-kyoku tools)
|
||||||
endif()
|
endif()
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/core/CMakeLists.txt")
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/core/CMakeLists.txt")
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/core/shared)
|
|
||||||
target_link_libraries(project-kyoku core)
|
target_link_libraries(project-kyoku core)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -4,7 +4,6 @@ project(core)
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE HEADERS "shared/*.h")
|
file(GLOB_RECURSE HEADERS "shared/*.h")
|
||||||
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
||||||
|
@ -12,3 +11,5 @@ file(GLOB_RECURSE SOURCES "src/*.cpp")
|
||||||
add_library(core STATIC ${SOURCES} ${HEADERS})
|
add_library(core STATIC ${SOURCES} ${HEADERS})
|
||||||
target_include_directories(core PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared)
|
target_include_directories(core PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared)
|
||||||
target_link_libraries(core tools)
|
target_link_libraries(core tools)
|
||||||
|
|
||||||
|
target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/core/shared)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#ifndef INPUTTYPE_H
|
#pragma once
|
||||||
#define INPUTTYPE_H
|
|
||||||
|
|
||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
#include "tools/mathutils.h"
|
#include "tools/mathutils.h"
|
||||||
|
@ -9,5 +8,3 @@ struct PlayerInput
|
||||||
microsec timestamp;
|
microsec timestamp;
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INPUTTYPE_H
|
|
||||||
|
|
|
@ -3,13 +3,17 @@ cmake_minimum_required(VERSION 2.8.8)
|
||||||
project(classicmode)
|
project(classicmode)
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/shared)
|
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||||
|
|
||||||
file(GLOB_RECURSE HEADERS "shared/*.h")
|
file(GLOB_RECURSE HEADERS "shared/*.h" )
|
||||||
file(GLOB_RECURSE SOURCES "editor/*.h" "editor/*.cpp" "game/*.h" "game/*.cpp" "./classicfactory.cpp")
|
file(GLOB_RECURSE SOURCES "editor/*.h" "editor/*.cpp" "game/*.h" "game/*.cpp" "./classicfactory.cpp")
|
||||||
|
|
||||||
add_library(classicmode STATIC ${SOURCES} ${HEADERS})
|
add_library(classicmode STATIC ${SOURCES} ${HEADERS})
|
||||||
target_include_directories(classicmode PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
target_include_directories(classicmode PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
target_include_directories(classicmode PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/game)
|
||||||
target_include_directories(classicmode PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared)
|
target_include_directories(classicmode PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared)
|
||||||
target_include_directories(classicmode PRIVATE ${CMAKE_SOURCE_DIR}/core/shared)
|
target_include_directories(classicmode PRIVATE ${CMAKE_SOURCE_DIR}/core/shared)
|
||||||
target_link_libraries(classicmode tools core)
|
target_link_libraries(classicmode tools core)
|
||||||
|
|
||||||
|
target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/modes/classicmode/shared)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#ifndef CLASSICACTIONS_H
|
#pragma once
|
||||||
#define CLASSICACTIONS_H
|
|
||||||
|
|
||||||
enum class Action
|
enum class Action
|
||||||
{
|
{
|
||||||
|
@ -28,5 +27,3 @@ enum class Type
|
||||||
SLIDER_RIGHT,
|
SLIDER_RIGHT,
|
||||||
SLIDER_LEFT
|
SLIDER_LEFT
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLASSICACTIONS_H
|
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
#include "classicarrownote.h"
|
||||||
|
#include "classicgraphicsmanager.h"
|
||||||
|
|
||||||
|
// Replace with interface by dependency injection
|
||||||
|
#include "classicflyinganimationscenario.h"
|
||||||
|
#include "classicdyinganimationscenario.h"
|
||||||
|
//
|
||||||
|
|
||||||
|
ClassicArrowNote::ClassicArrowNote(ArrowNoteInitializer&& init) :
|
||||||
|
ClassicNote(std::move(init.initializer)),
|
||||||
|
_is_hold(init.hold)
|
||||||
|
{
|
||||||
|
_elements.resize(init.elements.size());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < _elements.size(); ++i)
|
||||||
|
{
|
||||||
|
_elements[i].keys = init.elements[i].element.keys;
|
||||||
|
_elements[i].coordinates = init.elements[i].element.coordinates;
|
||||||
|
_elements[i].type = init.elements[i].type;
|
||||||
|
|
||||||
|
// Animations will be injected into note.
|
||||||
|
_elements[i].animations[State::NONE] = nullptr;
|
||||||
|
_elements[i].animations[State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
||||||
|
_elements[i].animations[State::ACTIVE] = _elements[i].animations[State::FLYING];
|
||||||
|
_elements[i].animations[State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
||||||
|
_elements[i].animations[State::DEAD] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicArrowNote::putToGame(const microsec &music_offset)
|
||||||
|
{
|
||||||
|
_state = State::FLYING;
|
||||||
|
|
||||||
|
for (auto& element : _elements)
|
||||||
|
{
|
||||||
|
element.sprite = _context->graphics_manager->getSprite(element.type);
|
||||||
|
element.sprite->setCoordinates(element.coordinates, 0., 9.);
|
||||||
|
element.animations[_state]->launch(element.sprite, music_offset, offset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicArrowNote::input(PlayerInput&& inputdata)
|
||||||
|
{
|
||||||
|
auto grade = ClassicNote::Grade::BAD;
|
||||||
|
|
||||||
|
bool input_valid = std::any_of(_elements.begin(), _elements.end(),
|
||||||
|
[inputdata=inputdata](auto& element)
|
||||||
|
{
|
||||||
|
if (element.pressed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto key_iterator = std::find(element.keys.begin(), element.keys.end(), inputdata.event.key.code);
|
||||||
|
bool found_key = key_iterator != element.keys.end();
|
||||||
|
if (found_key)
|
||||||
|
{
|
||||||
|
element.pressed = true;
|
||||||
|
element.pressed_as = inputdata.event.key.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_key;
|
||||||
|
});
|
||||||
|
|
||||||
|
bool all_pressed = allElementsPressed();
|
||||||
|
|
||||||
|
if (all_pressed)
|
||||||
|
grade = _evaluator.calculatePrecision(inputdata.timestamp);
|
||||||
|
|
||||||
|
if (all_pressed || !input_valid)
|
||||||
|
{
|
||||||
|
_state = State::DYING;
|
||||||
|
for (auto& element : _elements)
|
||||||
|
element.animations[_state]->launch(element.sprite, inputdata.timestamp, offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicArrowNote::draw() const
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < _elements.size(); ++i)
|
||||||
|
{
|
||||||
|
if (i >= 1)
|
||||||
|
_context->graphics_manager->drawLine(_elements[i-1].sprite->trailCoordinates(), _elements[i].sprite->trailCoordinates());
|
||||||
|
|
||||||
|
_context->graphics_manager->draw(_elements[i].sprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassicArrowNote::update(const microsec& music_offset)
|
||||||
|
{
|
||||||
|
switch (_state)
|
||||||
|
{
|
||||||
|
default: return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::FLYING:
|
||||||
|
if (_evaluator.isActive(music_offset))
|
||||||
|
_state = State::ACTIVE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::DYING:
|
||||||
|
if (_elements[0].animations[_state]->isDone())
|
||||||
|
_state = State::DEAD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::ACTIVE:
|
||||||
|
if (!_evaluator.isActive(music_offset))
|
||||||
|
{
|
||||||
|
_state = State::DYING;
|
||||||
|
for (auto& element : _elements)
|
||||||
|
element.animations[_state]->launch(element.sprite, music_offset, offset());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& element : _elements)
|
||||||
|
if (element.animations[_state])
|
||||||
|
element.animations[_state]->update(music_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicArrowNote::allElementsPressed() const
|
||||||
|
{
|
||||||
|
return std::all_of(_elements.begin(), _elements.end(),
|
||||||
|
[](const auto& element)
|
||||||
|
{
|
||||||
|
return element.pressed;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassicArrowNote::isPressedAs(sf::Keyboard::Key key) const
|
||||||
|
{
|
||||||
|
return std::any_of(_elements.begin(), _elements.end(),
|
||||||
|
[key=key](const auto& element)
|
||||||
|
{
|
||||||
|
return key == element.pressed_as;
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "classicnote.h"
|
||||||
|
#include "initializers/arrownoteinitializer.h"
|
||||||
|
|
||||||
|
class ClassicArrowNote : public ClassicNote
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ClassicArrowNote(ArrowNoteInitializer&& init);
|
||||||
|
virtual ~ClassicArrowNote() = default;
|
||||||
|
|
||||||
|
virtual void putToGame(const microsec& music_offset) override;
|
||||||
|
virtual void update(const microsec &music_offset) override;
|
||||||
|
virtual void input(PlayerInput&& inputdata) override;
|
||||||
|
virtual void draw() const override;
|
||||||
|
|
||||||
|
bool allElementsPressed() const;
|
||||||
|
bool isPressedAs(sf::Keyboard::Key key) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct ArrowElement
|
||||||
|
{
|
||||||
|
std::shared_ptr<ClassicSprite> sprite;
|
||||||
|
std::array<std::shared_ptr<ClassicAnimationScenario>, 5> animations;
|
||||||
|
sf::Keyboard::Key pressed_as = sf::Keyboard::Unknown;
|
||||||
|
|
||||||
|
Coordinates coordinates;
|
||||||
|
std::vector<Coordinates> falling_curve_interpolation;
|
||||||
|
std::array<sf::Keyboard::Key, 2> keys;
|
||||||
|
Type type = Type::NONE;
|
||||||
|
bool pressed = false;
|
||||||
|
|
||||||
|
// Each note may consist of several buttons.
|
||||||
|
// For example, ↑ → or ↓ → ←
|
||||||
|
// Note Element represents this idea.
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ArrowElement> _elements;
|
||||||
|
bool _is_hold;
|
||||||
|
};
|
|
@ -100,18 +100,18 @@ void ClassicGame::input(PlayerInput&& inputdata)
|
||||||
note->input(std::move(inputdata));
|
note->input(std::move(inputdata));
|
||||||
_slap.play();
|
_slap.play();
|
||||||
|
|
||||||
if (note->isHold() && note->allElementsPressed()) // also check for Type
|
/*if (note->isHold() && note->allElementsPressed()) // also check for Type
|
||||||
{
|
{
|
||||||
_notes_on_hold.emplace_back(note);
|
_notes_on_hold.emplace_back(note);
|
||||||
std::cout << "HOLD initited by " << inputdata.event.key.code << '\n';
|
std::cout << "HOLD initited by " << inputdata.event.key.code << '\n';
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sf::Event::KeyReleased:
|
case sf::Event::KeyReleased:
|
||||||
{
|
{
|
||||||
bool key_match = std::any_of(_notes_on_hold.begin(), _notes_on_hold.end(),
|
/*bool key_match = std::any_of(_notes_on_hold.begin(), _notes_on_hold.end(),
|
||||||
[key=inputdata.event.key.code](const auto& note)
|
[key=inputdata.event.key.code](const auto& note)
|
||||||
{
|
{
|
||||||
return note->isPressedAs(key);
|
return note->isPressedAs(key);
|
||||||
|
@ -121,7 +121,7 @@ void ClassicGame::input(PlayerInput&& inputdata)
|
||||||
{
|
{
|
||||||
_notes_on_hold.clear();
|
_notes_on_hold.clear();
|
||||||
std::cout << "HOLD released by " << inputdata.event.key.code << '\n';
|
std::cout << "HOLD released by " << inputdata.event.key.code << '\n';
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,6 @@ private:
|
||||||
std::map<Type, Action> _buttons_to_pressed_actions;
|
std::map<Type, Action> _buttons_to_pressed_actions;
|
||||||
std::map<Type, Action> _buttons_to_released_actions;
|
std::map<Type, Action> _buttons_to_released_actions;
|
||||||
|
|
||||||
std::vector<ClassicNote*> _notes_on_hold;
|
|
||||||
|
|
||||||
std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
||||||
Timeline<ClassicNote> _timeline;
|
Timeline<ClassicNote> _timeline;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "classicmapcreator.h"
|
#include "classicmapcreator.h"
|
||||||
#include "classicnote.h"
|
#include "classicarrownote.h"
|
||||||
|
|
||||||
// Replace with interface by dependency injection
|
// Replace with interface by dependency injection
|
||||||
#include "classicflyinganimationscenario.h"
|
#include "classicflyinganimationscenario.h"
|
||||||
|
@ -33,23 +33,26 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const
|
||||||
|
|
||||||
int counter = 3;
|
int counter = 3;
|
||||||
|
|
||||||
|
const auto context = std::make_shared<Context>(Context{_graphics_manager});
|
||||||
|
|
||||||
while (bpm_iterator < bpm_end)
|
while (bpm_iterator < bpm_end)
|
||||||
{
|
{
|
||||||
ClassicNote::ClassicNoteInitializer init;
|
ArrowNoteInitializer init;
|
||||||
ClassicNote::ClassicNoteInitializer::Element element;
|
ArrowElementInitializer element;
|
||||||
init.intervals = input_intervals;
|
init.initializer.intervals = input_intervals;
|
||||||
init.perfect_offset = bpm_iterator;
|
init.initializer.perfect_offset = bpm_iterator;
|
||||||
init.hold = false;
|
init.hold = false;
|
||||||
|
init.initializer.context = context;
|
||||||
|
|
||||||
element.coordinates = {x, 390.};
|
element.element.coordinates = {x, 390.};
|
||||||
element.falling_curve_interpolation = {};
|
element.element.falling_curve_interpolation = {};
|
||||||
element.keys = {sf::Keyboard::W, sf::Keyboard::Up};
|
element.element.keys = {sf::Keyboard::W, sf::Keyboard::Up};
|
||||||
element.type = Type::UP;
|
element.type = Type::UP;
|
||||||
|
|
||||||
if (counter == 0)
|
if (counter == 0)
|
||||||
{
|
{
|
||||||
init.hold = true;
|
init.hold = true;
|
||||||
element.keys = {sf::Keyboard::D, sf::Keyboard::Right};
|
element.element.keys = {sf::Keyboard::D, sf::Keyboard::Right};
|
||||||
element.type = Type::RIGHT;
|
element.type = Type::RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +60,7 @@ Beatmap ClassicMapCreator::createBeatmap(const std::string& filepath) const
|
||||||
|
|
||||||
init.elements = {element};
|
init.elements = {element};
|
||||||
|
|
||||||
notes.emplace_back(new ClassicNote(std::move(init), _graphics_manager));
|
notes.emplace_back(new ClassicArrowNote(std::move(init)));
|
||||||
|
|
||||||
bpm_iterator += tempo_interval;
|
bpm_iterator += tempo_interval;
|
||||||
x += 70;
|
x += 70;
|
||||||
|
|
|
@ -7,47 +7,18 @@
|
||||||
#include "classicdyinganimationscenario.h"
|
#include "classicdyinganimationscenario.h"
|
||||||
//
|
//
|
||||||
|
|
||||||
ClassicNote::ClassicNote(ClassicNoteInitializer &&init, const std::shared_ptr<ClassicGraphicsManager>& manager) :
|
ClassicNote::ClassicNote(NoteInitializer &&init) :
|
||||||
Note(init.perfect_offset),
|
Note(init.perfect_offset),
|
||||||
_evaluator(init.intervals, _perfect_offset),
|
_evaluator(init.intervals, _perfect_offset),
|
||||||
_graphics_manager(manager),
|
_state(State::NONE),
|
||||||
_state(State::NONE)
|
_context(init.context)
|
||||||
{
|
{}
|
||||||
_elements.resize(init.elements.size());
|
|
||||||
_isHold = init.hold;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < _elements.size(); ++i)
|
|
||||||
{
|
|
||||||
_elements[i].keys = init.elements[i].keys;
|
|
||||||
_elements[i].coordinates = init.elements[i].coordinates;
|
|
||||||
_elements[i].type = init.elements[i].type;
|
|
||||||
|
|
||||||
// Animations will be injected into note.
|
|
||||||
_elements[i].animations[State::NONE] = nullptr;
|
|
||||||
_elements[i].animations[State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
|
||||||
_elements[i].animations[State::ACTIVE] = _elements[i].animations[State::FLYING];
|
|
||||||
_elements[i].animations[State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
|
||||||
_elements[i].animations[State::DEAD] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::isActive() const
|
bool ClassicNote::isActive() const
|
||||||
{
|
{
|
||||||
return _state == State::ACTIVE;
|
return _state == State::ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicNote::putToGame(const microsec &music_offset)
|
|
||||||
{
|
|
||||||
_state = State::FLYING;
|
|
||||||
|
|
||||||
for (auto& element : _elements)
|
|
||||||
{
|
|
||||||
element.sprite = _graphics_manager->getSprite(element.type);
|
|
||||||
element.sprite->setCoordinates(element.coordinates, 0., 9.);
|
|
||||||
element.animations[_state]->launch(element.sprite, music_offset, offset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::isInGame() const
|
bool ClassicNote::isInGame() const
|
||||||
{
|
{
|
||||||
return _state == State::FLYING
|
return _state == State::FLYING
|
||||||
|
@ -59,104 +30,3 @@ bool ClassicNote::shouldRemove() const
|
||||||
{
|
{
|
||||||
return _state == State::DEAD;
|
return _state == State::DEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicNote::update(const microsec& music_offset)
|
|
||||||
{
|
|
||||||
switch (_state)
|
|
||||||
{
|
|
||||||
default: return;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::FLYING:
|
|
||||||
if (_evaluator.isActive(music_offset))
|
|
||||||
_state = State::ACTIVE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::DYING:
|
|
||||||
if (_elements[0].animations[_state]->isDone())
|
|
||||||
_state = State::DEAD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::ACTIVE:
|
|
||||||
if (!_evaluator.isActive(music_offset))
|
|
||||||
{
|
|
||||||
_state = State::DYING;
|
|
||||||
for (auto& element : _elements)
|
|
||||||
element.animations[_state]->launch(element.sprite, music_offset, offset());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& element : _elements)
|
|
||||||
if (element.animations[_state])
|
|
||||||
element.animations[_state]->update(music_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::input(PlayerInput&& inputdata)
|
|
||||||
{
|
|
||||||
auto grade = ClassicNote::Grade::BAD;
|
|
||||||
|
|
||||||
bool input_valid = std::any_of(_elements.begin(), _elements.end(),
|
|
||||||
[inputdata=inputdata](auto& element)
|
|
||||||
{
|
|
||||||
if (element.pressed)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto key_iterator = std::find(element.keys.begin(), element.keys.end(), inputdata.event.key.code);
|
|
||||||
bool found_key = key_iterator != element.keys.end();
|
|
||||||
if (found_key)
|
|
||||||
{
|
|
||||||
element.pressed = true;
|
|
||||||
element.pressed_as = inputdata.event.key.code;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found_key;
|
|
||||||
});
|
|
||||||
|
|
||||||
bool all_pressed = allElementsPressed();
|
|
||||||
|
|
||||||
if (all_pressed)
|
|
||||||
grade = _evaluator.calculatePrecision(inputdata.timestamp);
|
|
||||||
|
|
||||||
if (all_pressed || !input_valid)
|
|
||||||
{
|
|
||||||
_state = State::DYING;
|
|
||||||
for (auto& element : _elements)
|
|
||||||
element.animations[_state]->launch(element.sprite, inputdata.timestamp, offset());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "User input: " << static_cast<int>(grade) << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassicNote::draw() const
|
|
||||||
{
|
|
||||||
for (std::size_t i = 0; i < _elements.size(); ++i)
|
|
||||||
{
|
|
||||||
if (i >= 1)
|
|
||||||
_graphics_manager->drawLine(_elements[i-1].sprite->trailCoordinates(), _elements[i].sprite->trailCoordinates());
|
|
||||||
_graphics_manager->draw(_elements[i].sprite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::isHold() const
|
|
||||||
{
|
|
||||||
return _isHold;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::allElementsPressed() const
|
|
||||||
{
|
|
||||||
return std::all_of(_elements.begin(), _elements.end(),
|
|
||||||
[](const auto& element)
|
|
||||||
{
|
|
||||||
return element.pressed;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClassicNote::isPressedAs(sf::Keyboard::Key key) const
|
|
||||||
{
|
|
||||||
return std::any_of(_elements.begin(), _elements.end(),
|
|
||||||
[key=key](const auto& element)
|
|
||||||
{
|
|
||||||
return key == element.pressed_as;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
#include "core/note.h"
|
#include "core/note.h"
|
||||||
#include "core/precisionevaluator.h"
|
#include "core/precisionevaluator.h"
|
||||||
#include "classicactions.h"
|
#include "initializers/noteinitializer.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
class ClassicSprite;
|
class ClassicSprite;
|
||||||
class ClassicGraphicsManager;
|
|
||||||
class ClassicAnimationScenario;
|
class ClassicAnimationScenario;
|
||||||
|
|
||||||
class ClassicNote : public Note
|
class ClassicNote : public Note
|
||||||
|
@ -32,58 +29,21 @@ public:
|
||||||
DEAD
|
DEAD
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClassicNoteInitializer
|
explicit ClassicNote(NoteInitializer&& init);
|
||||||
{
|
|
||||||
std::vector<microsec> intervals;
|
|
||||||
microsec perfect_offset;
|
|
||||||
bool hold;
|
|
||||||
|
|
||||||
struct Element
|
|
||||||
{
|
|
||||||
Type type;
|
|
||||||
Coordinates coordinates;
|
|
||||||
std::vector<Coordinates> falling_curve_interpolation;
|
|
||||||
std::array<sf::Keyboard::Key, 2> keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Element> elements;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit ClassicNote(ClassicNoteInitializer&& init, const std::shared_ptr<ClassicGraphicsManager>& manager);
|
|
||||||
virtual ~ClassicNote() = default;
|
virtual ~ClassicNote() = default;
|
||||||
|
|
||||||
virtual bool isActive() const override;
|
virtual bool isActive() const override final;
|
||||||
virtual void update(const microsec &music_offset) override;
|
virtual bool isInGame() const override final;
|
||||||
virtual void input(PlayerInput&& inputdata) override;
|
virtual bool shouldRemove() const override final;
|
||||||
virtual void putToGame(const microsec &music_offset) override;
|
|
||||||
virtual bool isInGame() const override;
|
|
||||||
virtual bool shouldRemove() const override;
|
|
||||||
virtual void draw() const override;
|
|
||||||
|
|
||||||
bool isHold() const;
|
virtual void putToGame(const microsec &music_offset) override = 0;
|
||||||
bool allElementsPressed() const;
|
virtual void update(const microsec &music_offset) override = 0;
|
||||||
bool isPressedAs(sf::Keyboard::Key key) const;
|
virtual void input(PlayerInput&& inputdata) override = 0;
|
||||||
|
virtual void draw() const override = 0;
|
||||||
private:
|
|
||||||
|
|
||||||
struct NoteElement
|
|
||||||
{
|
|
||||||
std::shared_ptr<ClassicSprite> sprite;
|
|
||||||
std::array<std::shared_ptr<ClassicAnimationScenario>, 5> animations;
|
|
||||||
|
|
||||||
std::array<sf::Keyboard::Key, 2> keys;
|
|
||||||
Coordinates coordinates; // Each note may consist of several buttons.
|
|
||||||
Type type; // For example, ↑ → or ↓ → ←
|
|
||||||
// Note Element represents this idea.
|
|
||||||
bool pressed = false; // Each ending button in such sequence
|
|
||||||
sf::Keyboard::Key pressed_as; // is an element.
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<NoteElement> _elements;
|
|
||||||
|
|
||||||
|
protected:
|
||||||
const PrecisionEvaluator<Grade> _evaluator;
|
const PrecisionEvaluator<Grade> _evaluator;
|
||||||
const std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
|
||||||
|
|
||||||
State _state;
|
State _state;
|
||||||
bool _isHold;
|
std::shared_ptr<Context> _context;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class ClassicGraphicsManager;
|
||||||
|
|
||||||
|
struct Context
|
||||||
|
{
|
||||||
|
std::shared_ptr<ClassicGraphicsManager> graphics_manager;
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "holdmanager.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* THIS IS SIDEQUEST!!!! Right now I am working on the Editor >:C
|
||||||
|
*
|
||||||
|
* */
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/inputtype.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ClassicArrowNote;
|
||||||
|
|
||||||
|
class HoldManager // Not important now
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit HoldManager() = default;
|
||||||
|
|
||||||
|
void emplace(ClassicArrowNote* note);
|
||||||
|
void checkRelease(sf::Keyboard::Key released_key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ClassicArrowNote*> _notes_on_hold;
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "elementinitializer.h"
|
||||||
|
#include "classicactions.h"
|
||||||
|
|
||||||
|
struct ArrowElementInitializer
|
||||||
|
{
|
||||||
|
ElementInitializer element;
|
||||||
|
Type type = Type::NONE;
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "noteinitializer.h"
|
||||||
|
#include "arrowelementinitializer.h"
|
||||||
|
|
||||||
|
struct ArrowNoteInitializer
|
||||||
|
{
|
||||||
|
NoteInitializer initializer;
|
||||||
|
bool hold = false;
|
||||||
|
|
||||||
|
std::vector<ArrowElementInitializer> elements;
|
||||||
|
};
|
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/inputtype.h"
|
||||||
|
#include "tools/mathutils.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
struct ElementInitializer
|
||||||
|
{
|
||||||
|
Coordinates coordinates;
|
||||||
|
std::vector<Coordinates> falling_curve_interpolation;
|
||||||
|
std::array<sf::Keyboard::Key, 2> keys; // needs initialization
|
||||||
|
};
|
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
|
#include "tools/mathutils.h"
|
||||||
|
|
||||||
|
struct NoteInitializer
|
||||||
|
{
|
||||||
|
std::shared_ptr<Context> context;
|
||||||
|
std::vector<microsec> intervals;
|
||||||
|
microsec perfect_offset = 0;
|
||||||
|
};
|
|
@ -10,3 +10,5 @@ file(GLOB_RECURSE HEADERS "shared/*.h" "include/*.h")
|
||||||
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
||||||
|
|
||||||
add_library(tools STATIC ${SOURCES} ${HEADERS})
|
add_library(tools STATIC ${SOURCES} ${HEADERS})
|
||||||
|
|
||||||
|
target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared)
|
||||||
|
|
Loading…
Reference in New Issue