diff --git a/.gitignore b/.gitignore index 7a70de4..ca09e17 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ compile_commands.json imgui.ini bave*.log /spaced +/notes.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 3753ed5..88c1028 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,12 +9,12 @@ set(CMAKE_CXX_EXTENSIONS OFF) include(FetchContent) FetchContent_Declare( - bave - GIT_REPOSITORY https://github.com/karnkaul/bave - GIT_TAG v0.5.4 - SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/bave" + bgf + GIT_REPOSITORY https://github.com/karnkaul/bgf + GIT_TAG v0.1.0 + SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/bgf" ) -FetchContent_MakeAvailable(bave) +FetchContent_MakeAvailable(bgf) add_subdirectory(src) diff --git a/assets/fonts/CuteDino.otf b/assets/fonts/CuteDino.otf new file mode 100644 index 0000000..d247239 Binary files /dev/null and b/assets/fonts/CuteDino.otf differ diff --git a/assets/fonts/hesitation.regular.ttf b/assets/fonts/hesitation.regular.ttf deleted file mode 100644 index 83dafc7..0000000 Binary files a/assets/fonts/hesitation.regular.ttf and /dev/null differ diff --git a/assets/styles.json b/assets/styles.json index 50dd488..06607c0 100644 --- a/assets/styles.json +++ b/assets/styles.json @@ -37,8 +37,8 @@ "padding": 10 }, "enemy": { - "background": "#f75c03ff", - "fill": "#ffffffff", + "background": "orange", + "fill": "milk", "corner_ratio": 0.5, "padding": 5 } @@ -50,9 +50,9 @@ 10.000000 ], "corner_ratio": 0.25, - "background_tint": "#e5cdaeff", - "outline_tint": "#231d2aff", - "content_text_tint": "#231d2aff" + "background_tint": "milk", + "outline_tint": "black", + "content_text_tint": "black" } }, "sliders": { @@ -63,7 +63,7 @@ } }, "loading_screen": { - "background_tint": "#231d2aff", + "background_tint": "black", "spinner": { "size": [ 100.000000, diff --git a/src/spaced/CMakeLists.txt b/src/spaced/CMakeLists.txt index 3be00f3..c38e16e 100644 --- a/src/spaced/CMakeLists.txt +++ b/src/spaced/CMakeLists.txt @@ -7,7 +7,7 @@ add_library(${PROJECT_NAME}) add_library(spaced::lib ALIAS ${PROJECT_NAME}) target_link_libraries(${PROJECT_NAME} PUBLIC - bave::bave + bave::bgf bave::bave-compile-options ) @@ -19,3 +19,5 @@ target_include_directories(${PROJECT_NAME} PUBLIC file(GLOB_RECURSE sources LIST_DIRECTORIES false CONFIGURE_DEPENDS "spaced/*.?pp") target_sources(${PROJECT_NAME} PRIVATE ${sources}) + +target_precompile_headers(${PROJECT_NAME} REUSE_FROM bave) diff --git a/src/spaced/spaced/assets/asset_list.cpp b/src/spaced/spaced/assets/asset_list.cpp index 4d66598..c7edeb9 100644 --- a/src/spaced/spaced/assets/asset_list.cpp +++ b/src/spaced/spaced/assets/asset_list.cpp @@ -1,9 +1,12 @@ +#include #include #include -#include namespace spaced { +using bave::AsyncExec; using bave::Loader; +using bave::Resources; +using bave::Services; AssetList::AssetList(Loader loader, Services const& services) : m_loader(std::move(loader)), m_resources(&services.get()) {} diff --git a/src/spaced/spaced/assets/asset_list.hpp b/src/spaced/spaced/assets/asset_list.hpp index 8545a2d..a2debc1 100644 --- a/src/spaced/spaced/assets/asset_list.hpp +++ b/src/spaced/spaced/assets/asset_list.hpp @@ -1,17 +1,21 @@ #pragma once +#include #include +#include +#include #include -#include -#include #include -namespace spaced { +namespace bave { struct Resources; +} + +namespace spaced { class AssetLoader; class AssetList { public: - explicit AssetList(bave::Loader loader, Services const& services); + explicit AssetList(bave::Loader loader, bave::Services const& services); auto add_texture(std::string uri, bool mip_map = false) -> AssetList&; auto add_font(std::string uri) -> AssetList&; @@ -20,7 +24,7 @@ class AssetList { void add_manifest(AssetManifest manifest); - [[nodiscard]] auto build_task_stages() const -> std::vector; + [[nodiscard]] auto build_task_stages() const -> std::vector; private: struct Tex { @@ -32,11 +36,11 @@ class AssetList { auto operator<(Tex const& rhs) const -> bool { return uri < rhs.uri; } }; - auto build_stage_0(AssetLoader& asset_loader) const -> AsyncExec::Stage; - auto build_stage_1(AssetLoader& asset_loader) const -> AsyncExec::Stage; + auto build_stage_0(AssetLoader& asset_loader) const -> bave::AsyncExec::Stage; + auto build_stage_1(AssetLoader& asset_loader) const -> bave::AsyncExec::Stage; bave::Loader m_loader; - bave::NotNull m_resources; + bave::NotNull m_resources; std::set m_textures{}; std::set m_fonts{}; diff --git a/src/spaced/spaced/assets/asset_loader.cpp b/src/spaced/spaced/assets/asset_loader.cpp index f88b847..c995b61 100644 --- a/src/spaced/spaced/assets/asset_loader.cpp +++ b/src/spaced/spaced/assets/asset_loader.cpp @@ -9,6 +9,7 @@ using bave::Loader; using bave::Logger; using bave::NotNull; using bave::ParticleEmitter; +using bave::Resources; using bave::Texture; struct AssetLoader::Impl { diff --git a/src/spaced/spaced/assets/asset_loader.hpp b/src/spaced/spaced/assets/asset_loader.hpp index 36d1a68..22c9bf4 100644 --- a/src/spaced/spaced/assets/asset_loader.hpp +++ b/src/spaced/spaced/assets/asset_loader.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include @@ -10,7 +10,7 @@ class AssetLoader { public: using LoadTask = std::function; - explicit AssetLoader(bave::Loader loader, bave::NotNull resources); + explicit AssetLoader(bave::Loader loader, bave::NotNull resources); [[nodiscard]] auto make_load_font(std::string uri, bool reload = false) -> LoadTask; [[nodiscard]] auto make_load_texture(std::string uri, bool mip_map = false, bool reload = false) -> LoadTask; diff --git a/src/spaced/spaced/async_exec.cpp b/src/spaced/spaced/async_exec.cpp deleted file mode 100644 index 00e50a5..0000000 --- a/src/spaced/spaced/async_exec.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include - -namespace spaced { -using namespace std::chrono_literals; - -AsyncExec::AsyncExec(std::vector tasks) { - if (tasks.empty()) { return; } - - m_total = static_cast(tasks.size()); - enqueue(tasks); -} - -AsyncExec::AsyncExec(std::vector stages) { - if (stages.empty()) { return; } - std::move(stages.begin(), stages.end(), std::back_inserter(m_stages)); - m_total = std::accumulate(m_stages.begin(), m_stages.end(), 0, [](int count, auto const& tasks) { return static_cast(tasks.size()) + count; }); - start_next_stage(); -} - -auto AsyncExec::update() -> Status { - if (m_remain.empty()) { - if (m_stages.empty()) { return Status{.remain = 0, .total = m_total}; } - start_next_stage(); - } - std::erase_if(m_remain, [](std::future const& future) { return !future.valid() || future.wait_for(0s) == std::future_status::ready; }); - return Status{.remain = m_total - m_completed, .total = m_total}; -} - -void AsyncExec::start_next_stage() { - if (m_stages.empty()) { return; } - - auto get_next_stage = [&] { - auto ret = std::move(m_stages.front()); - m_stages.pop_front(); - return ret; - }; - - auto stage = get_next_stage(); - while (stage.empty() && !m_stages.empty()) { stage = get_next_stage(); } - - enqueue(stage); -} - -void AsyncExec::enqueue(std::span tasks) { - assert(m_remain.empty()); - if (tasks.empty()) { return; } - - m_remain.reserve(tasks.size()); - for (auto const& task : tasks) { - auto func = [task = task, this] { - task(); - ++m_completed; - }; - m_remain.push_back(std::async(std::move(func))); - } -} -} // namespace spaced diff --git a/src/spaced/spaced/async_exec.hpp b/src/spaced/spaced/async_exec.hpp deleted file mode 100644 index 66abe5e..0000000 --- a/src/spaced/spaced/async_exec.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace spaced { -class AsyncExec { - public: - using Task = std::function; - using Stage = std::vector; - - struct Status; - - explicit AsyncExec(std::vector tasks); - explicit AsyncExec(std::vector stages); - - auto update() -> Status; - - private: - void start_next_stage(); - void enqueue(std::span tasks); - - std::vector> m_remain{}; - std::deque m_stages{}; - std::atomic m_completed{}; - int m_total{}; -}; - -struct AsyncExec::Status { - int remain{}; - int total{}; - - [[nodiscard]] constexpr auto progress() const -> float { - if (total == 0) { return 1.0f; } - return static_cast(total - remain) / static_cast(total); - } - - [[nodiscard]] constexpr auto is_complete() const -> bool { return remain == 0; } - - explicit constexpr operator bool() const { return is_complete(); } -}; -} // namespace spaced diff --git a/src/spaced/spaced/game/arsenal.cpp b/src/spaced/spaced/game/arsenal.cpp index 90ff556..11bb5b9 100644 --- a/src/spaced/spaced/game/arsenal.cpp +++ b/src/spaced/spaced/game/arsenal.cpp @@ -3,6 +3,7 @@ namespace spaced { using bave::Seconds; +using bave::Services; using bave::Shader; Arsenal::Arsenal(Services const& services) : m_primary(services), m_stats(&services.get()) {} diff --git a/src/spaced/spaced/game/arsenal.hpp b/src/spaced/spaced/game/arsenal.hpp index 2322a49..38827f4 100644 --- a/src/spaced/spaced/game/arsenal.hpp +++ b/src/spaced/spaced/game/arsenal.hpp @@ -8,7 +8,7 @@ struct Stats; // Weapons only switch when they are idle. class Arsenal { public: - explicit Arsenal(Services const& services); + explicit Arsenal(bave::Services const& services); [[nodiscard]] auto get_weapon() const -> Weapon const&; [[nodiscard]] auto get_weapon() -> Weapon&; diff --git a/src/spaced/spaced/game/controllers/auto_controller.hpp b/src/spaced/spaced/game/controllers/auto_controller.hpp index d38fb3d..bf822ad 100644 --- a/src/spaced/spaced/game/controllers/auto_controller.hpp +++ b/src/spaced/spaced/game/controllers/auto_controller.hpp @@ -1,12 +1,12 @@ #pragma once #include #include +#include #include #include #include #include #include -#include namespace spaced { class AutoController : public FollowController { diff --git a/src/spaced/spaced/game/controllers/player_controller.cpp b/src/spaced/spaced/game/controllers/player_controller.cpp index 28edd78..8fcae45 100644 --- a/src/spaced/spaced/game/controllers/player_controller.cpp +++ b/src/spaced/spaced/game/controllers/player_controller.cpp @@ -9,18 +9,20 @@ using bave::Action; using bave::EnumArray; using bave::GamepadAxis; using bave::GamepadButton; +using bave::IDisplay; using bave::im_text; using bave::PointerMove; using bave::PointerTap; using bave::Seconds; +using bave::Services; -PlayerController::PlayerController(Services const& services) : m_layout(&services.get()), m_gamepad_provider(&services.get()) { - max_y = 0.5f * m_layout->get_world_space().y; +PlayerController::PlayerController(Services const& services) : m_display(&services.get()), m_gamepad_provider(&services.get()) { + max_y = 0.5f * m_display->get_world_space().y; min_y = -max_y; // NOLINT(cppcoreguidelines-prefer-member-initializer) } void PlayerController::on_move(PointerMove const& pointer_move) { - auto const world_pos = m_layout->project_to_world(pointer_move.pointer.position); + auto const world_pos = m_display->project_to_world(pointer_move.pointer.position); if (m_type == Type::eTouch) { if (!is_in_move_area(world_pos)) { @@ -39,7 +41,7 @@ void PlayerController::on_move(PointerMove const& pointer_move) { } void PlayerController::on_tap(PointerTap const& pointer_tap) { - auto const world_pos = m_layout->project_to_world(pointer_tap.pointer.position); + auto const world_pos = m_display->project_to_world(pointer_tap.pointer.position); if (m_type == Type::eTouch && is_in_move_area(world_pos)) { // pointer tap in move area is ingored return; @@ -66,7 +68,7 @@ void PlayerController::stop_firing() { } auto PlayerController::is_in_move_area(glm::vec2 const position) const -> bool { - auto const n_pos = position.x / m_layout->get_world_space().x; + auto const n_pos = position.x / m_display->get_world_space().x; return n_pos <= -n_move_area; } diff --git a/src/spaced/spaced/game/controllers/player_controller.hpp b/src/spaced/spaced/game/controllers/player_controller.hpp index f20c325..72f0c2c 100644 --- a/src/spaced/spaced/game/controllers/player_controller.hpp +++ b/src/spaced/spaced/game/controllers/player_controller.hpp @@ -1,11 +1,11 @@ #pragma once #include #include +#include +#include #include #include #include -#include -#include namespace spaced { class PlayerController : public FollowController { @@ -18,7 +18,7 @@ class PlayerController : public FollowController { [[nodiscard]] auto get_type_name() const -> std::string_view final { return type_name_v; }; - explicit PlayerController(Services const& services); + explicit PlayerController(bave::Services const& services); void on_move(bave::PointerMove const& pointer_move) final; void on_tap(bave::PointerTap const& pointer_tap) final; @@ -45,7 +45,7 @@ class PlayerController : public FollowController { auto tick_y(bave::Seconds dt) -> float final; void do_inspect() final; - bave::Ptr m_layout{}; + bave::Ptr m_display{}; bave::Ptr m_gamepad_provider{}; Type m_type{}; diff --git a/src/spaced/spaced/game/enemies/creep.cpp b/src/spaced/spaced/game/enemies/creep.cpp index 903ec8c..db37e37 100644 --- a/src/spaced/spaced/game/enemies/creep.cpp +++ b/src/spaced/spaced/game/enemies/creep.cpp @@ -8,6 +8,6 @@ void Creep::tick(Seconds const dt, bool const in_play) { if (!in_play) { return; } shape.transform.position.x -= x_speed * dt.count(); - if (shape.transform.position.x < -0.5f * (get_layout().get_world_space().x + shape.get_shape().size.x)) { set_destroyed(); } + if (shape.transform.position.x < -0.5f * (get_layout().world_space.x + shape.get_shape().size.x)) { set_destroyed(); } } } // namespace spaced diff --git a/src/spaced/spaced/game/enemies/creep.hpp b/src/spaced/spaced/game/enemies/creep.hpp index 12c1c6f..6579cc8 100644 --- a/src/spaced/spaced/game/enemies/creep.hpp +++ b/src/spaced/spaced/game/enemies/creep.hpp @@ -4,7 +4,7 @@ namespace spaced { class Creep : public Enemy { public: - explicit Creep(Services const& services) : Enemy(services, "Creep") {} + explicit Creep(bave::Services const& services) : Enemy(services, "Creep") {} void tick(bave::Seconds dt, bool in_play) override; diff --git a/src/spaced/spaced/game/enemies/creep_factory.cpp b/src/spaced/spaced/game/enemies/creep_factory.cpp index cea3595..18103ac 100644 --- a/src/spaced/spaced/game/enemies/creep_factory.cpp +++ b/src/spaced/spaced/game/enemies/creep_factory.cpp @@ -1,12 +1,13 @@ #include +#include +#include #include #include -#include -#include namespace spaced { using bave::random_in_range; using bave::Seconds; +using bave::Styles; auto CreepFactory::spawn_enemy() -> std::unique_ptr { auto ret = std::make_unique(get_services()); diff --git a/src/spaced/spaced/game/enemy.cpp b/src/spaced/spaced/game/enemy.cpp index e6e6a39..77cd6d3 100644 --- a/src/spaced/spaced/game/enemy.cpp +++ b/src/spaced/spaced/game/enemy.cpp @@ -1,19 +1,23 @@ #include #include +#include +#include #include -#include -#include namespace spaced { using bave::im_text; using bave::random_in_range; using bave::RoundedQuad; using bave::Seconds; +using bave::Services; using bave::Shader; +using bave::Styles; -Enemy::Enemy(Services const& services, std::string_view const type) : m_layout(&services.get()), m_health_bar(services), m_type(type) { +namespace ui = bave::ui; + +Enemy::Enemy(Services const& services, std::string_view const type) : m_layout(&services.get()), m_health_bar(services), m_type(type) { static constexpr auto init_size_v = glm::vec2{100.0f}; - auto const play_area = m_layout->get_play_area(); + auto const play_area = m_layout->play_area; auto const y_min = play_area.rb.y + 0.5f * init_size_v.y; auto const y_max = play_area.lt.y - 0.5f * init_size_v.y - 50.0f; setup(init_size_v, random_in_range(y_min, y_max)); @@ -49,7 +53,7 @@ void Enemy::setup(glm::vec2 max_size, float y_position) { rounded_quad.size = max_size; rounded_quad.corner_radius = 0.2f * max_size.x; shape.set_shape(rounded_quad); - shape.transform.position.x = 0.5f * (get_layout().get_world_space().x + rounded_quad.size.x); + shape.transform.position.x = 0.5f * (get_layout().world_space.x + rounded_quad.size.x); shape.transform.position.y = y_position; } diff --git a/src/spaced/spaced/game/enemy.hpp b/src/spaced/spaced/game/enemy.hpp index 04ffe58..45685ef 100644 --- a/src/spaced/spaced/game/enemy.hpp +++ b/src/spaced/spaced/game/enemy.hpp @@ -2,16 +2,16 @@ #include #include #include +#include +#include #include #include #include -#include -#include namespace spaced { class Enemy : public IDamageable, public bave::IDrawable { public: - explicit Enemy(Services const& services, std::string_view type); + explicit Enemy(bave::Services const& services, std::string_view type); [[nodiscard]] auto get_instigator() const -> Instigator final { return Instigator::eEnemy; } [[nodiscard]] auto get_bounds() const -> bave::Rect<> override { return shape.get_bounds(); } @@ -27,7 +27,7 @@ class Enemy : public IDamageable, public bave::IDrawable { void setup(glm::vec2 max_size, float y_position); - [[nodiscard]] auto get_layout() const -> ILayout const& { return *m_layout; } + [[nodiscard]] auto get_layout() const -> Layout const& { return *m_layout; } void inspect() { if constexpr (bave::debug_v) { do_inspect(); } @@ -43,9 +43,9 @@ class Enemy : public IDamageable, public bave::IDrawable { private: virtual void do_inspect(); - bave::NotNull m_layout; + bave::NotNull m_layout; - ui::ProgressBar m_health_bar; + bave::ui::ProgressBar m_health_bar; std::string_view m_type{}; bool m_destroyed{}; diff --git a/src/spaced/spaced/game/enemy_factory.cpp b/src/spaced/spaced/game/enemy_factory.cpp index 97c4c20..e31c7ce 100644 --- a/src/spaced/spaced/game/enemy_factory.cpp +++ b/src/spaced/spaced/game/enemy_factory.cpp @@ -1,9 +1,11 @@ +#include #include -#include namespace spaced { +using bave::IAudio; using bave::NotNull; using bave::Seconds; +using bave::Services; EnemyFactory::EnemyFactory(NotNull services) : m_services(services), m_audio(&services->get()) {} diff --git a/src/spaced/spaced/game/enemy_factory.hpp b/src/spaced/spaced/game/enemy_factory.hpp index c183b30..af22ddb 100644 --- a/src/spaced/spaced/game/enemy_factory.hpp +++ b/src/spaced/spaced/game/enemy_factory.hpp @@ -1,25 +1,24 @@ #pragma once #include +#include #include namespace spaced { -class IAudio; - class EnemyFactory : public bave::Polymorphic { public: - explicit EnemyFactory(bave::NotNull services); + explicit EnemyFactory(bave::NotNull services); [[nodiscard]] virtual auto spawn_enemy() -> std::unique_ptr = 0; auto tick(bave::Seconds dt) -> std::unique_ptr; - [[nodiscard]] auto get_services() const -> Services const& { return *m_services; } + [[nodiscard]] auto get_services() const -> bave::Services const& { return *m_services; } bave::Seconds spawn_rate{1s}; private: - bave::NotNull m_services; - bave::NotNull m_audio; + bave::NotNull m_services; + bave::NotNull m_audio; bave::Seconds m_elapsed{}; }; diff --git a/src/spaced/spaced/game/hud.cpp b/src/spaced/spaced/game/hud.cpp index 9799892..2a6d3c5 100644 --- a/src/spaced/spaced/game/hud.cpp +++ b/src/spaced/spaced/game/hud.cpp @@ -1,11 +1,16 @@ #include +#include #include -#include +#include namespace spaced { +using bave::Services; +using bave::Styles; using bave::TextHeight; -Hud::Hud(Services const& services) : ui::View(services), m_styles(&services.get()), m_area(m_layout->get_hud_area()) { +namespace ui = bave::ui; + +Hud::Hud(Services const& services) : ui::View(services), m_styles(&services.get()), m_area(services.get().hud_area) { create_background(); create_score(services); diff --git a/src/spaced/spaced/game/hud.hpp b/src/spaced/spaced/game/hud.hpp index 0f1d0bb..bc26dc3 100644 --- a/src/spaced/spaced/game/hud.hpp +++ b/src/spaced/spaced/game/hud.hpp @@ -1,26 +1,26 @@ #pragma once -#include -#include -#include -#include +#include +#include +#include +#include namespace spaced { -class Hud : public ui::View { +class Hud : public bave::ui::View { public: - explicit Hud(Services const& services); + explicit Hud(bave::Services const& services); void set_score(std::int64_t score); void set_hi_score(std::int64_t score); private: void create_background(); - void create_score(Services const& services); + void create_score(bave::Services const& services); - bave::NotNull m_styles; + bave::NotNull m_styles; bave::Rect<> m_area{}; - bave::Ptr m_background{}; - bave::Ptr m_score{}; - bave::Ptr m_hi_score{}; + bave::Ptr m_background{}; + bave::Ptr m_score{}; + bave::Ptr m_hi_score{}; }; } // namespace spaced diff --git a/src/spaced/spaced/game/player.cpp b/src/spaced/spaced/game/player.cpp index c123d4b..79eb349 100644 --- a/src/spaced/spaced/game/player.cpp +++ b/src/spaced/spaced/game/player.cpp @@ -1,10 +1,11 @@ #include #include #include +#include +#include #include -#include +#include #include -#include // temp for testing #include @@ -13,16 +14,19 @@ namespace spaced { using bave::ParticleEmitter; using bave::PointerMove; using bave::PointerTap; +using bave::Resources; using bave::RoundedQuad; using bave::Seconds; +using bave::Services; using bave::Shader; +using bave::Styles; Player::Player(Services const& services, std::unique_ptr controller) : m_services(&services), m_stats(&services.get()), m_controller(std::move(controller)) { - auto const& layout = services.get(); - ship.transform.position.x = layout.get_player_x(); + auto const& layout = services.get(); + ship.transform.position.x = layout.player_x; auto rounded_quad = RoundedQuad{}; - rounded_quad.size = layout.get_player_size(); + rounded_quad.size = layout.player_size; rounded_quad.corner_radius = 20.0f; ship.set_shape(rounded_quad); diff --git a/src/spaced/spaced/game/player.hpp b/src/spaced/spaced/game/player.hpp index ebee256..015ca75 100644 --- a/src/spaced/spaced/game/player.hpp +++ b/src/spaced/spaced/game/player.hpp @@ -17,7 +17,7 @@ class Player : public bave::IDrawable { std::span const> powerups{}; }; - explicit Player(Services const& services, std::unique_ptr controller); + explicit Player(bave::Services const& services, std::unique_ptr controller); void on_focus(bave::FocusChange const& focus_change); void on_move(bave::PointerMove const& pointer_move); @@ -50,7 +50,7 @@ class Player : public bave::IDrawable { void do_inspect(); bave::Logger m_log{"Player"}; - bave::NotNull m_services; + bave::NotNull m_services; bave::NotNull m_stats; std::unique_ptr m_controller; bave::ParticleEmitter m_exhaust{}; diff --git a/src/spaced/spaced/game/powerups/pu_base.cpp b/src/spaced/spaced/game/powerups/pu_base.cpp index 22cd99f..f30d6b5 100644 --- a/src/spaced/spaced/game/powerups/pu_base.cpp +++ b/src/spaced/spaced/game/powerups/pu_base.cpp @@ -1,13 +1,15 @@ +#include #include -#include namespace spaced { using bave::ParticleEmitter; +using bave::Resources; using bave::RoundedQuad; using bave::Seconds; +using bave::Services; using bave::Shader; -PUBase::PUBase(Services const& services, std::string_view const name) : m_services(&services), m_layout(&services.get()), m_name(name) { +PUBase::PUBase(Services const& services, std::string_view const name) : m_services(&services), m_layout(&services.get()), m_name(name) { auto quad = RoundedQuad{}; quad.size = glm::vec2{40.0f}; quad.corner_radius = 12.5f; @@ -21,7 +23,7 @@ PUBase::PUBase(Services const& services, std::string_view const name) : m_servic void PUBase::tick(Seconds const dt) { shape.transform.position.x -= speed * dt.count(); - if (shape.transform.position.x < m_layout->get_play_area().lt.x - 0.5f * shape.get_shape().size.x) { m_destroyed = true; } + if (shape.transform.position.x < m_layout->play_area.lt.x - 0.5f * shape.get_shape().size.x) { m_destroyed = true; } emitter.set_position(shape.transform.position); if (!m_emitter_ticked) { diff --git a/src/spaced/spaced/game/powerups/pu_base.hpp b/src/spaced/spaced/game/powerups/pu_base.hpp index baf64e7..4c200c4 100644 --- a/src/spaced/spaced/game/powerups/pu_base.hpp +++ b/src/spaced/spaced/game/powerups/pu_base.hpp @@ -2,14 +2,14 @@ #include #include #include +#include #include #include -#include namespace spaced { class PUBase : public IPowerup { public: - explicit PUBase(Services const& services, std::string_view name); + explicit PUBase(bave::Services const& services, std::string_view name); void tick(bave::Seconds dt) final; void draw(bave::Shader& shader) const final; @@ -26,8 +26,8 @@ class PUBase : public IPowerup { protected: virtual void do_activate(Player& player) = 0; - bave::NotNull m_services; - bave::NotNull m_layout; + bave::NotNull m_services; + bave::NotNull m_layout; std::string_view m_name{}; bool m_emitter_ticked{}; bool m_destroyed{}; diff --git a/src/spaced/spaced/game/powerups/pu_beam.cpp b/src/spaced/spaced/game/powerups/pu_beam.cpp index b1c50c5..49b2167 100644 --- a/src/spaced/spaced/game/powerups/pu_beam.cpp +++ b/src/spaced/spaced/game/powerups/pu_beam.cpp @@ -1,9 +1,12 @@ +#include #include #include #include -#include namespace spaced { +using bave::Services; +using bave::Styles; + PUBeam::PUBeam(Services const& services, int rounds) : PUBase(services, "Beam"), m_rounds(rounds) { emitter.config.lerp.tint.lo = emitter.config.lerp.tint.hi = shape.tint = services.get().rgbas["gun_beam"]; emitter.config.lerp.tint.hi.channels.w = 0; diff --git a/src/spaced/spaced/game/powerups/pu_beam.hpp b/src/spaced/spaced/game/powerups/pu_beam.hpp index 9e19668..abf8335 100644 --- a/src/spaced/spaced/game/powerups/pu_beam.hpp +++ b/src/spaced/spaced/game/powerups/pu_beam.hpp @@ -4,7 +4,7 @@ namespace spaced { class PUBeam : public PUBase { public: - explicit PUBeam(Services const& services, int rounds = 2); + explicit PUBeam(bave::Services const& services, int rounds = 2); private: void do_activate(Player& player) final; diff --git a/src/spaced/spaced/game/weapon.cpp b/src/spaced/spaced/game/weapon.cpp index fe67c4f..b4da785 100644 --- a/src/spaced/spaced/game/weapon.cpp +++ b/src/spaced/spaced/game/weapon.cpp @@ -1,11 +1,14 @@ #include +#include #include -#include namespace spaced { +using bave::IAudio; +using bave::IDisplay; using bave::im_text; +using bave::Services; -Weapon::Weapon(Services const& services, std::string name) : m_log{std::move(name)}, m_layout(&services.get()), m_audio(&services.get()) {} +Weapon::Weapon(Services const& services, std::string name) : m_log{std::move(name)}, m_display(&services.get()), m_audio(&services.get()) {} auto Weapon::fire(glm::vec2 const muzzle_position) -> std::unique_ptr { auto ret = do_fire(muzzle_position); diff --git a/src/spaced/spaced/game/weapon.hpp b/src/spaced/spaced/game/weapon.hpp index a105ca6..b114b84 100644 --- a/src/spaced/spaced/game/weapon.hpp +++ b/src/spaced/spaced/game/weapon.hpp @@ -1,18 +1,20 @@ #pragma once #include #include +#include +#include #include -#include -#include -namespace spaced { +namespace bave { class IAudio; +} +namespace spaced { class Weapon : public bave::Polymorphic { public: using Round = IWeaponRound; - explicit Weapon(Services const& services, std::string name); + explicit Weapon(bave::Services const& services, std::string name); [[nodiscard]] auto get_rounds_remaining() const -> int { return rounds < 0 ? 1 : rounds; } @@ -28,7 +30,7 @@ class Weapon : public bave::Polymorphic { int rounds{-1}; protected: - [[nodiscard]] auto get_layout() const -> ILayout const& { return *m_layout; } + [[nodiscard]] auto get_display() const -> bave::IDisplay const& { return *m_display; } virtual auto do_fire(glm::vec2 muzzle_position) -> std::unique_ptr = 0; virtual void do_inspect(); @@ -37,7 +39,7 @@ class Weapon : public bave::Polymorphic { std::vector m_fire_sfx{}; private: - bave::NotNull m_layout; - bave::NotNull m_audio; + bave::NotNull m_display; + bave::NotNull m_audio; }; } // namespace spaced diff --git a/src/spaced/spaced/game/weapons/gun_beam.cpp b/src/spaced/spaced/game/weapons/gun_beam.cpp index 43653a5..e877096 100644 --- a/src/spaced/spaced/game/weapons/gun_beam.cpp +++ b/src/spaced/spaced/game/weapons/gun_beam.cpp @@ -1,25 +1,28 @@ #include #include +#include #include -#include namespace spaced { +using bave::IDisplay; using bave::im_text; using bave::NotNull; using bave::Ptr; using bave::Rect; using bave::Rgba; using bave::Seconds; +using bave::Services; using bave::Shader; using bave::Sprite; +using bave::Styles; namespace { class LaserCharge : public IWeaponRound { public: using Config = GunBeam::Config; - explicit LaserCharge(NotNull layout, Config config, glm::vec2 const muzzle_position) - : m_layout(layout), m_config(config), m_fire_remain(config.fire_duration) { + explicit LaserCharge(NotNull display, Config config, glm::vec2 const muzzle_position) + : m_display(display), m_config(config), m_fire_remain(config.fire_duration) { m_ray.transform.position.y = muzzle_position.y; } @@ -30,7 +33,7 @@ class LaserCharge : public IWeaponRound { sort_entries(state.targets, state.muzzle_position); - auto const world_space = m_layout->get_world_space(); + auto const world_space = m_display->get_world_space(); auto const left_x = state.muzzle_position.x; auto right_x = 0.5f * world_space.x; for (auto const& entry : m_entries) { @@ -88,7 +91,7 @@ class LaserCharge : public IWeaponRound { float distance{}; }; - NotNull m_layout; + NotNull m_display; Config m_config; Sprite m_ray{}; @@ -119,7 +122,7 @@ auto GunBeam::do_fire(glm::vec2 const muzzle_position) -> std::unique_ptr if (rounds > 0) { --rounds; } m_fire_remain = config.fire_duration; m_reload_remain = 0s; - return std::make_unique(&get_layout(), config, muzzle_position); + return std::make_unique(&get_display(), config, muzzle_position); } void GunBeam::do_inspect() { diff --git a/src/spaced/spaced/game/weapons/gun_beam.hpp b/src/spaced/spaced/game/weapons/gun_beam.hpp index 691bd74..038288c 100644 --- a/src/spaced/spaced/game/weapons/gun_beam.hpp +++ b/src/spaced/spaced/game/weapons/gun_beam.hpp @@ -12,7 +12,7 @@ class GunBeam final : public Weapon { float dps{10.0f}; }; - explicit GunBeam(Services const& services); + explicit GunBeam(bave::Services const& services); [[nodiscard]] auto is_idle() const -> bool final { return m_fire_remain <= 0s; } void tick(bave::Seconds dt) final; diff --git a/src/spaced/spaced/game/weapons/gun_kinetic.cpp b/src/spaced/spaced/game/weapons/gun_kinetic.cpp index 8f33586..981ceb1 100644 --- a/src/spaced/spaced/game/weapons/gun_kinetic.cpp +++ b/src/spaced/spaced/game/weapons/gun_kinetic.cpp @@ -1,11 +1,14 @@ #include +#include #include -#include namespace spaced { +using bave::IAudio; using bave::im_text; using bave::Rgba; using bave::Seconds; +using bave::Services; +using bave::Styles; GunKinetic::GunKinetic(Services const& services) : Weapon(services, "GunKinetic"), m_audio(&services.get()) { projectile_config.tint = services.get().rgbas["black"]; @@ -20,7 +23,7 @@ auto GunKinetic::do_fire(glm::vec2 const muzzle_position) -> std::unique_ptr 0) { --rounds; } m_reload_remain = reload_delay; - return std::make_unique(&get_layout(), projectile_config, muzzle_position); + return std::make_unique(&get_display(), projectile_config, muzzle_position); } void GunKinetic::do_inspect() { diff --git a/src/spaced/spaced/game/weapons/gun_kinetic.hpp b/src/spaced/spaced/game/weapons/gun_kinetic.hpp index d58053a..c321966 100644 --- a/src/spaced/spaced/game/weapons/gun_kinetic.hpp +++ b/src/spaced/spaced/game/weapons/gun_kinetic.hpp @@ -1,12 +1,12 @@ #pragma once +#include #include #include -#include namespace spaced { class GunKinetic final : public Weapon { public: - explicit GunKinetic(Services const& services); + explicit GunKinetic(bave::Services const& services); [[nodiscard]] auto is_idle() const -> bool final { return m_reload_remain <= 0s; } @@ -20,6 +20,6 @@ class GunKinetic final : public Weapon { void do_inspect() final; bave::Seconds m_reload_remain{}; - bave::NotNull m_audio; + bave::NotNull m_audio; }; } // namespace spaced diff --git a/src/spaced/spaced/game/weapons/projectile.cpp b/src/spaced/spaced/game/weapons/projectile.cpp index 6652eca..11d2dbd 100644 --- a/src/spaced/spaced/game/weapons/projectile.cpp +++ b/src/spaced/spaced/game/weapons/projectile.cpp @@ -1,6 +1,7 @@ #include namespace spaced { +using bave::IDisplay; using bave::NotNull; using bave::Rect; using bave::RoundedQuad; @@ -15,7 +16,7 @@ namespace { } } // namespace -Projectile::Projectile(NotNull layout, Config config, glm::vec2 const muzzle_position) : m_layout(layout), m_config(std::move(config)) { +Projectile::Projectile(NotNull display, Config config, glm::vec2 const muzzle_position) : m_display(display), m_config(std::move(config)) { auto rounded_quad = RoundedQuad{}; rounded_quad.size = m_config.size; rounded_quad.corner_radius = m_config.corner_radius; @@ -42,7 +43,7 @@ void Projectile::tick(State const& state, Seconds const dt) { } } - if (m_shape.transform.position.x > 0.5f * (m_layout->get_world_space().x + m_config.size.x)) { m_destroyed = true; } + if (m_shape.transform.position.x > 0.5f * (m_display->get_world_space().x + m_config.size.x)) { m_destroyed = true; } } void Projectile::draw(Shader& shader) const { m_shape.draw(shader); } diff --git a/src/spaced/spaced/game/weapons/projectile.hpp b/src/spaced/spaced/game/weapons/projectile.hpp index a3f966b..ca4b129 100644 --- a/src/spaced/spaced/game/weapons/projectile.hpp +++ b/src/spaced/spaced/game/weapons/projectile.hpp @@ -1,8 +1,8 @@ #pragma once #include +#include #include #include -#include namespace spaced { class Projectile : public IWeaponRound { @@ -17,14 +17,14 @@ class Projectile : public IWeaponRound { Instigator instigator{Instigator::ePlayer}; }; - explicit Projectile(bave::NotNull layout, Config config, glm::vec2 muzzle_position); + explicit Projectile(bave::NotNull display, Config config, glm::vec2 muzzle_position); void tick(State const& state, bave::Seconds dt) override; [[nodiscard]] auto is_destroyed() const -> bool override { return m_destroyed; } void draw(bave::Shader& shader) const override; protected: - bave::NotNull m_layout; + bave::NotNull m_display; Config m_config{}; bave::RoundedQuadShape m_shape{}; diff --git a/src/spaced/spaced/game/world.cpp b/src/spaced/spaced/game/world.cpp index 9e55db6..4607c08 100644 --- a/src/spaced/spaced/game/world.cpp +++ b/src/spaced/spaced/game/world.cpp @@ -1,7 +1,7 @@ #include +#include #include #include -#include #include #include @@ -11,26 +11,29 @@ namespace spaced { using bave::FixedString; +using bave::IAudio; using bave::NotNull; using bave::ParticleEmitter; using bave::random_in_range; +using bave::Resources; using bave::Seconds; +using bave::Services; using bave::Shader; namespace { [[nodiscard]] auto make_player_controller(Services const& services) { auto ret = std::make_unique(services); if constexpr (bave::platform_v == bave::Platform::eAndroid) { ret->set_type(PlayerController::Type::eTouch); } - auto const& layout = services.get(); - auto const half_size = 0.5f * layout.get_player_size(); - auto const play_area = layout.get_play_area(); + auto const& layout = services.get(); + auto const half_size = 0.5f * layout.player_size; + auto const play_area = layout.play_area; ret->max_y = play_area.lt.y - half_size.y; ret->min_y = play_area.rb.y + half_size.y; return ret; } [[nodiscard]] auto make_auto_controller(ITargetProvider const& target_provider, Services const& services) { - return std::make_unique(&target_provider, services.get().get_player_x()); + return std::make_unique(&target_provider, services.get().player_x); } } // namespace diff --git a/src/spaced/spaced/game/world.hpp b/src/spaced/spaced/game/world.hpp index 46cf622..24720c9 100644 --- a/src/spaced/spaced/game/world.hpp +++ b/src/spaced/spaced/game/world.hpp @@ -4,13 +4,16 @@ #include #include -namespace spaced { +namespace bave { struct Resources; +} + +namespace spaced { struct Stats; class World : public ITargetProvider { public: - explicit World(bave::NotNull services, bave::NotNull scorer); + explicit World(bave::NotNull services, bave::NotNull scorer); [[nodiscard]] auto get_targets() const -> std::span const> final { return m_targets; } @@ -32,9 +35,9 @@ class World : public ITargetProvider { void debug_controller_type(); void debug_spawn_powerup(glm::vec2 position); - bave::NotNull m_services; - bave::NotNull m_resources; - bave::NotNull m_audio; + bave::NotNull m_services; + bave::NotNull m_resources; + bave::NotNull m_audio; bave::NotNull m_stats; bave::NotNull m_scorer; diff --git a/src/spaced/spaced/prefs.cpp b/src/spaced/spaced/prefs.cpp index da68d6d..223346f 100644 --- a/src/spaced/spaced/prefs.cpp +++ b/src/spaced/spaced/prefs.cpp @@ -1,16 +1,21 @@ #include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include namespace spaced { using bave::App; +using bave::IAudio; using bave::NotNull; using bave::Persistor; +using bave::Services; +using bave::Styles; + +namespace ui = bave::ui; namespace { constexpr std::string_view uri_v{"spaced/prefs.json"}; diff --git a/src/spaced/spaced/prefs.hpp b/src/spaced/spaced/prefs.hpp index be0863d..ce99338 100644 --- a/src/spaced/spaced/prefs.hpp +++ b/src/spaced/spaced/prefs.hpp @@ -1,10 +1,9 @@ #pragma once #include -#include +#include +#include namespace spaced { -class IAudio; - struct Prefs { class View; @@ -15,19 +14,19 @@ struct Prefs { void save(bave::App const& app) const; }; -class Prefs::View : public ui::View { +class Prefs::View : public bave::ui::View { public: View(View const&) = delete; View(View&&) = delete; auto operator=(View const&) = delete; auto operator=(View&&) = delete; - explicit View(bave::NotNull app, Services const& services); + explicit View(bave::NotNull app, bave::Services const& services); ~View() override; private: bave::NotNull m_app; - bave::NotNull m_audio; + bave::NotNull m_audio; Prefs m_prefs; }; } // namespace spaced diff --git a/src/spaced/spaced/resource_map.hpp b/src/spaced/spaced/resource_map.hpp deleted file mode 100644 index fb44e4b..0000000 --- a/src/spaced/spaced/resource_map.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace spaced { -class ResourceMap { - public: - template - auto add(std::string uri, std::shared_ptr resource) { - if (uri.empty() || !resource) { return; } - m_resources.insert_or_assign(std::move(uri), std::make_unique>(std::move(resource))); - } - - [[nodiscard]] auto contains(std::string_view const uri) const -> bool { return m_resources.contains(uri); } - - template - [[nodiscard]] auto contains(std::string_view const uri) const -> bool { - if (uri.empty()) { return false; } - auto const it = m_resources.find(uri); - if (it == m_resources.end()) { return false; } - return it->second->type_index == typeid(Type); - } - - template - [[nodiscard]] auto get(std::string_view const uri, std::shared_ptr const& fallback = {}) const -> std::shared_ptr { - if (uri.empty()) { return fallback; } - auto const it = m_resources.find(uri); - if (it == m_resources.end()) { return fallback; } - auto const& resource = it->second; - if (resource->type_index != typeid(Type)) { return fallback; } - return static_cast const&>(*it->second).resource; - } - - void clear() { m_resources.clear(); } - - [[nodiscard]] auto size() const -> std::size_t { return m_resources.size(); } - - private: - struct Base : bave::Polymorphic { - std::type_index type_index; - explicit Base(std::type_index type_index) : type_index(type_index) {} - }; - - template - struct Model : Base { - std::shared_ptr resource; - explicit Model(std::shared_ptr t) : Base(typeid(T)), resource(std::move(t)) {} - }; - - StringMap> m_resources{}; -}; -} // namespace spaced diff --git a/src/spaced/spaced/scene.cpp b/src/spaced/spaced/scene.cpp deleted file mode 100644 index a339c55..0000000 --- a/src/spaced/spaced/scene.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include - -namespace spaced { -using bave::App; -using bave::KeyInput; -using bave::PointerMove; -using bave::PointerTap; -using bave::Seconds; - -Scene::Scene(App& app, Services const& services, std::string name) : m_log{std::move(name)}, m_app(app), m_services(services) { m_log.info("constructed"); } - -void Scene::on_key_event(KeyInput const& key_input) { on_key(key_input); } - -void Scene::on_focus_event(bave::FocusChange const& focus_change) { on_focus(focus_change); } - -void Scene::on_move_event(PointerMove const& pointer_move) { - if (on_ui_event([pointer_move](ui::View& view) { view.on_move(pointer_move); })) { return; } - on_move(pointer_move); -} - -void Scene::on_tap_event(PointerTap const& pointer_tap) { - if (on_ui_event([pointer_tap](ui::View& view) { view.on_tap(pointer_tap); })) { return; } - on_tap(pointer_tap); -} - -void Scene::on_scroll_event(bave::MouseScroll const& mouse_scroll) { on_scroll(mouse_scroll); } - -auto Scene::is_ui_blocking_input() const -> bool { - return std::any_of(m_views.begin(), m_views.end(), [](auto const& view) { return view->block_input_events; }); -} - -void Scene::push_view(std::unique_ptr view) { - if (!view || view->is_destroyed()) { return; } - m_views.push_back(std::move(view)); -} - -void Scene::tick_frame(Seconds const dt) { - tick(dt); - for (auto const& view : cache_views()) { view->tick(dt); } - std::erase_if(m_views, [](auto const& view) { return view->is_destroyed(); }); -} - -void Scene::render_frame() const { - auto shader = get_app().load_shader("shaders/default.vert", "shaders/default.frag"); - if (!shader) { return; } - render(*shader); - for (auto const& view : m_views) { view->render(*shader); } -} - -template -auto Scene::on_ui_event(F per_view) -> bool { - auto const cached_views = cache_views(); - for (auto it = cached_views.rbegin(); it != cached_views.rend(); ++it) { - auto const& view = *it; - per_view(*view); - if (view->block_input_events) { return true; } - } - return false; -} - -auto Scene::cache_views() -> std::span const> { - m_cached_views.clear(); - m_cached_views.reserve(m_views.size()); - for (auto const& view : m_views) { m_cached_views.push_back(view.get()); } - return m_cached_views; -} -} // namespace spaced diff --git a/src/spaced/spaced/scene.hpp b/src/spaced/spaced/scene.hpp deleted file mode 100644 index 77acfcd..0000000 --- a/src/spaced/spaced/scene.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace spaced { -class Scene : public bave::PolyPinned { - public: - explicit Scene(bave::App& app, Services const& services, std::string name = "Scene"); - - void on_focus_event(bave::FocusChange const& focus_change); - void on_key_event(bave::KeyInput const& key_input); - void on_move_event(bave::PointerMove const& pointer_move); - void on_tap_event(bave::PointerTap const& pointer_tap); - void on_scroll_event(bave::MouseScroll const& mouse_scroll); - void tick_frame(bave::Seconds dt); - void render_frame() const; - - [[nodiscard]] virtual auto get_music_uri() const -> std::string_view { return {}; } - - [[nodiscard]] auto get_app() const -> bave::App& { return m_app; } - [[nodiscard]] auto get_services() const -> Services const& { return m_services; } - - [[nodiscard]] auto is_ui_blocking_input() const -> bool; - - [[nodiscard]] auto make_loader() const -> bave::Loader { return bave::Loader{&m_app.get_data_store(), &m_app.get_render_device()}; } - - void push_view(std::unique_ptr view); - - bave::Rgba clear_colour{bave::black_v}; - - protected: - virtual void on_focus(bave::FocusChange const& /*focus_change*/) {} - virtual void on_resize(bave::WindowResize const& /*window_resize*/) {} - virtual void on_resize(bave::FramebufferResize const& /*framebuffer_resize*/) {} - virtual void on_key(bave::KeyInput const& /*key_input*/) {} - virtual void on_char(bave::CharInput const& /*char_input*/) {} - virtual void on_tap(bave::PointerTap const& /*pointer_tap*/) {} - virtual void on_move(bave::PointerMove const& /*pointer_move*/) {} - virtual void on_scroll(bave::MouseScroll const& /*mouse_scroll*/) {} - virtual void on_drop(std::span /*paths*/) {} - - virtual void tick(bave::Seconds /*dt*/) {} - virtual void render(bave::Shader& /*shader*/) const {} - - bave::Logger m_log{}; - - private: - template - auto on_ui_event(F per_view) -> bool; - - auto cache_views() -> std::span const>; - - bave::App& m_app; - Services const& m_services; - std::vector> m_views{}; - std::vector> m_cached_views{}; -}; -} // namespace spaced diff --git a/src/spaced/spaced/scenes/game.cpp b/src/spaced/spaced/scenes/game.cpp index 142d639..5ab679d 100644 --- a/src/spaced/spaced/scenes/game.cpp +++ b/src/spaced/spaced/scenes/game.cpp @@ -1,13 +1,13 @@ #include #include +#include +#include +#include +#include #include #include #include -#include #include -#include -#include -#include namespace spaced { using bave::Action; @@ -21,7 +21,11 @@ using bave::PointerMove; using bave::PointerTap; using bave::Ptr; using bave::Seconds; +using bave::Services; using bave::Shader; +using bave::Styles; + +namespace ui = bave::ui; auto GameScene::get_manifest() -> AssetManifest { return AssetManifest{ @@ -54,9 +58,7 @@ GameScene::GameScene(App& app, Services const& services) : Scene(app, services, void GameScene::on_focus(FocusChange const& focus_change) { m_world.player.on_focus(focus_change); } void GameScene::on_key(KeyInput const& key_input) { - if (key_input.key == Key::eEscape && key_input.action == Action::eRelease && key_input.mods == KeyMods{}) { - get_services().get().switch_to(); - } + if (key_input.key == Key::eEscape && key_input.action == Action::eRelease && key_input.mods == KeyMods{}) { get_switcher().switch_to(); } } void GameScene::on_move(PointerMove const& pointer_move) { m_world.player.on_move(pointer_move); } @@ -84,7 +86,7 @@ void GameScene::on_game_over() { auto dci = ui::DialogCreateInfo{ .size = {600.0f, 200.0f}, .content_text = "GAME OVER", - .main_button = {.text = "RESTART", .callback = [this] { get_services().get().switch_to(); }}, + .main_button = {.text = "RESTART", .callback = [this] { get_switcher().switch_to(); }}, .second_button = {.text = "QUIT", .callback = [this] { get_app().shutdown(); }}, }; @@ -122,7 +124,7 @@ void GameScene::inspect(Seconds const dt, Seconds const frame_time) { ImGui::Checkbox("fps lock", &m_debug.fps.lock); ImGui::Separator(); - if (ImGui::Button("reload scene")) { get_services().get().switch_to(); } + if (ImGui::Button("reload scene")) { get_switcher().switch_to(); } } ImGui::End(); diff --git a/src/spaced/spaced/scenes/game.hpp b/src/spaced/spaced/scenes/game.hpp index 3bd14d8..4566bb2 100644 --- a/src/spaced/spaced/scenes/game.hpp +++ b/src/spaced/spaced/scenes/game.hpp @@ -1,18 +1,18 @@ #pragma once +#include #include #include #include #include #include #include -#include namespace spaced { -class GameScene : public Scene, public IScorer { +class GameScene : public bave::Scene, public IScorer { public: static auto get_manifest() -> AssetManifest; - GameScene(bave::App& app, Services const& services); + GameScene(bave::App& app, bave::Services const& services); private: void on_focus(bave::FocusChange const& focus_change) final; diff --git a/src/spaced/spaced/scenes/load_assets.cpp b/src/spaced/spaced/scenes/load_assets.cpp index ec6e481..5482362 100644 --- a/src/spaced/spaced/scenes/load_assets.cpp +++ b/src/spaced/spaced/scenes/load_assets.cpp @@ -1,16 +1,17 @@ +#include +#include #include #include #include #include -#include -#include #include namespace spaced { using bave::App; +using bave::AsyncExec; using bave::Loader; -using bave::Seconds; -using bave::Shader; +using bave::Resources; +using bave::Services; namespace { auto make_load_stages(Loader loader, Services const& services) -> std::vector { @@ -24,18 +25,9 @@ auto make_load_stages(Loader loader, Services const& services) -> std::vector().switch_to(); } +auto LoadAssets::build_load_stages() -> std::vector { return make_load_stages(make_loader(), get_services()); } -void LoadAssets::tick(Seconds const dt) { - auto const load_status = m_load.update(); - auto const progress = load_status.progress(); - m_loading_screen.update(dt, progress); - - if (load_status.is_complete()) { on_loaded(); } -} - -void LoadAssets::render(Shader& shader) const { m_loading_screen.draw(shader); } +void LoadAssets::on_loaded() { get_switcher().switch_to(); } } // namespace spaced diff --git a/src/spaced/spaced/scenes/load_assets.hpp b/src/spaced/spaced/scenes/load_assets.hpp index 95cc0c3..4a0f265 100644 --- a/src/spaced/spaced/scenes/load_assets.hpp +++ b/src/spaced/spaced/scenes/load_assets.hpp @@ -1,20 +1,13 @@ #pragma once -#include -#include -#include +#include namespace spaced { -class LoadAssets : public Scene { +class LoadAssets : public bave::Scene { public: - explicit LoadAssets(bave::App& app, Services const& services); + explicit LoadAssets(bave::App& app, bave::Services const& services); private: - void on_loaded(); - - void tick(bave::Seconds dt) final; - void render(bave::Shader& shader) const final; - - ui::LoadingScreen m_loading_screen; - AsyncExec m_load; + auto build_load_stages() -> std::vector final; + void on_loaded() final; }; } // namespace spaced diff --git a/src/spaced/spaced/scenes/menu.cpp b/src/spaced/spaced/scenes/menu.cpp index 650c229..d1d5d83 100644 --- a/src/spaced/spaced/scenes/menu.cpp +++ b/src/spaced/spaced/scenes/menu.cpp @@ -1,19 +1,22 @@ +#include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include #include namespace spaced { using bave::App; using bave::Seconds; +using bave::Services; using bave::TextHeight; +namespace ui = bave::ui; + auto MenuScene::get_text_heights() -> std::vector { return {TextHeight{100}, TextHeight{60}, ui::Dialog::text_height_v}; } MenuScene::MenuScene(App& app, Services const& services) : Scene(app, services, "Home") { create_ui(); } @@ -27,7 +30,7 @@ void MenuScene::create_ui() { auto start = std::make_unique(get_services()); start->set_text("start"); start->set_position({0.0f, -100.0f}); - start->callback = [this]() { get_services().get().switch_to(); }; + start->callback = [this]() { get_switcher().switch_to(); }; auto options = std::make_unique(get_services()); options->set_text("options"); diff --git a/src/spaced/spaced/scenes/menu.hpp b/src/spaced/spaced/scenes/menu.hpp index bfc7694..ec5e437 100644 --- a/src/spaced/spaced/scenes/menu.hpp +++ b/src/spaced/spaced/scenes/menu.hpp @@ -1,12 +1,12 @@ #pragma once -#include +#include namespace spaced { -class MenuScene : public Scene { +class MenuScene : public bave::Scene { public: static auto get_text_heights() -> std::vector; - explicit MenuScene(bave::App& app, Services const& services); + explicit MenuScene(bave::App& app, bave::Services const& services); private: void create_ui(); diff --git a/src/spaced/spaced/services/audio.hpp b/src/spaced/spaced/services/audio.hpp deleted file mode 100644 index abe1f90..0000000 --- a/src/spaced/spaced/services/audio.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace spaced { -class IAudio : public IService { - public: - [[nodiscard]] virtual auto get_sfx_gain() const -> float = 0; - virtual void set_sfx_gain(float gain) = 0; - - [[nodiscard]] virtual auto get_music_gain() const -> float = 0; - virtual void set_music_gain(float gain) = 0; - - virtual void play_sfx(std::string_view uri) = 0; - virtual void play_music(std::string_view uri, bave::Seconds crossfade = 1s) = 0; - virtual void stop_music() = 0; - - void play_any_sfx(std::span uris) { - if (uris.empty()) { return; } - if (uris.size() == 1) { return play_sfx(uris.front()); } - auto const index = bave::random_in_range(std::size_t{}, uris.size() - 1); - play_sfx(uris[index]); - } -}; -} // namespace spaced diff --git a/src/spaced/spaced/services/gamepad_provider.hpp b/src/spaced/spaced/services/gamepad_provider.hpp index 50e7711..11d9dde 100644 --- a/src/spaced/spaced/services/gamepad_provider.hpp +++ b/src/spaced/spaced/services/gamepad_provider.hpp @@ -1,9 +1,9 @@ #pragma once #include -#include +#include namespace spaced { -class IGamepadProvider : public IService { +class IGamepadProvider : public bave::IService { public: [[nodiscard]] virtual auto get_gamepad() const -> bave::Gamepad const& = 0; }; diff --git a/src/spaced/spaced/services/layout.hpp b/src/spaced/spaced/services/layout.hpp index c33691a..61d8b69 100644 --- a/src/spaced/spaced/services/layout.hpp +++ b/src/spaced/spaced/services/layout.hpp @@ -1,20 +1,14 @@ #pragma once -#include -#include +#include +#include namespace spaced { -class ILayout : public IService { - public: - [[nodiscard]] virtual auto get_main_view() const -> bave::RenderView const& = 0; - [[nodiscard]] virtual auto get_framebuffer_size() const -> glm::vec2 = 0; - [[nodiscard]] virtual auto get_world_space() const -> glm::vec2 = 0; - [[nodiscard]] virtual auto get_play_area() const -> bave::Rect<> = 0; - [[nodiscard]] virtual auto get_hud_area() const -> bave::Rect<> = 0; - [[nodiscard]] virtual auto project_to_world(glm::vec2 fb_point) const -> glm::vec2 = 0; - [[nodiscard]] virtual auto unproject(glm::vec2 pointer) const -> glm::vec2 = 0; - [[nodiscard]] virtual auto get_player_x() const -> float = 0; - [[nodiscard]] virtual auto get_player_size() const -> glm::vec2 = 0; +struct Layout : bave::IService { + glm::vec2 world_space{}; + bave::Rect<> play_area{}; + bave::Rect<> hud_area{}; - virtual void set_framebuffer_size(glm::vec2 size) = 0; + float player_x{-700.0f}; + glm::vec2 player_size{100.0f}; }; } // namespace spaced diff --git a/src/spaced/spaced/services/resources.hpp b/src/spaced/spaced/services/resources.hpp deleted file mode 100644 index cdd9089..0000000 --- a/src/spaced/spaced/services/resources.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace spaced { -struct Resources : ResourceMap, IService { - std::shared_ptr main_font{}; - std::shared_ptr spinner{}; -}; -} // namespace spaced diff --git a/src/spaced/spaced/services/scene_switcher.hpp b/src/spaced/spaced/services/scene_switcher.hpp deleted file mode 100644 index 3e26897..0000000 --- a/src/spaced/spaced/services/scene_switcher.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include -#include - -namespace spaced { -class ISceneSwitcher : public IService { - public: - virtual void switch_to_scene(std::unique_ptr new_scene) = 0; - - template T, typename... Args> - requires(std::constructible_from) - void switch_to(Args&&... args) { - switch_to_scene(std::make_unique(get_app(), get_services(), std::forward(args)...)); - } - - private: - [[nodiscard]] virtual auto get_app() const -> bave::App& = 0; - [[nodiscard]] virtual auto get_services() const -> Services const& = 0; -}; -} // namespace spaced diff --git a/src/spaced/spaced/services/serializer.hpp b/src/spaced/spaced/services/serializer.hpp index 206f12f..b636c7d 100644 --- a/src/spaced/spaced/services/serializer.hpp +++ b/src/spaced/spaced/services/serializer.hpp @@ -1,8 +1,8 @@ #pragma once #include #include +#include #include -#include #include #include #include @@ -13,7 +13,7 @@ namespace spaced { template concept SerializableT = std::derived_from; -class Serializer : public IService { +class Serializer : public bave::IService { public: using Factory = std::function()>; diff --git a/src/spaced/spaced/services/service.hpp b/src/spaced/spaced/services/service.hpp deleted file mode 100644 index 653cd52..0000000 --- a/src/spaced/spaced/services/service.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include - -namespace spaced { -/// \brief Base class for all services. -class IService : public bave::Polymorphic {}; -} // namespace spaced diff --git a/src/spaced/spaced/services/services.hpp b/src/spaced/spaced/services/services.hpp deleted file mode 100644 index 4c6b43f..0000000 --- a/src/spaced/spaced/services/services.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -namespace spaced { -/// \brief Concept constraining Type to a subclass of IService. -template -concept ServiceT = std::derived_from; - -/// \brief Container of stored services. -/// -/// Intended usage: -/// 1. Own an instance in main / app Driver. -/// 2. Bind services to subclasses. (From and To being the same type is also OK.) -/// 3. Pass a const reference of Services to dependencies -/// Point 3 ensures dependencies cannot bind new / remove existing services, -/// but can locate and use already bound ones. -class Services { - public: - /// \brief Bind a service instance to a type (From). - /// \param service Concrete instance of service to bind. - /// \pre service must not be null, From must not already be bound. - template To> - void bind(std::unique_ptr service) { - if (!service) { throw std::runtime_error{"Attempt to bind null service"}; } - static auto const index = std::type_index{typeid(From)}; - auto lock = std::scoped_lock{m_mutex}; - if (m_services.contains(index)) { throw std::runtime_error{"Attempt to bind duplicate service"}; } - m_services.insert_or_assign(index, std::move(service)); - } - - /// \brief Remove a bound service instance. Type need not actually be bound. - template - void remove() { - static auto const index = std::type_index{typeid(Type)}; - auto lock = std::scoped_lock{m_mutex}; - m_services.erase(index); - } - - /// \brief Remove all bound service instances. - void remove_all() { - auto lock = std::scoped_lock{m_mutex}; - m_services.clear(); - } - - /// \brief Check if a service is bound. - /// \returns true if bound. - template - [[nodiscard]] auto contains() const -> bool { - return find() != nullptr; - } - - /// \brief Locate a service instance if bound. - /// \returns Pointer to service instance if bound, else nullptr. - template - [[nodiscard]] auto find() const -> bave::Ptr { - static auto const index = std::type_index{typeid(Type)}; - auto lock = std::scoped_lock{m_mutex}; - if (auto const it = m_services.find(index); it != m_services.end()) { return static_cast(it->second.get()); } - return {}; - } - - /// \brief Obtain a bound service. - /// \returns Mutable reference to bound service. - /// \pre Type must be bound. - template - [[nodiscard]] auto get() const -> Type& { - auto ret = find(); - if (!ret) { throw std::runtime_error{"Service not found"}; } - return *ret; - } - - /// \brief Obtain the count of bound services. - /// \returns Count of bound services. - [[nodiscard]] auto size() const -> std::size_t { - auto lock = std::scoped_lock{m_mutex}; - return m_services.size(); - } - - private: - std::unordered_map> m_services{}; - mutable std::mutex m_mutex{}; -}; -} // namespace spaced diff --git a/src/spaced/spaced/services/stats.hpp b/src/spaced/spaced/services/stats.hpp index 682901f..ed4d037 100644 --- a/src/spaced/spaced/services/stats.hpp +++ b/src/spaced/spaced/services/stats.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include namespace dj { @@ -7,7 +7,7 @@ class Json; } namespace spaced { -struct Stats : IService { +struct Stats : bave::IService { struct { std::int64_t play_count{}; } game{}; diff --git a/src/spaced/spaced/services/styles.cpp b/src/spaced/spaced/services/styles.cpp deleted file mode 100644 index f2065d9..0000000 --- a/src/spaced/spaced/services/styles.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include - -namespace spaced { -namespace { -using bave::from_json; -using bave::to_json; -using util::from_json; -using util::to_json; - -template -void load_styles(StringMap& out, dj::Json const& json) { - for (auto const& [id, in_style] : json.object_view()) { - if (id.empty()) { continue; } - auto out_style = Type{}; - from_json(in_style, out_style); - out.insert_or_assign(std::string{id}, out_style); - } -} - -template -void save_styles(StringMap const& styles, dj::Json& out, std::string_view const key) { - auto out_styles = dj::Json{}; - for (auto const& [id, button_style] : styles) { - if (id.empty()) { continue; } - to_json(out_styles[id], button_style); - } - if (out_styles) { out[key] = std::move(out_styles); } -} -} // namespace - -auto Styles::load(dj::Json const& json) -> Styles { - auto ret = Styles{}; - load_styles(ret.rgbas, json["rgbas"]); - load_styles(ret.buttons, json["buttons"]); - load_styles(ret.progress_bars, json["progress_bars"]); - load_styles(ret.dialogs, json["dialogs"]); - load_styles(ret.sliders, json["sliders"]); - if (auto const& loading_screen = json["loading_screen"]) { from_json(loading_screen, ret.loading_screen); } - return ret; -} - -auto Styles::save() const -> dj::Json { - auto ret = dj::Json{}; - save_styles(rgbas, ret, "rgbas"); - save_styles(buttons, ret, "buttons"); - save_styles(progress_bars, ret, "progress_bars"); - save_styles(dialogs, ret, "dialogs"); - save_styles(sliders, ret, "sliders"); - to_json(ret["loading_screen"], loading_screen); - return ret; -} -} // namespace spaced diff --git a/src/spaced/spaced/services/styles.hpp b/src/spaced/spaced/services/styles.hpp deleted file mode 100644 index 32a8d8a..0000000 --- a/src/spaced/spaced/services/styles.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include -#include -#include - -namespace dj { -class Json; -} - -namespace spaced { -struct Styles : IService { - StringMap rgbas{}; - StringMap buttons{}; - StringMap progress_bars{}; - StringMap dialogs{}; - StringMap sliders{}; - ui::LoadingScreenStyle loading_screen{}; - - static auto load(dj::Json const& json) -> Styles; - - [[nodiscard]] auto save() const -> dj::Json; -}; -} // namespace spaced diff --git a/src/spaced/spaced/spaced.cpp b/src/spaced/spaced/spaced.cpp index 21ddd17..7db77e3 100644 --- a/src/spaced/spaced/spaced.cpp +++ b/src/spaced/spaced/spaced.cpp @@ -2,16 +2,15 @@ #include #include #include +#include +#include +#include #include #include -#include #include #include -#include -#include #include #include -#include #include namespace spaced { @@ -21,17 +20,17 @@ using bave::AudioClip; using bave::AudioDevice; using bave::AudioStreamer; using bave::Gamepad; -using bave::KeyInput; +using bave::IAudio; +using bave::IDisplay; using bave::Loader; -using bave::MouseScroll; using bave::NotNull; using bave::Persistor; -using bave::PointerMove; -using bave::PointerTap; using bave::Rect; using bave::RenderDevice; using bave::RenderView; +using bave::Resources; using bave::Seconds; +using bave::Styles; struct GamepadProvider : IGamepadProvider { bave::App& app; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) @@ -41,63 +40,6 @@ struct GamepadProvider : IGamepadProvider { [[nodiscard]] auto get_gamepad() const -> Gamepad const& final { return app.get_most_recent_gamepad(); } }; -struct Layout : ILayout { - NotNull render_device; - RenderView main_view{}; - glm::vec2 framebuffer_size{}; - Rect<> play_area{}; - Rect<> hud_area{}; - - explicit Layout(NotNull render_device) : render_device(render_device) {} - - [[nodiscard]] auto get_main_view() const -> RenderView const& final { return main_view; } - [[nodiscard]] auto get_framebuffer_size() const -> glm::vec2 final { return framebuffer_size; } - [[nodiscard]] auto get_world_space() const -> glm::vec2 final { return main_view.viewport; } - [[nodiscard]] auto get_play_area() const -> bave::Rect<> final { return play_area; } - [[nodiscard]] auto get_hud_area() const -> bave::Rect<> final { return hud_area; } - - [[nodiscard]] auto project_to_world(glm::vec2 fb_point) const -> glm::vec2 final { return render_device->project_to(get_world_space(), fb_point); } - - [[nodiscard]] auto unproject(glm::vec2 const pointer) const -> glm::vec2 final { - if (!bave::is_positive(framebuffer_size)) { return pointer; } - return main_view.unproject(pointer / framebuffer_size); - } - - [[nodiscard]] auto get_player_x() const -> float final { return -700.0f; } - [[nodiscard]] auto get_player_size() const -> glm::vec2 final { return glm::vec2{100.0f}; } - - void set_framebuffer_size(glm::vec2 const size) final { framebuffer_size = size; } -}; - -struct Audio : IAudio { - NotNull audio_device; - NotNull audio_streamer; - NotNull resources; - - explicit Audio(NotNull audio_device, NotNull audio_streamer, NotNull resources) - : audio_device(audio_device), audio_streamer(audio_streamer), resources(resources) {} - - [[nodiscard]] auto get_sfx_gain() const -> float final { return audio_device->sfx_gain; } - void set_sfx_gain(float const gain) final { audio_device->sfx_gain = gain; } - - [[nodiscard]] auto get_music_gain() const -> float final { return audio_streamer->gain; } - void set_music_gain(float const gain) final { audio_streamer->gain = gain; } - - void play_sfx(std::string_view const uri) final { - auto const clip = resources->get(uri); - if (!clip) { return; } - audio_device->play_once(*clip); - } - - void play_music(std::string_view const uri, Seconds const crossfade) final { - auto const clip = resources->get(uri); - if (!clip) { return; } - audio_streamer->play(clip, crossfade); - } - - void stop_music() final { audio_streamer->stop(); } -}; - struct PersistentStats : Stats { static constexpr std::string_view uri_v{"spaced/stats.json"}; @@ -124,22 +66,9 @@ struct PersistentStats : Stats { }; } // namespace -struct SceneSwitcher : ISceneSwitcher { - App& app; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) - Services const& services; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) - std::unique_ptr next_scene{}; - - explicit SceneSwitcher(App& app, Services const& services) : app(app), services(services) {} - - void switch_to_scene(std::unique_ptr new_scene) final { next_scene = std::move(new_scene); } - - [[nodiscard]] auto get_app() const -> App& final { return app; } - [[nodiscard]] auto get_services() const -> Services const& final { return services; } -}; - void Spaced::set_bindings([[maybe_unused]] Serializer& serializer) {} -Spaced::Spaced(App& app) : Driver(app), m_scene(std::make_unique(app, m_services)) { +Spaced::Spaced(App& app) : GameDriver(app) { m_log.info("using MSAA: {}x", static_cast(app.get_render_device().get_sample_count())); load_resources(); set_layout(); @@ -148,39 +77,11 @@ Spaced::Spaced(App& app) : Driver(app), m_scene(std::make_unique(app, m_s set_scene(); } -void Spaced::on_focus(bave::FocusChange const& focus_change) { m_scene->on_focus_event(focus_change); } - -void Spaced::on_key(KeyInput const& key_input) { m_scene->on_key_event(key_input); } - -void Spaced::on_move(PointerMove const& pointer_move) { m_scene->on_move_event(pointer_move); } - -void Spaced::on_tap(PointerTap const& pointer_tap) { m_scene->on_tap_event(pointer_tap); } - -void Spaced::on_scroll(MouseScroll const& mouse_scroll) { m_scene->on_scroll_event(mouse_scroll); } - -void Spaced::tick() { - auto const dt = get_app().get_dt(); - m_layout->set_framebuffer_size(get_app().get_framebuffer_size()); - - if (m_scene_switcher->next_scene) { - switch_track(m_scene->get_music_uri(), m_scene_switcher->next_scene->get_music_uri()); - m_scene = std::move(m_scene_switcher->next_scene); - } - - m_scene->tick_frame(dt); - - clear_colour = m_scene->clear_colour; -} - -void Spaced::render() const { m_scene->render_frame(); } - void Spaced::load_resources() { auto const loader = Loader{&get_app().get_data_store(), &get_app().get_render_device()}; - auto resources = std::make_unique(); - resources->main_font = loader.load_font("fonts/hesitation.regular.ttf"); - resources->spinner = loader.load_texture("images/spinner.png", true); - m_resources = resources.get(); - m_services.bind(std::move(resources)); + m_resources = &m_services.get(); + m_resources->main_font = loader.load_font("fonts/CuteDino.otf"); + m_resources->spinner = loader.load_texture("images/spinner.png", true); auto styles = std::make_unique(); if (auto const json = loader.load_json("styles.json")) { @@ -198,22 +99,6 @@ void Spaced::load_resources() { m_services.bind(std::move(styles)); } -void Spaced::set_layout() { - auto const& app = get_app(); - auto layout = std::make_unique(&app.get_render_device()); - m_layout = layout.get(); - layout->main_view = app.get_render_device().get_default_view(); - layout->main_view.viewport = app.get_render_device().get_viewport_scaler().match_height({1920.0f, 1080.0f}); - layout->framebuffer_size = app.get_framebuffer_size(); - auto const hud_size = glm::vec2{layout->main_view.viewport.x, 100.0f}; - auto const hud_origin = glm::vec2{0.0f, 0.5f * (layout->main_view.viewport.y - hud_size.y)}; - layout->hud_area = Rect<>::from_size(hud_size, hud_origin); - auto const play_size = glm::vec2{hud_size.x, layout->main_view.viewport.y - hud_size.y}; - auto const play_origin = glm::vec2{0.0f, -0.5f * (layout->main_view.viewport.y - play_size.y)}; - layout->play_area = Rect<>::from_size(play_size, play_origin); - m_services.bind(std::move(layout)); -} - void Spaced::create_services() { auto serializer = std::make_unique(); set_bindings(*serializer); @@ -221,33 +106,31 @@ void Spaced::create_services() { m_services.bind(std::make_unique(get_app())); - auto audio = std::make_unique