From fce37403bbc29521b2b5bd983291b3730f8ad7b4 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sat, 13 Mar 2021 12:24:05 -0500 Subject: Added submenus #7 --- res/sfx/menu_deselect.wav | Bin 0 -> 29480 bytes src/menu.cpp | 23 ++++++++--- src/menu.h | 19 +++++++++- src/menu_system.cpp | 95 +++++++++++++++++++++++++++++----------------- src/menu_system.h | 24 +++++++++--- src/renderer.cpp | 26 +++++++++---- src/renderer.h | 3 +- 7 files changed, 137 insertions(+), 53 deletions(-) create mode 100644 res/sfx/menu_deselect.wav diff --git a/res/sfx/menu_deselect.wav b/res/sfx/menu_deselect.wav new file mode 100644 index 0000000..800f84f Binary files /dev/null and b/res/sfx/menu_deselect.wav differ diff --git a/src/menu.cpp b/src/menu.cpp index 4da4574..cfb0dd6 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -1,12 +1,25 @@ #include "menu.h" -std::vector CreateMenu(const std::vector& builders) { - std::vector result; - result.reserve(builders.size()); +Menu::Menu(const std::vector& builders) { + items_.reserve(builders.size()); for (const MenuBuilder& builder : builders) { - result.push_back(builder.Build()); + items_.push_back(builder.Build()); } +} + +void Menu::moveCursorUp() { + cursor_--; - return result; + if (cursor_ < 0) { + cursor_ = items_.size() - 1; + } +} + +void Menu::moveCursorDown() { + cursor_++; + + if (cursor_ >= items_.size()) { + cursor_ = 0; + } } diff --git a/src/menu.h b/src/menu.h index 528f8c8..67c75c0 100644 --- a/src/menu.h +++ b/src/menu.h @@ -48,6 +48,23 @@ private: MenuItem result_; }; -std::vector CreateMenu(const std::vector& builders); +class Menu { +public: + + explicit Menu(const std::vector& builders); + + const std::vector& getItems() const { return items_; } + + int getCursorPosition() const { return cursor_; } + + void moveCursorUp(); + + void moveCursorDown(); + +private: + + std::vector items_; + int cursor_ = 0; +}; #endif /* end of include guard: MENU_H_3F6E62B3 */ diff --git a/src/menu_system.cpp b/src/menu_system.cpp index 7631e4d..7ac8af5 100644 --- a/src/menu_system.cpp +++ b/src/menu_system.cpp @@ -4,10 +4,12 @@ void MenuSystem::tick(double dt) { pauseAnimation_.tick(dt); + menuChangeAnimation_.tick(dt); if (openState_ == OpenState::Animating && pauseAnimation_.isComplete()) { if (pauseAnimation_.getProgress() == 0.0) { openState_ = OpenState::Closed; + menus_.clear(); game_.unpauseGameplay(); game_.getMixer().unpauseSounds(); @@ -15,20 +17,28 @@ void MenuSystem::tick(double dt) { openState_ = OpenState::Open; } } else if (openState_ == OpenState::Open) { - cursorBobTimer_.accumulate(dt); - while (cursorBobTimer_.step()) { - if (cursorBobDown_) { - cursorBob_++; - - if (cursorBob_ >= 4) { - cursorBobDown_ = false; + if (!isMenuChanging_) { + cursorBobTimer_.accumulate(dt); + while (cursorBobTimer_.step()) { + if (cursorBobDown_) { + cursorBob_++; + + if (cursorBob_ >= 4) { + cursorBobDown_ = false; + } + } else { + cursorBob_--; + + if (cursorBob_ <= 0) { + cursorBobDown_ = true; + } } - } else { - cursorBob_--; + } + } else if (menuChangeAnimation_.isComplete()) { + isMenuChanging_ = false; - if (cursorBob_ <= 0) { - cursorBobDown_ = true; - } + if (menuChangeAnimation_.getProgress() == 0.0) { + menus_.pop_back(); } } } @@ -41,7 +51,16 @@ void MenuSystem::openPauseMenu() { game_.pauseGameplay(); std::vector builders = { - MenuBuilder().Command("Settings"), + MenuBuilder().Command("Settings") + .ActivationFunction([this] (Game&) { + openSubmenu(Menu({ + MenuBuilder().Command("Back") + .ActivationFunction([this] (Game& game) { + closePauseMenu(); + }) + .SkipSoundEffect() + })); + }), MenuBuilder().Command("Resume Game") .ActivationFunction([] (Game& game) { game.getSystem().closePauseMenu(); @@ -61,29 +80,32 @@ void MenuSystem::openPauseMenu() { })); } - menu_ = CreateMenu(builders); - - cursor_ = 0; + menus_.emplace_back(builders); game_.getMixer().pauseSounds(); game_.getMixer().playSound("../res/sfx/menu_open.wav"); } void MenuSystem::closePauseMenu(bool playSfx) { - pauseAnimation_.start(125, 0.0); - openState_ = OpenState::Animating; + if (menus_.size() > 1) { + isMenuChanging_ = true; + menuChangeAnimation_.start(250, 0.0); + + if (playSfx) { + game_.getMixer().playSound("../res/sfx/menu_deselect.wav"); + } + } else { + pauseAnimation_.start(125, 0.0); + openState_ = OpenState::Animating; - if (playSfx) { - game_.getMixer().playSound("../res/sfx/menu_close.wav"); + if (playSfx) { + game_.getMixer().playSound("../res/sfx/menu_close.wav"); + } } } void MenuSystem::pressedUp() { - cursor_--; - - if (cursor_ < 0) { - cursor_ = menu_.size() - 1; - } + menus_.back().moveCursorUp(); cursorBob_ = 0; cursorBobDown_ = true; @@ -92,11 +114,7 @@ void MenuSystem::pressedUp() { } void MenuSystem::pressedDown() { - cursor_++; - - if (cursor_ >= menu_.size()) { - cursor_ = 0; - } + menus_.back().moveCursorDown(); cursorBob_ = 0; cursorBobDown_ = true; @@ -105,13 +123,22 @@ void MenuSystem::pressedDown() { } void MenuSystem::activateOption() { - if (menu_[cursor_].type == MenuType::Command) { - if (menu_[cursor_].playSfx) { + Menu& curMenu = menus_.back(); + const MenuItem& menuItem = curMenu.getItems()[curMenu.getCursorPosition()]; + + if (menuItem.type == MenuType::Command) { + if (menuItem.playSfx) { game_.getMixer().playSound("../res/sfx/menu_activate.wav"); } - if (menu_[cursor_].activationFunction) { - menu_[cursor_].activationFunction(game_); + if (menuItem.activationFunction) { + menuItem.activationFunction(game_); } } } + +void MenuSystem::openSubmenu(Menu submenu) { + menus_.push_back(std::move(submenu)); + isMenuChanging_ = true; + menuChangeAnimation_.start(250, 1.0); +} diff --git a/src/menu_system.h b/src/menu_system.h index 736d555..c921d0b 100644 --- a/src/menu_system.h +++ b/src/menu_system.h @@ -1,6 +1,7 @@ #ifndef MENU_SYSTEM_H_205861EC #define MENU_SYSTEM_H_205861EC +#include #include #include "interpolation.h" #include "menu.h" @@ -34,16 +35,24 @@ public: double getPauseAnimationProgress() const { return pauseAnimation_.getProgress(); } - bool isMenuOpen() const { return openState_ == OpenState::Open; } + bool isMenuOpen() const { return openState_ == OpenState::Open && !isMenuChanging_; } - const std::vector& getMenu() const { return menu_; } + // Only call this if a menu is open. + Menu& getMenu() { return menus_.back(); } - int getCursorPosition() const { return cursor_; } + // Only call this if a submenu is open. + Menu& getParentMenu() { return menus_[menus_.size()-2]; } int getCursorBob() const { return cursorBob_; } + double getMenuChangeAnimationProgress() const { return menuChangeAnimation_.getProgress(); } + + bool isMenuChanging() const { return isMenuChanging_; } + private: + void openSubmenu(Menu submenu); + enum class OpenState { Closed, Animating, @@ -51,13 +60,18 @@ private: }; Game& game_; + Interpolation pauseAnimation_; OpenState openState_ = OpenState::Closed; - std::vector menu_; - int cursor_ = 0; + + std::deque menus_; + int cursorBob_ = 0; bool cursorBobDown_ = true; Timer cursorBobTimer_ { 125 }; + + Interpolation menuChangeAnimation_; + bool isMenuChanging_ = false; }; #endif /* end of include guard: MENU_SYSTEM_H_205861EC */ diff --git a/src/renderer.cpp b/src/renderer.cpp index fc16e20..f7644ca 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -3,6 +3,7 @@ #include "consts.h" #include "game.h" #include "map.h" +#include "menu.h" #include "transform_system.h" #include "camera_system.h" #include "message_system.h" @@ -142,11 +143,22 @@ void Renderer::render(Game& game) { } if (menus.getPauseAnimationProgress() > 0.0) { - renderMenu(game); + renderMenu(game, menus.getMenu()); SDL_SetRenderTarget(ren_.get(), canvas.get()); if (menus.getPauseAnimationProgress() == 1.0) { - SDL_RenderCopy(ren_.get(), menuTex_.get(), nullptr, nullptr); + if (menus.isMenuChanging()) { + SDL_Rect dest { static_cast(CANVAS_WIDTH * (1.0 - menus.getMenuChangeAnimationProgress())), 0, CANVAS_WIDTH, CANVAS_HEIGHT }; + SDL_RenderCopy(ren_.get(), menuTex_.get(), nullptr, &dest); + + renderMenu(game, menus.getParentMenu()); + + dest.x -= CANVAS_WIDTH; + SDL_SetRenderTarget(ren_.get(), canvas.get()); + SDL_RenderCopy(ren_.get(), menuTex_.get(), nullptr, &dest); + } else { + SDL_RenderCopy(ren_.get(), menuTex_.get(), nullptr, nullptr); + } } else { int barHeight = CANVAS_HEIGHT / 2 * menus.getPauseAnimationProgress(); SDL_Rect topHalf { 0, 0, CANVAS_WIDTH, barHeight }; @@ -536,7 +548,7 @@ void Renderer::renderGame(Game& game) { } } -void Renderer::renderMenu(Game& game) { +void Renderer::renderMenu(Game& game, const Menu& menu) { auto& menus = game.getSystem(); if (!menuTex_) { @@ -558,11 +570,11 @@ void Renderer::renderMenu(Game& game) { SDL_RenderFillRect(ren_.get(), nullptr); const int lineHeight = 16; - int totalHeight = menus.getMenu().size() * lineHeight; + int totalHeight = menu.getItems().size() * lineHeight; std::vector positions; int index = 0; - for (const MenuItem& menuItem : menus.getMenu()) { + for (const MenuItem& menuItem : menu.getItems()) { switch (menuItem.type) { case MenuType::Command: { MessageCache output; @@ -589,8 +601,8 @@ void Renderer::renderMenu(Game& game) { int cursorTexId = loadImageFromFile("../res/feather_pen.png"); const SDL_Rect cursorDest { - positions[menus.getCursorPosition()].x() - 2 - 16 - menus.getCursorBob(), - positions[menus.getCursorPosition()].y() - 8 - menus.getCursorBob(), + positions[menu.getCursorPosition()].x() - 2 - 16 - menus.getCursorBob(), + positions[menu.getCursorPosition()].y() - 8 - menus.getCursorBob(), 16, 16 }; SDL_RenderCopy(ren_.get(), textures_.at(cursorTexId).get(), nullptr, &cursorDest); diff --git a/src/renderer.h b/src/renderer.h index 75bd9fe..82d34a5 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -12,6 +12,7 @@ class Game; class Map; class Sprite; +class Menu; class sdl_error : public std::logic_error { public: @@ -135,7 +136,7 @@ private: std::map filenameToTexId_; // Menu rendering - void renderMenu(Game& game); + void renderMenu(Game& game, const Menu& menu); texture_ptr menuTex_; -- cgit 1.4.1