From 5201d10e203a699bb48a72f2c2e2ad6062fa0794 Mon Sep 17 00:00:00 2001 From: zvon Date: Mon, 19 Sep 2022 22:56:50 +0200 Subject: [PATCH] Game main menu/retry scenes --- mario/CMakeLists.txt | 5 + mario/main.cpp | 271 ++++++++++++++++++++------------ mario/scenes/editor_main.cpp | 9 +- mario/scenes/editor_scenes.hpp | 21 +-- mario/scenes/game_main_menu.cpp | 229 +++++++++++++++++++++++++++ mario/scenes/game_scenes.hpp | 15 ++ mario/scenes/load_scene.cpp | 16 +- mario/scenes/shared_scenes.hpp | 24 +++ 8 files changed, 463 insertions(+), 127 deletions(-) create mode 100644 mario/scenes/game_main_menu.cpp create mode 100644 mario/scenes/game_scenes.hpp create mode 100644 mario/scenes/shared_scenes.hpp diff --git a/mario/CMakeLists.txt b/mario/CMakeLists.txt index cc18c11..15115a1 100644 --- a/mario/CMakeLists.txt +++ b/mario/CMakeLists.txt @@ -78,6 +78,11 @@ target_sources(mario PRIVATE blocks/coinblock.cpp PRIVATE blocks/mushroomblock.cpp PRIVATE blocks/goombablock.cpp + PRIVATE scenes/load_scene.cpp + PRIVATE scenes/game_main_menu.cpp + PRIVATE editor_visitor.cpp # TODO + PRIVATE edit_box.cpp # TODO + PRIVATE tool_box.cpp # TODO ) target_sources(editor diff --git a/mario/main.cpp b/mario/main.cpp index c1873bd..c56686f 100644 --- a/mario/main.cpp +++ b/mario/main.cpp @@ -20,8 +20,11 @@ #include "mario.hpp" #include "visitors/visitor_generator.hpp" -bool quit = false; +// TODO make shared scenes +#include "scenes/game_scenes.hpp" + bool update = false; +bool newLoaded = false; std::shared_ptr mario = nullptr; std::shared_ptr leftStop = nullptr; std::shared_ptr renderer = nullptr; @@ -31,14 +34,13 @@ int coin_count = 0; int global_frames = 0; std::vector> moving_objects = {}; +std::vector game_scenes{}; std::mutex render_mutex; +std::mutex gamescene_mutex; void handleKeyDown(SDL_Keycode key, SDLPP::Scene &scene) { switch (key) { - case SDLK_ESCAPE: - quit = true; - break; case SDLK_a: mario->walkLeft(); break; @@ -66,6 +68,12 @@ void handleKeyDown(SDL_Keycode key, SDLPP::Scene &scene) { void handleKeyUp(SDL_Keycode key) { switch (key) { + case SDLK_ESCAPE: + { + std::lock_guard lock(render_mutex); + game_scenes.push_back(createGameMainMenuScene(renderer)); + } + break; case SDLK_a: mario->walkRight(); break; @@ -112,7 +120,7 @@ void pollEvents(SDLPP::Scene &scene) { while (SDLPP::getSDLEvent(event)) { switch (event.type) { case SDL_QUIT: - quit = true; + g_quit = true; break; case SDL_KEYDOWN: if (!event.key.repeat) { @@ -135,80 +143,84 @@ void pollEvents(SDLPP::Scene &scene) { } } -void doInput(std::shared_ptr scene) { +void doInputMainGame(std::shared_ptr scene) { + pollEvents(*scene); + std::lock_guard lock(render_mutex); + scene->updateScene(); + auto prev_coin_count = coin_count; + auto rightmost_x = renderer->getDoubleDimensions().getX(); + for (size_t i = 0; i < moving_objects.size(); i++) { + moving_objects[i]->checkVisibility(rightmost_x); + if (!moving_objects[i]->wasVisible()) { + continue; + } + auto visitor = getVisitor(*moving_objects[i], *scene, g_quit, + coin_count, moving_objects); + scene->visitCollisions(*moving_objects[i], *visitor); + moving_objects[i]->handleVisitor(*visitor); + auto rightmost_pos = + moving_objects[i]->getAbsolutePos().getX() + + moving_objects[i]->getDoubleRect().second.getX(); + if (rightmost_pos < 0 && moving_objects[i] != mario) { + moving_objects[i]->destroy(); + } + } + std::vector killed_indices{}; + for (size_t i = 0; i < moving_objects.size(); i++) { + if (moving_objects[i]->getKilled()) { + killed_indices.push_back(i); + } + } + std::reverse(killed_indices.begin(), killed_indices.end()); + for (auto &index : killed_indices) { + moving_objects.erase(moving_objects.begin() + index); + } + + if (coin_count != prev_coin_count) { + coins->changeText(std::to_string(coin_count) + " COINS"); + } + // if player is > 0.7 of playground, move everything left + auto playerX = mario->getRect().x; + auto width = scene->getWidth(); + auto rightBarrier = width * 0.5; + auto rightmostX = + scene->rightmost()->getRect().x + scene->rightmost()->getRect().w; + scene->moveEverything((playerX > rightBarrier && rightmostX > width) * + (rightBarrier - playerX) / width, + 0); + update = update || (playerX > rightBarrier && rightmostX > width); + global_frames++; +} + +void doInput() { FPSmanager gFPS; SDL_initFramerate(&gFPS); SDL_setFramerate(&gFPS, 200); - while (!quit) { + while (!g_quit) { SDL_framerateDelay(&gFPS); - pollEvents(*scene); - std::lock_guard lock(render_mutex); - scene->updateScene(); - auto prev_coin_count = coin_count; - auto rightmost_x = renderer->getDoubleDimensions().getX(); - for (size_t i = 0; i < moving_objects.size(); i++) { - moving_objects[i]->checkVisibility(rightmost_x); - if (!moving_objects[i]->wasVisible()) { - continue; - } - auto visitor = getVisitor(*moving_objects[i], *scene, quit, - coin_count, moving_objects); - scene->visitCollisions(*moving_objects[i], *visitor); - moving_objects[i]->handleVisitor(*visitor); - auto rightmost_pos = - moving_objects[i]->getAbsolutePos().getX() + - moving_objects[i]->getDoubleRect().second.getX(); - if (rightmost_pos < 0 && moving_objects[i] != mario) { - moving_objects[i]->destroy(); - } - } - std::vector killed_indices{}; - for (size_t i = 0; i < moving_objects.size(); i++) { - if (moving_objects[i]->getKilled()) { - killed_indices.push_back(i); - } - } - std::reverse(killed_indices.begin(), killed_indices.end()); - for (auto &index : killed_indices) { - moving_objects.erase(moving_objects.begin() + index); - } - - if (coin_count != prev_coin_count) { - coins->changeText(std::to_string(coin_count) + " COINS"); - } - // if player is > 0.7 of playground, move everything left - auto playerX = mario->getRect().x; - auto width = scene->getWidth(); - auto rightBarrier = width * 0.5; - auto rightmostX = - scene->rightmost()->getRect().x + scene->rightmost()->getRect().w; - scene->moveEverything((playerX > rightBarrier && rightmostX > width) * - (rightBarrier - playerX) / width, - 0); - update = update || (playerX > rightBarrier && rightmostX > width); - global_frames++; + std::lock_guard lock(gamescene_mutex); + game_scenes.back().doInput(game_scenes.back().scene); + game_scenes.back().scene->updateScene(); } } -#ifdef _WIN32 -int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, - PWSTR szCmdLine, int nCmdShow) { -#else -int main() { -#endif - SDLPP::init(); - SDLPP::Window w("Mario clone!"); - w.setResizable(true); - - renderer = std::make_shared(w); - renderer->setBlendMode(SDL_BLENDMODE_BLEND); - - // prepare global vars - g_terrain_texture = std::make_shared( - renderer, "sprites/terrain.png", MARIO_OVERWORLD_COLORKEY); - g_enemies_texture = std::make_shared( - renderer, "sprites/enemies.png", MARIO_OVERWORLD_COLORKEY); +void mainGameAdditional(std::shared_ptr &/*UNUSED*/) { + static auto base = SDL_GetTicks(); + static int frames = 0; + mario->setStanding(); + frames++; + if (SDL_GetTicks() - base >= 1000) { + if (global_frames < frames) { + frames = global_frames; + } + global_frames = 0; + fps->changeText(std::to_string(frames) + " fps"); + frames = 0; + base = SDL_GetTicks(); + } +} +SceneStruct mainGameScene(const std::string &level_path) { auto scene = std::make_shared(renderer); g_playground = scene; auto bg = std::make_shared( @@ -217,11 +229,7 @@ int main() { bg->setStatic(); bg->setId(1); scene->addObject(bg); - g_mario_texture = std::make_shared( - renderer, "sprites/mario.png", MARIO_OVERWORLD_COLORKEY); - g_translucent_terrain_texture = std::make_shared( - renderer, "sprites/terrain.png", MARIO_OVERWORLD_COLORKEY); - g_translucent_terrain_texture->setAlpha(100); + mario = std::make_shared(renderer); scene->addObject(mario); @@ -247,7 +255,7 @@ int main() { leftStop->setColiderColor("#FF00FF"); scene->addObject(leftStop); - loadMap(scene, mario, "test_binary2.bin"); + loadMap(scene, mario, level_path); auto font = std::make_shared("testfont.ttf", 36); fps = std::make_shared( @@ -266,15 +274,7 @@ int main() { coins->setId(0); coins->setPermanent(); scene->addObject(coins); - - FPSmanager gFPS; - SDL_initFramerate(&gFPS); - SDL_setFramerate(&gFPS, 60); - - auto base = SDL_GetTicks(); - int frames = 0; scene->moveEverything(-mario->getDoubleRect().first.getX() + 0.2, 0); - update = true; std::unordered_set background_ids = { HILL_INCLINE_ID, HILL_DECLINE_ID, HILL_DOTS_RIGHT_ID, @@ -290,6 +290,7 @@ int main() { scene->updateBackgroundObjectZIndex(); // we want mario to be first because visiting isn't perfect + moving_objects.clear(); moving_objects.push_back(mario); std::unordered_set moving_object_ids = { GOOMBA_ID, @@ -298,34 +299,96 @@ int main() { moving_objects.push_back(std::dynamic_pointer_cast(obj)); } - std::thread inputThread(doInput, scene); + SceneStruct ret{}; + ret.scene = scene; + ret.doInput = doInputMainGame; + ret.additionalRender = mainGameAdditional; + + return ret; +} + +void loadLevel(const std::string &level) { + //std::lock_guard lock(render_mutex); + coin_count = 0; + std::lock_guard lock(gamescene_mutex); + game_scenes.clear(); + game_scenes.push_back(mainGameScene("levels/" + level)); + game_scenes.back().scene->updateSizeAndPosition(); + update = true; + newLoaded = true; +} + +#ifdef _WIN32 +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + PWSTR szCmdLine, int nCmdShow) { +#else +int main() { +#endif + SDLPP::init(); + SDLPP::Window w("Mario clone!"); + w.setResizable(true); + + renderer = std::make_shared(w); + renderer->setBlendMode(SDL_BLENDMODE_BLEND); + + // prepare global vars + g_terrain_texture = std::make_shared( + renderer, "sprites/terrain.png", MARIO_OVERWORLD_COLORKEY); + g_enemies_texture = std::make_shared( + renderer, "sprites/enemies.png", MARIO_OVERWORLD_COLORKEY); + + g_mario_texture = std::make_shared( + renderer, "sprites/mario.png", MARIO_OVERWORLD_COLORKEY); + g_translucent_terrain_texture = std::make_shared( + renderer, "sprites/terrain.png", MARIO_OVERWORLD_COLORKEY); + g_translucent_terrain_texture->setAlpha(100); + + FPSmanager gFPS; + SDL_initFramerate(&gFPS); + SDL_setFramerate(&gFPS, 60); + + auto font = std::make_shared("testfont.ttf", 36); + g_text_config = std::make_shared(font, "#FFFFFF", + "#000000", 0.15); + game_scenes.push_back(createGameMainMenuScene(renderer, false)); + + std::thread inputThread(doInput); SDL_PumpEvents(); - scene->updateSizeAndPosition(); - scene->renderScene(); + // TODO main menu +/* game_scenes.push_back(mainGameScene("levels/test.marmap")); + game_scenes.back().scene->updateSizeAndPosition(); + game_scenes.back().scene->renderScene(); + renderer->presentRenderer();*/ + game_scenes.back().scene->updateSizeAndPosition(); + game_scenes.back().scene->renderScene(); renderer->presentRenderer(); update = true; - while (!quit) { + while (!g_quit) { SDL_framerateDelay(&gFPS); SDL_PumpEvents(); std::lock_guard lock(render_mutex); - mario->setStanding(); - if (update) { - scene->updateSizeAndPosition(); - update = false; - } - scene->renderScene(); - renderer->presentRenderer(); - frames++; - if (SDL_GetTicks() - base >= 1000) { - if (global_frames < frames) { - frames = global_frames; + if (update || newLoaded) { + for(auto &scene : game_scenes) { + scene.scene->updateSizeAndPosition(); + } + if(newLoaded) { + newLoaded = false; + } else { + update = false; } - global_frames = 0; - fps->changeText(std::to_string(frames) + " fps"); - frames = 0; - base = SDL_GetTicks(); } + auto max_game_scenes = game_scenes.size(); + renderer->clearRenderer(); + for (size_t i = 0; i < max_game_scenes; i++) { + game_scenes[i].additionalRender(game_scenes[i].scene); + // additional renderer can remove scene from game_scenes, better + // check + if (i < game_scenes.size()) { + game_scenes[i].scene->renderScene(false); + } + } + renderer->presentRenderer(); } inputThread.join(); diff --git a/mario/scenes/editor_main.cpp b/mario/scenes/editor_main.cpp index 0d50f30..f25abd8 100644 --- a/mario/scenes/editor_main.cpp +++ b/mario/scenes/editor_main.cpp @@ -1052,6 +1052,13 @@ void openMapEditor(std::shared_ptr &scene, } else { loadMap(scene, global_vars.mario, filename, global_vars.objects, true, MAP_WIDTH); + for(int i = 0; i < global_vars.objects.size(); i++) { + for(int j = 0; j < 16; j++) { + if(global_vars.objects[i][j].hasCharacter() && global_vars.objects[i][j].getCharacterId() == MARIO_ID) { + global_vars.mario_pos = {i,j}; + } + } + } } // map @@ -1368,4 +1375,4 @@ SceneStruct createEditorScene(std::shared_ptr &renderer) { mainMenuScene = createEditorMainMenuScene(renderer); // fileChoiceScene = createEditorFileChoiceScene(renderer); return ret; -} \ No newline at end of file +} diff --git a/mario/scenes/editor_scenes.hpp b/mario/scenes/editor_scenes.hpp index 1a72d86..d5df0cc 100644 --- a/mario/scenes/editor_scenes.hpp +++ b/mario/scenes/editor_scenes.hpp @@ -1,15 +1,10 @@ -#ifndef EDITOR_MAIN_HPP -#define EDITOR_MAIN_HPP +#ifndef EDITOR_SCENES_HPP +#define EDITOR_SCENES_HPP #include "../../sdlpp/sdlpp_scene.hpp" #include "../gui/gui.hpp" #include - -struct SceneStruct { - std::shared_ptr scene; - std::function &)> doInput; - std::function &)> additionalRender; -}; +#include "shared_scenes.hpp" extern std::mutex render_mutex; extern std::vector game_scenes; @@ -22,15 +17,5 @@ SceneStruct createEditorMainMenuScene(std::shared_ptr &renderer); SceneStruct createEditorFileChoiceScene(std::shared_ptr &renderer); -// TODO move to a shared header -SceneStruct createYesNoScene(std::shared_ptr renderer, - const std::string &text, - std::function finalizer); -SceneStruct createOkScene(std::shared_ptr renderer, - const std::string &text, - std::function finalizer); -SceneStruct createLoadScene(std::shared_ptr renderer, - const std::string &path, - std::function finalizer); #endif \ No newline at end of file diff --git a/mario/scenes/game_main_menu.cpp b/mario/scenes/game_main_menu.cpp new file mode 100644 index 0000000..50dbf6a --- /dev/null +++ b/mario/scenes/game_main_menu.cpp @@ -0,0 +1,229 @@ +#include "editor_scenes.hpp" +#include "../../sdlpp/sdlpp.hpp" +#include "../../sdlpp/sdlpp_mouse.hpp" +#include "../global_vars.hpp" +#include "../objectids.hpp" +#include "../editor_visitor.hpp" +#include + +bool __update_scenes_main_menu = false; +bool __quit_scenes_main_menu = false; +bool __started_main_menu = false; +uint64_t __cur_button_index_main_menu = -1; +uint64_t __cur_button_index_main_menu_down = -1; +std::vector> __buttons_main_menu{}; +std::shared_ptr __mouse_main_menu{}; + +extern void loadLevel(const std::string &level); + +void quitMainMenu() { + g_quit = true; +} + +void resumeMainMenu() { + __quit_scenes_main_menu = true; +} + +void quitMainMenuCallback(void * /*UNUSED*/, Button * /*UNUSED*/) { + quitMainMenu(); +} + +void resumeMainMenuCallback(void * /*UNUSED*/, Button * /*UNUSED*/) { + resumeMainMenu(); +} + +void resetGlobals() { + __update_scenes_main_menu = false; + __quit_scenes_main_menu = false; + __started_main_menu = false; + __cur_button_index_main_menu_down = -1; + __mouse_main_menu.reset(); + __buttons_main_menu.clear(); +} + +void showLoadMenu(void */*UNUSED*/, Button */*UNUSED*/) { + auto loadMenu = createLoadScene(__buttons_main_menu.back()->getRenderer(), "levels", loadLevel, false); + std::lock_guard lock(render_mutex); + game_scenes.pop_back(); + resetGlobals(); + game_scenes.push_back(loadMenu); +} + +void __updateSelectedButton_MainMenu(uint64_t new_index) { + if (new_index != __cur_button_index_main_menu && + new_index != (uint64_t)-1) { + __buttons_main_menu[new_index]->setHighlight(); + + if (__cur_button_index_main_menu != (uint64_t)-1) { + __buttons_main_menu[__cur_button_index_main_menu] + ->unsetHighlight(); + } + __cur_button_index_main_menu = new_index; + } +} + +void handleKeyUpMainMenu(SDL_Keycode key, SDLPP::Scene & /*UNUSED*/) { + switch (key) { + case SDLK_ESCAPE: + resumeMainMenu(); + break; + case SDLK_DOWN: + case SDLK_s: + if(__cur_button_index_main_menu == __buttons_main_menu.size() - 1) { + __updateSelectedButton_MainMenu(0); + } else { + __updateSelectedButton_MainMenu(__cur_button_index_main_menu + 1); + } + break; + case SDLK_UP: + case SDLK_w: + if(__cur_button_index_main_menu == 0) { + __updateSelectedButton_MainMenu(__buttons_main_menu.size() - 1); + } else { + __updateSelectedButton_MainMenu(__cur_button_index_main_menu - 1); + } + break; + case SDLK_RETURN: + if(__cur_button_index_main_menu >= 0 && __cur_button_index_main_menu < __buttons_main_menu.size()) { + __buttons_main_menu[__cur_button_index_main_menu] + ->performFunction(); + } + break; + default: + break; + } +} + +std::shared_ptr +createSceneMainMenu(std::shared_ptr &renderer, bool include_resume) { + auto scene = std::make_shared(renderer); + auto bg = std::make_shared(0, 0, 10, 10, renderer, + "#00000088", true); + bg->setPermanent(); + bg->setId(1); + scene->addObject(bg); + __mouse_main_menu = + std::make_shared(0.01, 0.01, 0, 0, renderer); + __mouse_main_menu->setMinWidth(1); + __mouse_main_menu->setMinHeight(1); + __mouse_main_menu->setAlignment(SDLPP::OBJ_CENTER, SDLPP::OBJ_CENTER); + __mouse_main_menu->setId(EDITOR_MOUSE_ID); + __mouse_main_menu->setColiderColor("#00FF00"); + __mouse_main_menu->addCollision(SDLPP::RectColider({ 0, 0 }, { 1, 1 })); + scene->addObject(__mouse_main_menu); + + ButtonConfig default_button_theme{}; + default_button_theme.bg_color = "#FFFFFF88"; + default_button_theme.bg_color_highlight = "#FFFFFFBB"; + default_button_theme.bg_color_disabled = "#AAAAAA88"; + default_button_theme.font_color = "#000000"; + default_button_theme.font_color_highlight = "#000000"; + default_button_theme.font_color_disabled = "#555555"; + default_button_theme.font_outline_color = "#FFFFFF88"; + default_button_theme.font_outline_color_highlight = "#FFFFFFAA"; + default_button_theme.font_outline_color_disabled = "#787878"; + default_button_theme.outline = 0.1; + // buttons + if(include_resume) { + __buttons_main_menu.emplace_back(std::make_shared