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 0000000..3690898 Binary files /dev/null and b/menu_background1.png differ