Skip to content
Snippets Groups Projects
Select Git revision
  • c5a9fd3b19ad4b43257f8bfbe1c18602e21168ba
  • main default protected
  • leveleditor
  • david-author
  • clang-tidy-cleanup
  • architecture-refactoring
  • cleanUpMenus
  • doxygen-cleanup
  • project-structure-refactoring
  • interpolation
  • buildingFeatures
  • win_end_screen
  • helpMenu
  • leveleditor-placement
  • text-rendering
  • updated_unit_contextmenu
  • level-from-commandline
  • unit_contextmenu
  • player
  • engine-scaling
  • clang-tidy
21 results

Menu.cpp

Blame
  • Menu.cpp 7.58 KiB
    #include "Menu.hpp"
    #include "../Building.hpp"
    #include "../Level.hpp"
    #include "../Spritesheet.hpp"
    #include "../Tile.hpp"
    #include "../Unit.hpp"
    #include <SDL.h>
    #include <SDL_image.h>
    #include <SDL_ttf.h>
    #include <iostream>
    #include <string>
    
    namespace advanced_wars
    {
    
    Menu::Menu(int selectedOption)
        : m_selectedOption(selectedOption), m_options({"Start Game", "Options", "Exit"}),
          m_backgroundTexture(nullptr)
    {
    }
    
    Menu::~Menu()
    {
        if (m_backgroundTexture)
        {
            SDL_DestroyTexture(m_backgroundTexture);
        }
    }
    
    void Menu::render(Engine& engine)
    {
        if (TTF_Init() == -1)
        {
            std::cerr << "Failed to initialize TTF: " << TTF_GetError() << std::endl;
            return;
        }
    
        if (m_backgroundTexture)
        {
            SDL_RenderCopy(engine.renderer(), m_backgroundTexture, nullptr, nullptr);
        }
        else
        {
            SDL_SetRenderDrawColor(engine.renderer(), 0, 0, 0, 255);
            SDL_RenderClear(engine.renderer());
        }
    
        std::string basePath = SDL_GetBasePath();
        std::string relativePath = "res/ARCADECLASSIC.TTF";
        std::string fullPath = basePath + relativePath;
        TTF_Font*   titleFont = TTF_OpenFont(fullPath.c_str(), 48);
        if (!titleFont)
        {
            std::cerr << "Failed to load title font: " << fullPath << TTF_GetError() << std::endl;
            return;
        }
    
        TTF_Font* menuFont = TTF_OpenFont(fullPath.c_str(), 24);
        if (!menuFont)
        {
            TTF_CloseFont(titleFont);
            std::cerr << "Failed to load menu font: " << fullPath << TTF_GetError() << std::endl;
            return;
        }
    
        SDL_Color white = {255, 255, 255, 255};
        SDL_Color yellow = {255, 255, 0, 255};
    
        SDL_Surface* titleSurface = TTF_RenderText_Solid(titleFont, "Advanced Wars", white);
        if (titleSurface)
        {
            SDL_Texture* titleTexture = SDL_CreateTextureFromSurface(engine.renderer(), titleSurface);
            SDL_Rect     titleRect = {
                static_cast<int>((800 - titleSurface->w) / 2), 50, titleSurface->w, titleSurface->h};
            SDL_RenderCopy(engine.renderer(), titleTexture, nullptr, &titleRect);
            SDL_DestroyTexture(titleTexture);
            SDL_FreeSurface(titleSurface);
        }
    
        for (size_t i = 0; i < m_options.size(); ++i)
        {
            SDL_Surface* textSurface = TTF_RenderText_Solid(
                menuFont, m_options[i].c_str(), (i == m_selectedOption) ? yellow : white);
            if (!textSurface)
            {
                continue;
            }
    
            SDL_Texture* textTexture = SDL_CreateTextureFromSurface(engine.renderer(), textSurface);
            SDL_Rect     textRect = {
                static_cast<int>((800 - textSurface->w) / 2), static_cast<int>(150 + i * 50),
                textSurface->w, textSurface->h};
            SDL_RenderCopy(engine.renderer(), textTexture, nullptr, &textRect);
    
            SDL_DestroyTexture(textTexture);
            SDL_FreeSurface(textSurface);
        }
    
        TTF_CloseFont(titleFont);
        TTF_CloseFont(menuFont);
    
        TTF_Quit();
    }
    
    void Menu::handleEvent(Engine& engine, SDL_Event& event)
    {
        if (event.type == SDL_KEYDOWN)
        {
            if (event.key.keysym.sym == SDLK_DOWN)
            {
                m_selectedOption = (m_selectedOption + 1) % m_options.size();
            }
            else if (event.key.keysym.sym == SDLK_UP)
            {
                m_selectedOption = (m_selectedOption - 1 + m_options.size()) % m_options.size();
            }
            else if (event.key.keysym.sym == SDLK_RETURN)
            {
                if (m_options[m_selectedOption] == "Exit")
                {
                    std::cout << "Exiting game..." << std::endl;
                    engine.exit();
                }
                else if (m_options[m_selectedOption] == "Start Game")
                {
                    std::cout << "Starting game..." << std::endl;
    
                    // Construct a level
                    std::vector<Tile> tiles;
                    for (int y = 0; y < 20; y++)
                    {
                        for (int x = 0; x < 20; x++)
                        {
                            tiles.push_back(Tile(TileId::PLAIN, x, y));
                        }
                    }
    
                    // Fill the edges with water
                    for (size_t n = 0; n < 20; n++)
                    {
                        // Vertical
                        tiles.at(n * 20) = Tile(TileId::WATER, 0, n);
                        tiles.at(n * 20 + 19) = Tile(TileId::WATER, 19, n);
                        // Horizontal
                        tiles.at(n) = Tile(TileId::WATER, n, 0);
                        tiles.at(19 * 20 + n) = Tile(TileId::WATER, n, 19);
                    }
    
                    // Make the edges cliffs
                    for (size_t n = 1; n < 19; n++)
                    {
                        // Vertical
                        tiles.at(n * 20 + 1) = Tile(TileId::CLIFF_RIGHT, 1, n);
                        tiles.at(n * 20 + 18) = Tile(TileId::CLIFF_LEFT, 18, n);
    
                        // Horizontal
                        tiles.at(20 + n) = Tile(TileId::CLIFF_BOTTOM, n, 1);
                        tiles.at(18 * 20 + n) = Tile(TileId::CLIFF_TOP, n, 18);
                    }
    
                    // Fix the corners
                    tiles.at(20 + 1) = Tile(TileId::CLIFF_CORNER_TOP_LEFT, 1, 1);
                    tiles.at(20 + 18) = Tile(TileId::CLIFF_CORNER_TOP_RIGHT, 18, 1);
                    tiles.at(18 * 20 + 1) = Tile(TileId::CLIFF_CORNER_BOTTOM_LEFT, 1, 18);
                    tiles.at(18 * 20 + 18) = Tile(TileId::CLIFF_CORNER_BOTTOM_RIGHT, 18, 18);
    
                    // Buildings
                    std::vector<Building> buildings;
    
                    for (int y = 0; y < 6; y++)
                    {
                        for (int x = 0; x < 5; x++)
                        {
                            BuildingId      id = static_cast<BuildingId>(x);
                            BuildingFaction faction = static_cast<BuildingFaction>(y);
    
                            buildings.push_back(Building(3 + x, 3 + 2 * y, id, faction));
                        }
                    }
    
                    // Units
                    std::vector<Unit> units;
    
                    for (int y = 0; y < 19; y++)
                    {
                        for (int x = 0; x < 6; x++)
                        {
                            units.push_back(Unit(
                                x + 9, y + 2, UnitFaction::URED, static_cast<UnitId>(y),
                                static_cast<UnitState>(x)));
                        }
                    }
    
                    std::vector<Effect> effects(
                        {Effect(3, 15, EffectId::LAND_EXPLOSION, false),
                         Effect(5, 15, EffectId::AIR_EXPLOSION, true),
                         Effect(5, 18, EffectId::NAVAL_EXPLOSION, true)});
    
                    std::shared_ptr<Level> level =
                        std::make_shared<Level>("Osnabrück", 20, 20, tiles, buildings, units, effects);
    
                    engine.pushScene(level);
                }
                else if (m_options[m_selectedOption] == "Options")
                {
                    std::cout << "Opening options..." << std::endl;
                }
            }
        }
    }
    
    void Menu::loadBackground(Engine& engine, const std::string& imagePath)
    {
        // Lade das Hintergrundbild
        SDL_Surface* backgroundSurface = IMG_Load(imagePath.c_str());
        if (!backgroundSurface)
        {
            std::cerr << "Failed to load background image: " << IMG_GetError() << std::endl;
            return;
        }
    
        // Erstelle eine Textur aus der Oberfläche und speichere sie als
        // Klassenmitglied
        m_backgroundTexture = SDL_CreateTextureFromSurface(engine.renderer(), backgroundSurface);
        SDL_FreeSurface(backgroundSurface); // Oberfläche freigeben, da sie nicht mehr
                                            // benötigt wird
    
        if (!m_backgroundTexture)
        {
            std::cerr << "Failed to create background texture: " << SDL_GetError() << std::endl;
        }
    }
    
    } // namespace advanced_wars