Skip to content

Commit a2f04bc

Browse files
committed
Initial take at menu support
1 parent 8dc74c9 commit a2f04bc

File tree

3 files changed

+97
-18
lines changed

3 files changed

+97
-18
lines changed

src/game.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ Game_Map make_map()// NOLINT cognitive complexity
6363
game.last_message = "";
6464
};
6565

66+
map.locations.at(Point{2,0}).enter_action = [](Game &game, Point, Direction) {
67+
Menu menu;
68+
menu.items.push_back(Menu::MenuItem{"Hello World", [](auto &){}});
69+
menu.items.push_back(Menu::MenuItem{ "Exit Menu", [](Game &menu_action_game) {menu_action_game.clear_menu();}});
70+
game.set_menu(menu);
71+
};
72+
6673

6774
return map;
6875
}

src/game_components.hpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
#ifndef MY_AWESOME_GAME_GAME_COMPONENTS_HPP
22
#define MY_AWESOME_GAME_GAME_COMPONENTS_HPP
33

4-
#include <functional>
54
#include <chrono>
5+
#include <functional>
66
#include <map>
77
#include <optional>
88
#include <variant>
99

1010
#include "color.hpp"
1111
#include "vector2d.hpp"
1212

13-
namespace lefticus::my_awesome_game
14-
{
13+
namespace lefticus::my_awesome_game {
1514

1615
struct Game;
1716

@@ -47,14 +46,25 @@ struct Game_Map
4746
}
4847
};
4948

49+
struct Menu
50+
{
51+
struct MenuItem
52+
{
53+
std::string text;
54+
std::function<void(Game &)> action;
55+
};
56+
57+
std::vector<MenuItem> items;
58+
};
59+
5060
using Variable = std::variant<double, std::int64_t, std::string>;
5161

5262
struct Game
5363
{
5464

5565
std::map<std::string, Game_Map> maps;
5666
Character player;
57-
std::function<void (Game &)> start_game;
67+
std::function<void(Game &)> start_game;
5868

5969
std::map<std::string, Variable> variables;
6070
std::vector<std::string> display_variables;
@@ -63,8 +73,38 @@ struct Game
6373
Size tile_size;
6474

6575
std::string last_message;
76+
77+
[[nodiscard]] bool has_new_menu() const { return menu_is_new; }
78+
79+
[[nodiscard]] bool has_menu() const { return static_cast<bool>(menu); }
80+
81+
[[nodiscard]] Menu get_menu()
82+
{
83+
if (menu) {
84+
menu_is_new = false;
85+
return *menu;
86+
} else {
87+
return Menu{};
88+
}
89+
}
90+
91+
void set_menu(Menu menu_)
92+
{
93+
menu_is_new = true;
94+
menu = std::move(menu_);
95+
}
96+
97+
void clear_menu()
98+
{
99+
menu_is_new = false;
100+
menu.reset();
101+
}
102+
103+
private:
104+
std::optional<Menu> menu;
105+
bool menu_is_new = false;
66106
};
67107

68-
}
108+
}// namespace lefticus::my_awesome_game
69109

70110
#endif// MY_AWESOME_GAME_GAME_COMPONENTS_HPP

src/main.cpp

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,28 @@ void draw(Bitmap &viewport, const Game &game)
7070
}
7171
}
7272

73+
struct Displayed_Menu
74+
{
75+
Displayed_Menu(Menu menu_, Game &game) : menu{ std::move(menu_) }
76+
{
77+
ftxui::Components menu_lines;
78+
79+
std::ranges::transform(menu.items, std::back_inserter(menu_lines), [&game](auto &item) {
80+
return ftxui::Button(item.text, [&game, &item]() { item.action(game); });
81+
});
82+
83+
buttons = ftxui::Container::Vertical(menu_lines);
84+
}
85+
86+
Menu menu;
87+
ftxui::Component buttons;
88+
};
89+
7390
void game_iteration_canvas()// NOLINT cognitive complexity
7491
{
7592
auto game = make_game();
7693

94+
Displayed_Menu current_menu{ Menu{}, game };
7795

7896
// this should probably have a `bitmap` helper function that does what you expect
7997
// similar to the other parts of FTXUI
@@ -102,6 +120,10 @@ void game_iteration_canvas()// NOLINT cognitive complexity
102120
game.clock = game_clock;
103121

104122
[&] {
123+
if (game.has_menu()) {
124+
return;
125+
}
126+
105127
if (current_event != last_event) {
106128
auto location = game.player.map_location;
107129
const auto last_location = location;
@@ -133,7 +155,6 @@ void game_iteration_canvas()// NOLINT cognitive complexity
133155
auto enter_action = game.maps.at(game.current_map).locations.at(location).enter_action;
134156
if (enter_action) { enter_action(game, location, from); }
135157
}
136-
137158
}
138159
}();
139160

@@ -149,32 +170,43 @@ void game_iteration_canvas()// NOLINT cognitive complexity
149170

150171
std::string last_character;
151172

173+
auto container = ftxui::Container::Vertical({});
174+
175+
auto key_press = ftxui::CatchEvent(container, [&](const ftxui::Event &event) {
176+
if (game.has_menu()) {
177+
return false;
178+
} else {
179+
last_event = std::exchange(current_event, event);
180+
return true;
181+
}
182+
});
183+
152184
auto make_layout = [&] {
153185
// This code actually processes the draw event
154186
const auto new_time = std::chrono::steady_clock::now();
155187

188+
if (game.has_new_menu()) { current_menu = Displayed_Menu{ game.get_menu(), game };
189+
key_press->DetachAllChildren();
190+
key_press->Add(current_menu.buttons);
191+
}
192+
156193
++counter;
157194
// we will dispatch to the game_iteration function, where the work happens
158195
game_iteration(new_time - last_time);
159196
last_time = new_time;
160197

161198
// now actually draw the game elements
162-
return ftxui::vbox({ftxui::hbox({ bm | ftxui::border,
163-
ftxui::vbox({ ftxui::text("Frame: " + std::to_string(counter)),
164-
ftxui::text("FPS: " + std::to_string(fps)),
165-
ftxui::text("Character: " + last_character),
166-
small_bm | ftxui::border }) }), ftxui::text("Message: " + game.last_message)});
199+
return ftxui::vbox({ ftxui::hbox({ (game.has_menu() ? current_menu.buttons->Render() : bm) | ftxui::border,
200+
ftxui::vbox({ ftxui::text("Frame: " + std::to_string(counter)),
201+
ftxui::text("FPS: " + std::to_string(fps)),
202+
ftxui::text("Character: " + last_character),
203+
small_bm | ftxui::border }) }),
204+
ftxui::text("Message: " + game.last_message) });
167205
};
168206

169-
auto container = ftxui::Container::Vertical({});
170-
171-
auto key_press = ftxui::CatchEvent(container, [&](const ftxui::Event &event) {
172-
last_event = std::exchange(current_event, event);
173-
return false;
174-
});
175207

176208

177-
auto renderer = ftxui::Renderer(key_press, make_layout);
209+
auto renderer = ftxui::Renderer(game.has_menu() ? current_menu.buttons : key_press, make_layout);
178210

179211
std::atomic<bool> refresh_ui_continue = true;
180212

0 commit comments

Comments
 (0)