diff options
| -rw-r--r-- | res/slider_off.png | bin | 0 -> 111 bytes | |||
| -rw-r--r-- | res/slider_on.png | bin | 0 -> 145 bytes | |||
| -rw-r--r-- | src/input_system.cpp | 8 | ||||
| -rw-r--r-- | src/menu.h | 26 | ||||
| -rw-r--r-- | src/menu_system.cpp | 28 | ||||
| -rw-r--r-- | src/menu_system.h | 4 | ||||
| -rw-r--r-- | src/renderer.cpp | 55 |
7 files changed, 117 insertions, 4 deletions
| diff --git a/res/slider_off.png b/res/slider_off.png new file mode 100644 index 0000000..432c5ec --- /dev/null +++ b/res/slider_off.png | |||
| Binary files differ | |||
| diff --git a/res/slider_on.png b/res/slider_on.png new file mode 100644 index 0000000..eb67a43 --- /dev/null +++ b/res/slider_on.png | |||
| Binary files differ | |||
| diff --git a/src/input_system.cpp b/src/input_system.cpp index 25af7ed..3e4b679 100644 --- a/src/input_system.cpp +++ b/src/input_system.cpp | |||
| @@ -119,12 +119,20 @@ void InputSystem::tick(double dt) { | |||
| 119 | } | 119 | } |
| 120 | } | 120 | } |
| 121 | } else if (e.key.keysym.sym == SDLK_LEFT) { | 121 | } else if (e.key.keysym.sym == SDLK_LEFT) { |
| 122 | if (game_.getSystem<MenuSystem>().isMenuOpen()) { | ||
| 123 | game_.getSystem<MenuSystem>().pressedLeft(); | ||
| 124 | } | ||
| 125 | |||
| 122 | if (game_.isGameplayPaused()) continue; | 126 | if (game_.isGameplayPaused()) continue; |
| 123 | 127 | ||
| 124 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { | 128 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { |
| 125 | game_.getSystem<MessageSystem>().selectFirstChoice(); | 129 | game_.getSystem<MessageSystem>().selectFirstChoice(); |
| 126 | } | 130 | } |
| 127 | } else if (e.key.keysym.sym == SDLK_RIGHT) { | 131 | } else if (e.key.keysym.sym == SDLK_RIGHT) { |
| 132 | if (game_.getSystem<MenuSystem>().isMenuOpen()) { | ||
| 133 | game_.getSystem<MenuSystem>().pressedRight(); | ||
| 134 | } | ||
| 135 | |||
| 128 | if (game_.isGameplayPaused()) continue; | 136 | if (game_.isGameplayPaused()) continue; |
| 129 | 137 | ||
| 130 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { | 138 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { |
| diff --git a/src/menu.h b/src/menu.h index 67c75c0..9ef94be 100644 --- a/src/menu.h +++ b/src/menu.h | |||
| @@ -9,14 +9,17 @@ | |||
| 9 | class Game; | 9 | class Game; |
| 10 | 10 | ||
| 11 | enum class MenuType { | 11 | enum class MenuType { |
| 12 | Command | 12 | Command, |
| 13 | Slider | ||
| 13 | }; | 14 | }; |
| 14 | 15 | ||
| 15 | struct MenuItem { | 16 | struct MenuItem { |
| 16 | MenuType type = MenuType::Command; | 17 | MenuType type = MenuType::Command; |
| 17 | std::string text; | 18 | std::string text; |
| 18 | std::function<void(Game&)> activationFunction; | 19 | std::function<void(Game&)> activationFunction; |
| 19 | bool playSfx = false; | 20 | bool playSfx = true; |
| 21 | int value = 0; | ||
| 22 | int maxValue = 0; | ||
| 20 | }; | 23 | }; |
| 21 | 24 | ||
| 22 | class MenuBuilder { | 25 | class MenuBuilder { |
| @@ -25,7 +28,6 @@ public: | |||
| 25 | MenuBuilder& Command(std::string text) { | 28 | MenuBuilder& Command(std::string text) { |
| 26 | result_.type = MenuType::Command; | 29 | result_.type = MenuType::Command; |
| 27 | result_.text = std::move(text); | 30 | result_.text = std::move(text); |
| 28 | result_.playSfx = true; | ||
| 29 | return *this; | 31 | return *this; |
| 30 | } | 32 | } |
| 31 | 33 | ||
| @@ -39,6 +41,22 @@ public: | |||
| 39 | return *this; | 41 | return *this; |
| 40 | } | 42 | } |
| 41 | 43 | ||
| 44 | MenuBuilder& Slider(std::string text) { | ||
| 45 | result_.type = MenuType::Slider; | ||
| 46 | result_.text = std::move(text); | ||
| 47 | return *this; | ||
| 48 | } | ||
| 49 | |||
| 50 | MenuBuilder& InitialValue(int value) { | ||
| 51 | result_.value = value; | ||
| 52 | return *this; | ||
| 53 | } | ||
| 54 | |||
| 55 | MenuBuilder& MaxValue(int mv) { | ||
| 56 | result_.maxValue = mv; | ||
| 57 | return *this; | ||
| 58 | } | ||
| 59 | |||
| 42 | MenuItem Build() const { | 60 | MenuItem Build() const { |
| 43 | return result_; | 61 | return result_; |
| 44 | } | 62 | } |
| @@ -55,6 +73,8 @@ public: | |||
| 55 | 73 | ||
| 56 | const std::vector<MenuItem>& getItems() const { return items_; } | 74 | const std::vector<MenuItem>& getItems() const { return items_; } |
| 57 | 75 | ||
| 76 | std::vector<MenuItem>& getItems() { return items_; } | ||
| 77 | |||
| 58 | int getCursorPosition() const { return cursor_; } | 78 | int getCursorPosition() const { return cursor_; } |
| 59 | 79 | ||
| 60 | void moveCursorUp(); | 80 | void moveCursorUp(); |
| diff --git a/src/menu_system.cpp b/src/menu_system.cpp index 7ac8af5..e1aca8d 100644 --- a/src/menu_system.cpp +++ b/src/menu_system.cpp | |||
| @@ -54,6 +54,12 @@ void MenuSystem::openPauseMenu() { | |||
| 54 | MenuBuilder().Command("Settings") | 54 | MenuBuilder().Command("Settings") |
| 55 | .ActivationFunction([this] (Game&) { | 55 | .ActivationFunction([this] (Game&) { |
| 56 | openSubmenu(Menu({ | 56 | openSubmenu(Menu({ |
| 57 | MenuBuilder().Slider("Music Volume: ") | ||
| 58 | .InitialValue(10) | ||
| 59 | .MaxValue(10), | ||
| 60 | MenuBuilder().Slider("Sound Volume: ") | ||
| 61 | .InitialValue(10) | ||
| 62 | .MaxValue(10), | ||
| 57 | MenuBuilder().Command("Back") | 63 | MenuBuilder().Command("Back") |
| 58 | .ActivationFunction([this] (Game& game) { | 64 | .ActivationFunction([this] (Game& game) { |
| 59 | closePauseMenu(); | 65 | closePauseMenu(); |
| @@ -122,6 +128,28 @@ void MenuSystem::pressedDown() { | |||
| 122 | game_.getMixer().playSound("../res/sfx/vertical_menu.wav"); | 128 | game_.getMixer().playSound("../res/sfx/vertical_menu.wav"); |
| 123 | } | 129 | } |
| 124 | 130 | ||
| 131 | void MenuSystem::pressedLeft() { | ||
| 132 | Menu& curMenu = menus_.back(); | ||
| 133 | MenuItem& menuItem = curMenu.getItems()[curMenu.getCursorPosition()]; | ||
| 134 | |||
| 135 | if (menuItem.type == MenuType::Slider && menuItem.value > 0) { | ||
| 136 | menuItem.value--; | ||
| 137 | |||
| 138 | game_.getMixer().playSound("../res/sfx/horizontal_menu.wav"); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | void MenuSystem::pressedRight() { | ||
| 143 | Menu& curMenu = menus_.back(); | ||
| 144 | MenuItem& menuItem = curMenu.getItems()[curMenu.getCursorPosition()]; | ||
| 145 | |||
| 146 | if (menuItem.type == MenuType::Slider && menuItem.value < menuItem.maxValue) { | ||
| 147 | menuItem.value++; | ||
| 148 | |||
| 149 | game_.getMixer().playSound("../res/sfx/horizontal_menu.wav"); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 125 | void MenuSystem::activateOption() { | 153 | void MenuSystem::activateOption() { |
| 126 | Menu& curMenu = menus_.back(); | 154 | Menu& curMenu = menus_.back(); |
| 127 | const MenuItem& menuItem = curMenu.getItems()[curMenu.getCursorPosition()]; | 155 | const MenuItem& menuItem = curMenu.getItems()[curMenu.getCursorPosition()]; |
| diff --git a/src/menu_system.h b/src/menu_system.h index c921d0b..71e2b39 100644 --- a/src/menu_system.h +++ b/src/menu_system.h | |||
| @@ -29,6 +29,10 @@ public: | |||
| 29 | 29 | ||
| 30 | void pressedDown(); | 30 | void pressedDown(); |
| 31 | 31 | ||
| 32 | void pressedLeft(); | ||
| 33 | |||
| 34 | void pressedRight(); | ||
| 35 | |||
| 32 | void activateOption(); | 36 | void activateOption(); |
| 33 | 37 | ||
| 34 | // Info | 38 | // Info |
| diff --git a/src/renderer.cpp b/src/renderer.cpp index f7644ca..b28e3cb 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #include "renderer.h" | 1 | #include "renderer.h" |
| 2 | #include <deque> | ||
| 2 | #include <iostream> | 3 | #include <iostream> |
| 3 | #include "consts.h" | 4 | #include "consts.h" |
| 4 | #include "game.h" | 5 | #include "game.h" |
| @@ -570,11 +571,33 @@ void Renderer::renderMenu(Game& game, const Menu& menu) { | |||
| 570 | SDL_RenderFillRect(ren_.get(), nullptr); | 571 | SDL_RenderFillRect(ren_.get(), nullptr); |
| 571 | 572 | ||
| 572 | const int lineHeight = 16; | 573 | const int lineHeight = 16; |
| 574 | const int sliderBarWidth = 9; | ||
| 573 | int totalHeight = menu.getItems().size() * lineHeight; | 575 | int totalHeight = menu.getItems().size() * lineHeight; |
| 574 | std::vector<vec2i> positions; | 576 | std::vector<vec2i> positions; |
| 577 | std::deque<MessageCache> sliderText; | ||
| 578 | int maxSliderLineWidth = 0; | ||
| 579 | int sliderAlignX = 0; | ||
| 575 | 580 | ||
| 581 | // First, find all of the sliders so we can figure out how to align them. | ||
| 582 | for (const MenuItem& menuItem : menu.getItems()) { | ||
| 583 | if (menuItem.type == MenuType::Slider) { | ||
| 584 | MessageCache output; | ||
| 585 | renderMessageLine(output, menuItem.text, game); | ||
| 586 | |||
| 587 | int width = output.charIndexToWidth.back() + sliderBarWidth * menuItem.maxValue; | ||
| 588 | if (width > maxSliderLineWidth) { | ||
| 589 | maxSliderLineWidth = width; | ||
| 590 | sliderAlignX = (CANVAS_WIDTH - maxSliderLineWidth) / 2 + output.charIndexToWidth.back(); | ||
| 591 | } | ||
| 592 | |||
| 593 | sliderText.push_back(std::move(output)); | ||
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 597 | // Now, render all of the items. | ||
| 576 | int index = 0; | 598 | int index = 0; |
| 577 | for (const MenuItem& menuItem : menu.getItems()) { | 599 | for (const MenuItem& menuItem : menu.getItems()) { |
| 600 | int lineY = (CANVAS_HEIGHT - totalHeight) / 2 + lineHeight * index; | ||
| 578 | switch (menuItem.type) { | 601 | switch (menuItem.type) { |
| 579 | case MenuType::Command: { | 602 | case MenuType::Command: { |
| 580 | MessageCache output; | 603 | MessageCache output; |
| @@ -582,7 +605,24 @@ void Renderer::renderMenu(Game& game, const Menu& menu) { | |||
| 582 | 605 | ||
| 583 | SDL_Rect dest { | 606 | SDL_Rect dest { |
| 584 | (CANVAS_WIDTH - output.charIndexToWidth.back()) / 2, | 607 | (CANVAS_WIDTH - output.charIndexToWidth.back()) / 2, |
| 585 | (CANVAS_HEIGHT - totalHeight) / 2 + lineHeight * index, | 608 | lineY, |
| 609 | MESSAGE_TEXT_WIDTH, | ||
| 610 | game.getFont().getCharacterHeight() | ||
| 611 | }; | ||
| 612 | |||
| 613 | SDL_SetRenderTarget(ren_.get(), menuTex_.get()); | ||
| 614 | SDL_RenderCopy(ren_.get(), output.renderedTex.get(), nullptr, &dest); | ||
| 615 | |||
| 616 | positions.emplace_back(dest.x, dest.y); | ||
| 617 | |||
| 618 | break; | ||
| 619 | } | ||
| 620 | case MenuType::Slider: { | ||
| 621 | MessageCache& output = sliderText.front(); | ||
| 622 | |||
| 623 | SDL_Rect dest { | ||
| 624 | sliderAlignX - output.charIndexToWidth.back(), | ||
| 625 | lineY, | ||
| 586 | MESSAGE_TEXT_WIDTH, | 626 | MESSAGE_TEXT_WIDTH, |
| 587 | game.getFont().getCharacterHeight() | 627 | game.getFont().getCharacterHeight() |
| 588 | }; | 628 | }; |
| @@ -592,6 +632,19 @@ void Renderer::renderMenu(Game& game, const Menu& menu) { | |||
| 592 | 632 | ||
| 593 | positions.emplace_back(dest.x, dest.y); | 633 | positions.emplace_back(dest.x, dest.y); |
| 594 | 634 | ||
| 635 | for (int j = 0; j < menuItem.maxValue; j++) { | ||
| 636 | int boxTexId = menuItem.value > j ? loadImageFromFile("../res/slider_on.png") : loadImageFromFile("../res/slider_off.png"); | ||
| 637 | const SDL_Rect boxDest { | ||
| 638 | sliderAlignX + j * sliderBarWidth, | ||
| 639 | lineY + 2, | ||
| 640 | 8, | ||
| 641 | 8 }; | ||
| 642 | SDL_SetRenderTarget(ren_.get(), menuTex_.get()); | ||
| 643 | SDL_RenderCopy(ren_.get(), textures_.at(boxTexId).get(), nullptr, &boxDest); | ||
| 644 | } | ||
| 645 | |||
| 646 | sliderText.pop_front(); | ||
| 647 | |||
| 595 | break; | 648 | break; |
| 596 | } | 649 | } |
| 597 | } | 650 | } |
