From 89b4bce73411bc056948fbfb2e70ac66dd01691f Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Mon, 21 Apr 2025 17:03:26 +1000 Subject: [PATCH] menu --- Ai.cpp | 8 +++++ Engine.cpp | 48 ++++++++++++++++++++++------ Engine.h | 2 ++ Gui.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++- Gui.h | 27 ++++++++++++++-- menu_background1.png | Bin 0 -> 10785 bytes 6 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 menu_background1.png diff --git a/Ai.cpp b/Ai.cpp index a20e55b..2f97658 100644 --- a/Ai.cpp +++ b/Ai.cpp @@ -20,6 +20,11 @@ void PlayerAi::update(Actor* owner) { case SDL_EVENT_QUIT: engine->gameStatus = Engine::QUIT; break; + case SDL_EVENT_KEY_DOWN: + if (event.key.key == SDLK_ESCAPE) { + engine->gameStatus = Engine::PAUSE; + } + break; default: break; } @@ -47,6 +52,9 @@ void PlayerAi::update(Actor* owner) { case SDLK_RIGHT: dx = 1; break; + case SDLK_ESCAPE: + engine->gameStatus = Engine::PAUSE; + break; default: if (event.key.key >= SDLK_A && event.key.key <= SDLK_Z) { handleActionKey(owner, event.key.key); diff --git a/Engine.cpp b/Engine.cpp index aa89efe..5ef268b 100644 --- a/Engine.cpp +++ b/Engine.cpp @@ -19,7 +19,6 @@ Engine::Engine(int screenWidth, int screenHeight, tcod::Context *context, tcod:: player = nullptr; fovRadius = 10; computeFov = true; - gameStatus = STARTUP; mouse.cx = 0; mouse.cy = 0; mouse.rbutton_pressed = false; @@ -27,7 +26,6 @@ Engine::Engine(int screenWidth, int screenHeight, tcod::Context *context, tcod:: } void Engine::init() { - gui = new Gui(context, console); player = new Actor(40, 25, "@", "player", TCOD_ColorRGB(255, 255, 255)); player->destructible = new PlayerDestructible(30, 2, "player corpse"); player->attacker = new Attacker(5); @@ -38,11 +36,17 @@ void Engine::init() { map->init(true); gui->message(TCOD_ColorRGB(150,0,0), "Welcome stranger!\nPrepare to perish in the Tombs of Andrew's Dunegon."); + gameStatus = STARTUP; +} + +void Engine::term() { + actors.clearAndDelete(); + if (map) delete map; + gui->clear(); } Engine::~Engine() { - actors.clearAndDelete(); - delete map; + term(); delete gui; } @@ -50,6 +54,7 @@ bool Engine::update() { if (gameStatus == STARTUP) map->computeFov(); gameStatus = IDLE; player->update(); + if (gameStatus == NEW_TURN) { for (Actor** iterator = actors.begin(); iterator != actors.end(); iterator++) { @@ -58,10 +63,15 @@ bool Engine::update() { actor->update(); } } - } - if (gameStatus == QUIT) { + } else if (gameStatus == QUIT) { return false; } + else if (gameStatus == PAUSE) { + save(); + load(); + } + + return true; } @@ -198,8 +208,28 @@ void Engine::save() { } void Engine::load() { + gui = new Gui(context, console); + gui->menu.clear(); + gui->menu.addItem(Menu::NEW_GAME, "New game"); if (TCODSystem::fileExists("game.sav")) { + engine->gui->menu.addItem(Menu::CONTINUE, "Continue"); + } + engine->gui->menu.addItem(Menu::EXIT, "Exit"); + Menu::MenuItemCode menuItem = engine->gui->menu.pick(context, console); + + if (menuItem == Menu::EXIT || menuItem == Menu::NONE) { + // Exit or window closed + exit(0); + } + else if (menuItem == Menu::NEW_GAME) { + // New game + term(); + init(); + } + else if (menuItem == Menu::CONTINUE) { + // Continue TCODZip zip; + term(); zip.loadFromFile("game.sav"); // load the map int width = zip.getInt(); @@ -219,10 +249,8 @@ void Engine::load() { nbActors--; } // finally the message log - gui = new Gui(context, console); + gui->load(zip); - } - else { - engine->init(); + gameStatus = STARTUP; } } \ No newline at end of file diff --git a/Engine.h b/Engine.h index 20f50b3..eae8079 100644 --- a/Engine.h +++ b/Engine.h @@ -13,6 +13,7 @@ public: NEW_TURN, VICTORY, DEFEAT, + PAUSE, QUIT } gameStatus; @@ -28,6 +29,7 @@ public: tcod::Console* console; Engine(int screenWidth, int screenHeight, tcod::Context *context, tcod::Console *console); void init(); + void term(); ~Engine(); bool update(); void render(bool present = true); diff --git a/Gui.cpp b/Gui.cpp index 65e7023..e56d86f 100644 --- a/Gui.cpp +++ b/Gui.cpp @@ -1,3 +1,4 @@ +#include #include "Gui.h" #include "Engine.h" #include "Actor.h" @@ -14,10 +15,15 @@ Gui::Gui(tcod::Context *ctx, tcod::Console *root) { this->root = root; } -Gui::~Gui() { +void Gui::clear() { log.clearAndDelete(); } +Gui::~Gui() { + delete con.release(); + clear(); +} + void Gui::render() { // clear the GUI console con.clear(); @@ -136,4 +142,69 @@ void Gui::load(TCODZip& zip) { message(col, text); nbMessages--; } +} + +Menu::~Menu() { + clear(); +} + +void Menu::clear() { + items.clearAndDelete(); +} + +void Menu::addItem(MenuItemCode code, std::string label) { + MenuItem* item = new MenuItem(); + item->code = code; + item->label = label; + items.push(item); +} + +Menu::MenuItemCode Menu::pick(tcod::Context *ctx, tcod::Console *con) { + static TCODImage img("menu_background1.png"); + int selectedItem = 0; + + while (true) { + img.blit2x(*con, 0, 0); + int currentItem = 0; + for (MenuItem** it = items.begin(); it != items.end(); it++) { + if (currentItem == selectedItem) { + tcod::print(*con, { 10, 10 + currentItem * 3 }, (*it)->label,TCOD_ColorRGB(255, 100, 255), std::nullopt); + } + else { + tcod::print(*con, { 10, 10 + currentItem * 3 }, (*it)->label, TCOD_ColorRGB(200, 200, 200), std::nullopt); + } + currentItem++; + } + ctx->present(*con); + // check key presses + SDL_Event event; + + while (SDL_PollEvent(&event)) { + ctx->convert_event_coordinates(event); + switch (event.type) { + case SDL_EVENT_KEY_DOWN: + { + if (event.key.key == SDLK_UP) { + selectedItem--; + if (selectedItem < 0) { + selectedItem = items.size() - 1; + } + } + else if (event.key.key == SDLK_DOWN) { + selectedItem = (selectedItem + 1) % items.size(); + } + else if (event.key.key == SDLK_RETURN) { + return items.get(selectedItem)->code; + } + else if (event.key.key == SDLK_ESCAPE) { + return NONE; + } + } + break; + case SDL_EVENT_QUIT: + engine->gameStatus = Engine::QUIT; + return NONE; + } + } + } } \ No newline at end of file diff --git a/Gui.h b/Gui.h index 2bf5d6d..10fc364 100644 --- a/Gui.h +++ b/Gui.h @@ -2,6 +2,27 @@ #include "libtcod.hpp" #include "Persistance.h" + +class Menu { +public: + enum MenuItemCode { + NONE, + NEW_GAME, + CONTINUE, + EXIT + }; + ~Menu(); + void clear(); + void addItem(MenuItemCode code, std::string label); + MenuItemCode pick(tcod::Context* ctx, tcod::Console* con); +protected: + struct MenuItem { + MenuItemCode code; + std::string label; + }; + TCODList items; +}; + class Gui : public Persistent { public: Gui(tcod::Context *ctx, tcod::Console *root); @@ -10,7 +31,8 @@ public: void message(const TCOD_ColorRGB& col, const char* text, ...); void load(TCODZip& zip); void save(TCODZip& zip); - + void clear(); + Menu menu; protected: tcod::Console con; tcod::Console* root; @@ -26,4 +48,5 @@ protected: }; TCODList log; -}; \ No newline at end of file +}; + diff --git a/menu_background1.png b/menu_background1.png new file mode 100644 index 0000000000000000000000000000000000000000..3690898eceff719653984dc7bba68c32a88a0bd1 GIT binary patch literal 10785 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 literal 0 HcmV?d00001