From bb46f3f68e5c5108dfff3bd9054bc2ce96463fc5 Mon Sep 17 00:00:00 2001 From: Nicolas Will <nicolas.will01@gmail.com> Date: Mon, 3 Feb 2025 10:48:34 +0100 Subject: [PATCH 01/20] render context menu at unit --- src/game/Level.cpp | 10 +++++----- src/game/ui/Menu.cpp | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 67e35e5..87a7d1d 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -183,22 +183,21 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) { case SDL_MOUSEBUTTONDOWN: - m_contextMenu.update(event.button.x, event.button.y); - m_contextMenuActive = true; - // the current unit debug combat should be handled by the contextmenu with its menu options if (event.button.button == SDL_BUTTON_LEFT) { int tileX = event.button.x / (16 * RENDERING_SCALE); int tileY = event.button.y / (16 * RENDERING_SCALE); - if (clickCheckLeft(tileX, tileY)) { - if (m_selectedUnit > -1) { m_units.at(m_selectedUnit).on_left_click(event); + int menuPositionX = (tileX * 16 + 12) * RENDERING_SCALE; + int menuPositionY = (tileY * 16 + 12) * RENDERING_SCALE; + m_contextMenu.update(menuPositionX, menuPositionY); + m_contextMenuActive = true; } if (m_selectedBuilding > -1) @@ -212,6 +211,7 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) std::cout << "Neither building nor unit clicked!" << std::endl; m_selectedUnit = -1; m_selectedBuilding = -1; + m_contextMenuActive = false; } } else if (event.button.button == SDL_BUTTON_RIGHT) diff --git a/src/game/ui/Menu.cpp b/src/game/ui/Menu.cpp index 392209b..0ea5ba9 100644 --- a/src/game/ui/Menu.cpp +++ b/src/game/ui/Menu.cpp @@ -99,7 +99,6 @@ void Menu::render(Engine& engine) TTF_CloseFont(titleFont); TTF_CloseFont(menuFont); - SDL_RenderPresent(engine.renderer()); TTF_Quit(); } -- GitLab From 150d7df5991eed082330b815b7b7f0ecada4a016 Mon Sep 17 00:00:00 2001 From: Nicolas Will <nicolas.will01@gmail.com> Date: Tue, 4 Feb 2025 11:36:59 +0100 Subject: [PATCH 02/20] add TileMarker class. Add TileMarker member to level --- src/game/Level.cpp | 3 ++- src/game/Level.hpp | 2 ++ src/game/ui/TileMarker.cpp | 27 +++++++++++++++++++++++++++ src/game/ui/TileMarker.hpp | 29 +++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/game/ui/TileMarker.cpp create mode 100644 src/game/ui/TileMarker.hpp diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 87a7d1d..2e22cab 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -23,7 +23,7 @@ Level::Level( std::string name, int width, int height, std::vector<Tile> tiles, std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect> effects) : m_name(name), m_width(width), m_height(height), m_tiles(tiles), m_contextMenu(ContextMenu()), - m_contextMenuActive(false), m_id(0) + m_contextMenuActive(false), m_currentPos(TileMarker(RENDERING_SCALE, 1, 1)), m_id(0) { m_contextMenu.setOptions({"Move", "Info", "Wait"}); @@ -330,6 +330,7 @@ void Level::render(Engine& engine) { m_contextMenu.render(engine); } + m_currentPos.render(engine); } int Level::addBuilding(Building building) diff --git a/src/game/Level.hpp b/src/game/Level.hpp index 49c076f..10cb757 100644 --- a/src/game/Level.hpp +++ b/src/game/Level.hpp @@ -7,6 +7,7 @@ #include "Tile.hpp" #include "Unit.hpp" #include "ui/Contextmenu.hpp" +#include "ui/TileMarker.hpp" #include <SDL.h> #include <string> #include <unordered_map> @@ -58,6 +59,7 @@ class Level : public Scene int m_selectedBuilding; ContextMenu m_contextMenu; + TileMarker m_currentPos; bool m_contextMenuActive; int m_id; diff --git a/src/game/ui/TileMarker.cpp b/src/game/ui/TileMarker.cpp new file mode 100644 index 0000000..eb2f654 --- /dev/null +++ b/src/game/ui/TileMarker.cpp @@ -0,0 +1,27 @@ +#include "TileMarker.hpp" + +namespace advanced_wars +{ +TileMarker::TileMarker(int renderingScale, int tileX, int tileY) + : m_renderingScale(renderingScale), m_width(16), m_height(16) +{ + updatePosition(tileX, tileY); +} + +void TileMarker::updatePosition(int TileX, int TileY) +{ + int tileSize = 16 * m_renderingScale; + m_x = TileX * tileSize; + m_y = TileY * tileSize + (tileSize - m_height); +} + +void TileMarker::render(Engine& engine) +{ + SDL_SetRenderDrawColor(engine.renderer(), 255, 0, 0, 255); + SDL_Rect box = {m_x, m_y, m_width, m_height}; + SDL_RenderFillRect(engine.renderer(), &box); +} + +void TileMarker::handleEvent(Engine& engine, SDL_Event& event) {} + +} // namespace advanced_wars diff --git a/src/game/ui/TileMarker.hpp b/src/game/ui/TileMarker.hpp new file mode 100644 index 0000000..19a3dff --- /dev/null +++ b/src/game/ui/TileMarker.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "../Scene.hpp" + +namespace advanced_wars +{ +/** + * @class TileMarker + * @brief Renders a marker on top of a tile to mark current position + * + */ +class TileMarker : public Scene +{ + public: + TileMarker(int renderingScale, int tileX, int tileY); + + void render(Engine& engine) override; + + void handleEvent(Engine& engine, SDL_Event& event) override; + + void updatePosition(int TileX, int TileY); + + private: + int m_x; + int m_y; + int m_renderingScale; + int m_width; + int m_height; +}; +} // namespace advanced_wars \ No newline at end of file -- GitLab From 46477af5bfd7039c491251921c160a3408a47b13 Mon Sep 17 00:00:00 2001 From: Nicolas Will <nicolas.will01@gmail.com> Date: Tue, 4 Feb 2025 13:48:02 +0100 Subject: [PATCH 03/20] add eventhandling TileMarker --- src/game/Level.cpp | 11 +++++- src/game/ui/TileMarker.cpp | 78 +++++++++++++++++++++++++++++++++----- src/game/ui/TileMarker.hpp | 6 ++- 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 2e22cab..7798ee3 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -23,7 +23,8 @@ Level::Level( std::string name, int width, int height, std::vector<Tile> tiles, std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect> effects) : m_name(name), m_width(width), m_height(height), m_tiles(tiles), m_contextMenu(ContextMenu()), - m_contextMenuActive(false), m_currentPos(TileMarker(RENDERING_SCALE, 1, 1)), m_id(0) + m_contextMenuActive(false), + m_currentPos(TileMarker(RENDERING_SCALE, 1, 1, m_width, m_height)), m_id(0) { m_contextMenu.setOptions({"Move", "Info", "Wait"}); @@ -273,6 +274,14 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) m_contextMenu.handleEvent(engine, event); } } + else + { + if (event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || + event.key.keysym.sym == SDLK_RIGHT || event.key.keysym.sym == SDLK_LEFT) + { + m_currentPos.handleEvent(engine, event); + } + } break; } } diff --git a/src/game/ui/TileMarker.cpp b/src/game/ui/TileMarker.cpp index eb2f654..9f6449c 100644 --- a/src/game/ui/TileMarker.cpp +++ b/src/game/ui/TileMarker.cpp @@ -1,18 +1,16 @@ #include "TileMarker.hpp" +#include <iostream> namespace advanced_wars { -TileMarker::TileMarker(int renderingScale, int tileX, int tileY) +TileMarker::TileMarker(int renderingScale, int tileX, int tileY, int levelWidth, int levelHeight) : m_renderingScale(renderingScale), m_width(16), m_height(16) { - updatePosition(tileX, tileY); -} - -void TileMarker::updatePosition(int TileX, int TileY) -{ - int tileSize = 16 * m_renderingScale; - m_x = TileX * tileSize; - m_y = TileY * tileSize + (tileSize - m_height); + int tileSize = 16 * renderingScale; + m_x = tileX * tileSize; + m_y = tileY * tileSize + (tileSize - m_height); + m_levelWidth = levelWidth * tileSize; + m_levelHeight = levelHeight * tileSize; } void TileMarker::render(Engine& engine) @@ -22,6 +20,66 @@ void TileMarker::render(Engine& engine) SDL_RenderFillRect(engine.renderer(), &box); } -void TileMarker::handleEvent(Engine& engine, SDL_Event& event) {} +void TileMarker::handleEvent(Engine& engine, SDL_Event& event) +{ + if (event.type == SDL_KEYDOWN) + { + int newX; + int newY; + switch (event.key.keysym.sym) + { + case SDLK_UP: + newY = m_y - 16 * m_renderingScale; + std::cout << "New Y: " << newY << std::endl; + if (newY <= 0) + { + break; + } + m_y = newY; + break; + case SDLK_DOWN: + newY = m_y + 16 * m_renderingScale; + std::cout << "New Y: " << newY << std::endl; + + if (newY >= m_levelHeight) + + { + break; + } + m_y = newY; + break; + case SDLK_RIGHT: + newX = m_x + 16 * m_renderingScale; + std::cout << "New X: " << newX << std::endl; + + if (newX >= m_levelWidth) + { + break; + } + m_x = newX; + break; + case SDLK_LEFT: + newX = m_x - 16 * m_renderingScale; + std::cout << "New X: " << newX << std::endl; + + if (newX <= 0) + { + break; + } + m_x = newX; + break; + + default: + break; + } + } +} + +std::pair<int, int> TileMarker::getPosition() +{ + int tileX = m_x / (16 * m_renderingScale); + int tileY = m_y / (16 * m_renderingScale); + return {tileX, tileY}; +} } // namespace advanced_wars diff --git a/src/game/ui/TileMarker.hpp b/src/game/ui/TileMarker.hpp index 19a3dff..dbbd4b2 100644 --- a/src/game/ui/TileMarker.hpp +++ b/src/game/ui/TileMarker.hpp @@ -11,13 +11,13 @@ namespace advanced_wars class TileMarker : public Scene { public: - TileMarker(int renderingScale, int tileX, int tileY); + TileMarker(int renderingScale, int tileX, int tileY, int levelWidth, int levelHeight); void render(Engine& engine) override; void handleEvent(Engine& engine, SDL_Event& event) override; - void updatePosition(int TileX, int TileY); + std::pair<int, int> getPosition(); private: int m_x; @@ -25,5 +25,7 @@ class TileMarker : public Scene int m_renderingScale; int m_width; int m_height; + int m_levelHeight; + int m_levelWidth; }; } // namespace advanced_wars \ No newline at end of file -- GitLab From 693dd23a728e27749ed59dc6852e1710c888a0c1 Mon Sep 17 00:00:00 2001 From: Frederik <frederik@prasch.de> Date: Wed, 5 Feb 2025 14:37:35 +0100 Subject: [PATCH 04/20] Remove unused or double declarations from merge conflict --- src/game/Level.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/game/Level.hpp b/src/game/Level.hpp index f00e208..9df7382 100644 --- a/src/game/Level.hpp +++ b/src/game/Level.hpp @@ -87,19 +87,8 @@ class Level : public Scene int selectUnit(int tileX, int tileY); int selectBuilding(int tileX, int tileY); - ContextMenu m_contextMenu; - TileMarker m_currentPos; - bool m_contextMenuActive; + TileMarker m_currentPos; - int m_id; - - bool selectUnit(int tileX, int tileY); - bool targetUnit(int tileX, int tileY); - bool selectBuilding(int tileX, int tileY); - - bool clickCheckLeft(int mouseX, int mouseY); - bool clickCheckRight(int mouseX, int mouseY); - void handleSelectingEvents(Engine& engine, SDL_Event& event); void handleMenuActiveEvents(Engine& engine, SDL_Event& event); void handleMovementEvents(Engine& engine, SDL_Event& event); -- GitLab From f8e2c82cf838edc60cd4879c84096568ef6900ee Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 16:26:03 +0100 Subject: [PATCH 05/20] Add recruitingmenu.cpp --- src/game/ui/Recruitingmenu.cpp | 74 ++++++++++++++++++++++++++++++++++ src/game/ui/Recruitingmenu.hpp | 24 +++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/game/ui/Recruitingmenu.cpp create mode 100644 src/game/ui/Recruitingmenu.hpp diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp new file mode 100644 index 0000000..f51e018 --- /dev/null +++ b/src/game/ui/Recruitingmenu.cpp @@ -0,0 +1,74 @@ +#include "Recruitingmenu.hpp" +#include <iostream> +#include <SDL_ttf.h> + +namespace advanced_wars +{ + Recruitingmenu::Recruitingmenu() : m_selectedOption(0) { + + } + + void Recruitingmenu::setOptions(const std::vector<std::string>& newOptions) { + m_options = newOptions; + m_selectedOption = 0; + } + + void Recruitingmenu::render(Engine& engine) +{ + + if (TTF_Init() == -1) + { + std::cerr << "Failed to initialize TTF: " << TTF_GetError() << std::endl; + return; + } + + if (m_options.empty()) + { + // TODO handle somehow + return; + } + + std::string basePath = SDL_GetBasePath(); + std::string relativePath = "res/ARCADECLASSIC.TTF"; + std::string fullPath = basePath + relativePath; + TTF_Font* font = TTF_OpenFont(fullPath.c_str(), 16); + if (!font) + { + std::cerr << "Failed to load font: " << TTF_GetError() << std::endl; + return; + } + + SDL_Color white = {255, 255, 255, 255}; + SDL_Color yellow = {192, 255, 0, 255}; + + int spacing = 20; // Abstand zwischen den Optionen + // box around options + SDL_SetRenderDrawColor(engine.renderer(), 0, 0, 255, 255); + SDL_Rect box = {m_x, m_y - 3, 50, static_cast<int>(m_options.size() * spacing)}; + SDL_RenderFillRect(engine.renderer(), &box); + + SDL_SetRenderDrawColor(engine.renderer(), 0, 0, 0, 255); + + for (size_t i = 0; i < m_options.size(); ++i) + { + SDL_Surface* textSurface = TTF_RenderText_Solid( + font, m_options[i].c_str(), (i == m_selectedOption) ? yellow : white); + if (!textSurface) + { + continue; + } + + SDL_Texture* textTexture = SDL_CreateTextureFromSurface(engine.renderer(), textSurface); + SDL_Rect textRect = { + m_x + 10, m_y + static_cast<int>(i * spacing), textSurface->w, textSurface->h}; + SDL_RenderCopy(engine.renderer(), textTexture, nullptr, &textRect); + + SDL_DestroyTexture(textTexture); + SDL_FreeSurface(textSurface); + } + + TTF_CloseFont(font); + TTF_Quit(); +} + +}//namespace advance_wars \ No newline at end of file diff --git a/src/game/ui/Recruitingmenu.hpp b/src/game/ui/Recruitingmenu.hpp new file mode 100644 index 0000000..431ceed --- /dev/null +++ b/src/game/ui/Recruitingmenu.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "../Scene.hpp" + +namespace advanced_wars +{ + + class Recruitingmenu : public Scene { + + private: + size_t m_selectedOption; + std::vector<std::string> m_options; + int m_x; + int m_y; + + void setOptions(const std::vector<std::string>& newOptions); + + void render(Engine& engine) override; + + void handleEvent(Engine& engine, SDL_Event& event); + + }; + +} //namespace advanced_wars \ No newline at end of file -- GitLab From cb40f859c65e45d3b4f3c1bead8cf84773849eee Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 17:02:02 +0100 Subject: [PATCH 06/20] Add basic recruitingMenu --- src/game/Level.cpp | 16 ++++++++++++++-- src/game/Level.hpp | 5 ++++- src/game/ui/Recruitingmenu.cpp | 33 ++++++++++++++++++++++++++++++--- src/game/ui/Recruitingmenu.hpp | 24 +++++++++++++++++++++--- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 77d3c9d..7daa01e 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -163,6 +163,8 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) case LevelState::ATTACKING_STATE: handleAttackingEvents(engine, event); break; + case LevelState::RECRUITING_STATE: + default: break; } @@ -212,6 +214,15 @@ void Level::render(Engine& engine) { m_contextMenu.render(engine); } + + if (m_state == LevelState::RECRUITING_STATE) + { + std::pair<int, int> tilePos = m_currentPos.getPosition(); + m_recruitingMenu.update( + (tilePos.first * 16 + 15) * RENDERING_SCALE, + (tilePos.second * 16 + 15) * RENDERING_SCALE); + m_recruitingMenu.render(engine); + } m_currentPos.render(engine); } @@ -350,8 +361,9 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event) } } if (cmd == "Train") - { - // hier Einheitenrekrutierung einsetzen + { + m_state = LevelState::RECRUITING_STATE; + m_recruitingMenu.setOptions({"Infantery", "Tank", "Artillery", "Medium", "Heavy", "Light"}); std::cout << "no training here" << std::endl; } } diff --git a/src/game/Level.hpp b/src/game/Level.hpp index 9df7382..16e7928 100644 --- a/src/game/Level.hpp +++ b/src/game/Level.hpp @@ -8,6 +8,7 @@ #include "Unit.hpp" #include "ui/Contextmenu.hpp" #include "ui/TileMarker.hpp" +#include "ui/Recruitingmenu.hpp" #include <SDL.h> #include <string> #include <unordered_map> @@ -22,7 +23,8 @@ enum class LevelState MOVEMENT_STATE, ANIMATING_STATE, MENUACTIVE_STATE, - ATTACKING_STATE + ATTACKING_STATE, + RECRUITING_STATE, }; /** @@ -79,6 +81,7 @@ class Level : public Scene int m_selectedUnit; int m_selectedBuilding; ContextMenu m_contextMenu; + RecruitingMenu m_recruitingMenu; int m_id; LevelState m_state; diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp index f51e018..7b05d48 100644 --- a/src/game/ui/Recruitingmenu.cpp +++ b/src/game/ui/Recruitingmenu.cpp @@ -4,16 +4,17 @@ namespace advanced_wars { - Recruitingmenu::Recruitingmenu() : m_selectedOption(0) { + RecruitingMenu::RecruitingMenu() : m_selectedOption(0) { } - void Recruitingmenu::setOptions(const std::vector<std::string>& newOptions) { + void RecruitingMenu::setOptions(const std::vector<std::string>& newOptions) { m_options = newOptions; m_selectedOption = 0; + renderableunit = {}; } - void Recruitingmenu::render(Engine& engine) + void RecruitingMenu::render(Engine& engine) { if (TTF_Init() == -1) @@ -71,4 +72,30 @@ namespace advanced_wars TTF_Quit(); } +void RecruitingMenu::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(); + } + } +} + +std::string RecruitingMenu::getSelectedOption() +{ + return m_options[m_selectedOption]; +} + +void RecruitingMenu::update(int x, int y) +{ + this->m_x = x; + this->m_y = y; +} + }//namespace advance_wars \ No newline at end of file diff --git a/src/game/ui/Recruitingmenu.hpp b/src/game/ui/Recruitingmenu.hpp index 431ceed..c19c1c4 100644 --- a/src/game/ui/Recruitingmenu.hpp +++ b/src/game/ui/Recruitingmenu.hpp @@ -5,20 +5,38 @@ namespace advanced_wars { - class Recruitingmenu : public Scene { + class RecruitingMenu : public Scene { private: + size_t m_selectedOption; std::vector<std::string> m_options; int m_x; int m_y; - void setOptions(const std::vector<std::string>& newOptions); + std::vector<std::vector<std::vector<std::pair<SDL_Texture *, int>>>> renderableunit; - void render(Engine& engine) override; + void handleEvent(Engine& engine, SDL_Event& event); + + + void selectSprite(); + + std::string getSelectedOption(); + + public: + + void update(int x, int y); + + RecruitingMenu(); + + void setOptions(const std::vector<std::string>& newOptions); + + void render(Engine& engine) override; + + }; } //namespace advanced_wars \ No newline at end of file -- GitLab From e986848d71a6e8b01e43090340adc0d2f5f0ac65 Mon Sep 17 00:00:00 2001 From: fdai7466 <nicolas-paul.will@hs-fulda.de> Date: Wed, 5 Feb 2025 17:07:09 +0100 Subject: [PATCH 07/20] add key navigation for selecting state --- src/game/Level.cpp | 26 ++++++++++++++++++++++++++ src/game/ui/TileMarker.cpp | 5 +++++ src/game/ui/TileMarker.hpp | 2 ++ 3 files changed, 33 insertions(+) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 77d3c9d..db7ec98 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -272,6 +272,31 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event) { engine.pushScene(std::make_shared<PauseMenu>(0, nullptr)); } + if(event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) + { + m_currentPos.handleEvent(engine, event); + } + if(event.key.keysym.sym == SDLK_RETURN){ + + std::pair<int, int> tilePos = m_currentPos.getPosition(); + std::cout << "TilePos: " << tilePos.first << " " << tilePos.second << std::endl; + selectEntity(tilePos.first * 16 * RENDERING_SCALE, tilePos.second* 16 * RENDERING_SCALE); + if (m_selectedUnit >= 0 || m_selectedBuilding >= 0) + { + m_contextMenu.update( + (tilePos.first * 16 + 15) * RENDERING_SCALE, + (tilePos.second * 16 + 15) * RENDERING_SCALE); + if (m_selectedUnit >= 0) + { + m_contextMenu.setOptions({"Move", "Attack", "Info", "Wait"}); + } + else + { + m_contextMenu.setOptions({"Train", "Info", "Wait"}); + } + m_state = LevelState::MENUACTIVE_STATE; + } + } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) @@ -280,6 +305,7 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event) if (m_selectedUnit >= 0 || m_selectedBuilding >= 0) { std::pair<int, int> tilePos = calcTilePos(event.button.x, event.button.y); + m_currentPos.setPosition(tilePos.first, tilePos.second); m_contextMenu.update( (tilePos.first * 16 + 15) * RENDERING_SCALE, (tilePos.second * 16 + 15) * RENDERING_SCALE); diff --git a/src/game/ui/TileMarker.cpp b/src/game/ui/TileMarker.cpp index 9f6449c..cfffcc6 100644 --- a/src/game/ui/TileMarker.cpp +++ b/src/game/ui/TileMarker.cpp @@ -82,4 +82,9 @@ std::pair<int, int> TileMarker::getPosition() return {tileX, tileY}; } +void TileMarker::setPosition(int tileX, int tileY){ + m_x = tileX * 16 * m_renderingScale; + m_y = tileY * 16 * m_renderingScale + (16 * m_renderingScale - m_height); +} + } // namespace advanced_wars diff --git a/src/game/ui/TileMarker.hpp b/src/game/ui/TileMarker.hpp index dbbd4b2..5b0225d 100644 --- a/src/game/ui/TileMarker.hpp +++ b/src/game/ui/TileMarker.hpp @@ -19,6 +19,8 @@ class TileMarker : public Scene std::pair<int, int> getPosition(); + void setPosition(int x, int y); + private: int m_x; int m_y; -- GitLab From 857e699a81a34be62b0efdb0bf3fc54d5aeec40a Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 17:07:42 +0100 Subject: [PATCH 08/20] Add smth --- src/game/Level.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 7daa01e..78f27be 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -217,10 +217,6 @@ void Level::render(Engine& engine) if (m_state == LevelState::RECRUITING_STATE) { - std::pair<int, int> tilePos = m_currentPos.getPosition(); - m_recruitingMenu.update( - (tilePos.first * 16 + 15) * RENDERING_SCALE, - (tilePos.second * 16 + 15) * RENDERING_SCALE); m_recruitingMenu.render(engine); } m_currentPos.render(engine); @@ -363,6 +359,10 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event) if (cmd == "Train") { m_state = LevelState::RECRUITING_STATE; + std::pair<int, int> tilePos = m_currentPos.getPosition(); + m_recruitingMenu.update( + (tilePos.first * 16 + 15) * RENDERING_SCALE, + (tilePos.second * 16 + 15) * RENDERING_SCALE); m_recruitingMenu.setOptions({"Infantery", "Tank", "Artillery", "Medium", "Heavy", "Light"}); std::cout << "no training here" << std::endl; } @@ -374,6 +374,7 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event) } } + void Level::handleMovementEvents(Engine& engine, SDL_Event& event) { switch (event.type) -- GitLab From 835af860829e135021537850aa99c7b5fc9c9b66 Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 17:35:57 +0100 Subject: [PATCH 09/20] Add texture rendering to recruitingmenu --- src/game/ui/Recruitingmenu.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp index 7b05d48..9ce8f27 100644 --- a/src/game/ui/Recruitingmenu.cpp +++ b/src/game/ui/Recruitingmenu.cpp @@ -1,6 +1,7 @@ #include "Recruitingmenu.hpp" #include <iostream> #include <SDL_ttf.h> +#include "../Unit.hpp" namespace advanced_wars { @@ -17,6 +18,8 @@ namespace advanced_wars void RecruitingMenu::render(Engine& engine) { + Spritesheet* spritesheet = engine.getSpritesheet(); + if (TTF_Init() == -1) { std::cerr << "Failed to initialize TTF: " << TTF_GetError() << std::endl; @@ -45,7 +48,7 @@ namespace advanced_wars int spacing = 20; // Abstand zwischen den Optionen // box around options SDL_SetRenderDrawColor(engine.renderer(), 0, 0, 255, 255); - SDL_Rect box = {m_x, m_y - 3, 50, static_cast<int>(m_options.size() * spacing)}; + SDL_Rect box = {m_x, m_y - 3, 125, static_cast<int>(m_options.size() * spacing)}; SDL_RenderFillRect(engine.renderer(), &box); SDL_SetRenderDrawColor(engine.renderer(), 0, 0, 0, 255); @@ -61,9 +64,24 @@ namespace advanced_wars SDL_Texture* textTexture = SDL_CreateTextureFromSurface(engine.renderer(), textSurface); SDL_Rect textRect = { - m_x + 10, m_y + static_cast<int>(i * spacing), textSurface->w, textSurface->h}; + m_x + 10 + 16, m_y + static_cast<int>(i * spacing), textSurface->w, textSurface->h}; SDL_RenderCopy(engine.renderer(), textTexture, nullptr, &textRect); + + SDL_Texture* unit_texture = spritesheet->getUnitTextures() + .at(static_cast<int>(UnitFaction::URED)) + .at(static_cast<int>(UnitId::INFANTERY)) + .at(static_cast<int>(UnitState::IDLE)) + .first; + + SDL_Rect rect = { + m_x + 5, // X-Position rechts neben dem Text + m_y + static_cast<int>(i * spacing), // Gleiche Y-Position wie der Text + 16, // Breite des Rechtecks + 16 // Höhe des Rechtecks entspricht der Texthöhe + }; + SDL_RenderCopy(engine.renderer(), unit_texture, nullptr, &rect); + SDL_DestroyTexture(textTexture); SDL_FreeSurface(textSurface); } -- GitLab From 02c11f5b040dbb72b26af8ae6e27498d9fd68bf6 Mon Sep 17 00:00:00 2001 From: fdai7466 <nicolas-paul.will@hs-fulda.de> Date: Wed, 5 Feb 2025 17:38:06 +0100 Subject: [PATCH 10/20] add key handling for movement --- src/game/Level.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index db7ec98..4c5beb1 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -395,11 +395,29 @@ void Level::handleMovementEvents(Engine& engine, SDL_Event& event) case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_RETURN) { + std::pair<int, int> tilePos = m_currentPos.getPosition(); + for (auto& [id, unit] : m_units) + { + if (unit.m_x == tilePos.first && unit.m_y == tilePos.second) + { + // unit already at clicked position (maybe even selected unit) + std::cout << "Unit already at clicked position" << std::endl; + return; + } + } + m_units.at(m_selectedUnit).updatePosition(tilePos.first, tilePos.second); + m_selectedUnit = -1; + m_state = LevelState::SELECTING_STATE; + } if (event.key.keysym.sym == SDLK_ESCAPE) { m_state = LevelState::MENUACTIVE_STATE; } + if(event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) + { + m_currentPos.handleEvent(engine, event); + } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) -- GitLab From d5286895d132ed67d3fad4f0ce21a92766400e3f Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 17:41:03 +0100 Subject: [PATCH 11/20] Correct rendering of unit textures --- src/game/ui/Recruitingmenu.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp index 9ce8f27..46f2e9f 100644 --- a/src/game/ui/Recruitingmenu.cpp +++ b/src/game/ui/Recruitingmenu.cpp @@ -74,13 +74,21 @@ namespace advanced_wars .at(static_cast<int>(UnitState::IDLE)) .first; - SDL_Rect rect = { - m_x + 5, // X-Position rechts neben dem Text - m_y + static_cast<int>(i * spacing), // Gleiche Y-Position wie der Text - 16, // Breite des Rechtecks - 16 // Höhe des Rechtecks entspricht der Texthöhe + SDL_Rect trgt_rect = { + m_x + 5, + m_y + static_cast<int>(i * spacing), + 16, + 16 }; - SDL_RenderCopy(engine.renderer(), unit_texture, nullptr, &rect); + + SDL_Rect src_rect = { + 5, + 0, + 10, + 10 + }; + + SDL_RenderCopy(engine.renderer(), unit_texture, &src_rect, &trgt_rect); SDL_DestroyTexture(textTexture); SDL_FreeSurface(textSurface); -- GitLab From 2c4e309e94cd502e801bf4e1836bcc8c41552127 Mon Sep 17 00:00:00 2001 From: fdai7466 <nicolas-paul.will@hs-fulda.de> Date: Wed, 5 Feb 2025 17:56:23 +0100 Subject: [PATCH 12/20] add key events for attacking --- src/game/Level.cpp | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index a8d00c5..757843c 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -286,7 +286,6 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event) if(event.key.keysym.sym == SDLK_RETURN){ std::pair<int, int> tilePos = m_currentPos.getPosition(); - std::cout << "TilePos: " << tilePos.first << " " << tilePos.second << std::endl; selectEntity(tilePos.first * 16 * RENDERING_SCALE, tilePos.second* 16 * RENDERING_SCALE); if (m_selectedUnit >= 0 || m_selectedBuilding >= 0) { @@ -465,6 +464,42 @@ void Level::handleAttackingEvents(Engine& engine, SDL_Event& event) { m_state = LevelState::MENUACTIVE_STATE; } + if(event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) + { + m_currentPos.handleEvent(engine, event); + } + if (event.key.keysym.sym == SDLK_RETURN) + { + std::pair<int, int> tilePos = m_currentPos.getPosition(); + int targetedUnit = selectUnit(tilePos.first, tilePos.second); + if (targetedUnit >= 0) + { + if (m_units.at(m_selectedUnit).getFaction() == + m_units.at(targetedUnit).getFaction()) + { + std::cout << "You cannot attack your allies!" << std::endl; + return; + } + + Unit& attacking = m_units.at(m_selectedUnit); + Unit& defending = m_units.at(targetedUnit); + attacking.attack(defending); + if (attacking.m_health <= 0) + { + removeUnit(m_selectedUnit); + } + if (defending.m_health <= 0) + { + removeUnit(targetedUnit); + } + m_selectedUnit = -1; + m_state = LevelState::SELECTING_STATE; + } + else + { + std::cout << "No valid target clicked" << std::endl; + } + } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) -- GitLab From 2cf018dff637328b4b82bdf95ebcfd89f83a2a0d Mon Sep 17 00:00:00 2001 From: fdai7466 <nicolas-paul.will@hs-fulda.de> Date: Wed, 5 Feb 2025 18:33:14 +0100 Subject: [PATCH 13/20] add helper functions to avoid code duplication --- src/game/Level.cpp | 188 ++++++++++++++++++++------------------------- src/game/Level.hpp | 4 + 2 files changed, 87 insertions(+), 105 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 757843c..7df2700 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -215,8 +215,8 @@ void Level::render(Engine& engine) m_contextMenu.render(engine); } - if (m_state == LevelState::RECRUITING_STATE) - { + if (m_state == LevelState::RECRUITING_STATE) + { m_recruitingMenu.render(engine); } m_currentPos.render(engine); @@ -270,23 +270,85 @@ Effect Level::removeEffect(int id) return value; } +//*******************helper functions for event Handling************************************* + +void Level::handleAttack(std::pair<int, int> tilePos) +{ + int targetedUnit = selectUnit(tilePos.first, tilePos.second); + if (targetedUnit >= 0) + { + if (m_units.at(m_selectedUnit).getFaction() == m_units.at(targetedUnit).getFaction()) + { + std::cout << "You cannot attack your allies!" << std::endl; + return; + } + + Unit& attacking = m_units.at(m_selectedUnit); + Unit& defending = m_units.at(targetedUnit); + attacking.attack(defending); + if (attacking.m_health <= 0) + { + removeUnit(m_selectedUnit); + } + if (defending.m_health <= 0) + { + removeUnit(targetedUnit); + } + m_selectedUnit = -1; + m_state = LevelState::SELECTING_STATE; + } + else + { + std::cout << "No valid target clicked" << std::endl; + } +} + +void Level::handleMovement(std::pair<int, int> tilePos) +{ + for (auto& [id, unit] : m_units) + { + if (unit.m_x == tilePos.first && unit.m_y == tilePos.second) + { + // unit already at clicked position (maybe even selected unit) + std::cout << "Unit already at clicked position" << std::endl; + return; + } + } + m_units.at(m_selectedUnit).updatePosition(tilePos.first, tilePos.second); + m_selectedUnit = -1; + m_state = LevelState::SELECTING_STATE; +} + +void Level::handlePositionMarker(Engine& engine, SDL_Event& event) +{ + if (event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || + event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) + { + m_currentPos.handleEvent(engine, event); + } +} + +//*******************end helper functions for event Handling********************************* + +//************event handler delegates for different level states***************************** + void Level::handleSelectingEvents(Engine& engine, SDL_Event& event) { switch (event.type) { case SDL_KEYDOWN: + handlePositionMarker(engine, event); if (event.key.keysym.sym == SDLK_ESCAPE) { engine.pushScene(std::make_shared<PauseMenu>(0, nullptr)); } - if(event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) + + if (event.key.keysym.sym == SDLK_RETURN) { - m_currentPos.handleEvent(engine, event); - } - if(event.key.keysym.sym == SDLK_RETURN){ - + std::pair<int, int> tilePos = m_currentPos.getPosition(); - selectEntity(tilePos.first * 16 * RENDERING_SCALE, tilePos.second* 16 * RENDERING_SCALE); + selectEntity( + tilePos.first * 16 * RENDERING_SCALE, tilePos.second * 16 * RENDERING_SCALE); if (m_selectedUnit >= 0 || m_selectedBuilding >= 0) { m_contextMenu.update( @@ -302,7 +364,7 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event) } m_state = LevelState::MENUACTIVE_STATE; } - } + } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) @@ -382,13 +444,14 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event) } } if (cmd == "Train") - { + { m_state = LevelState::RECRUITING_STATE; std::pair<int, int> tilePos = m_currentPos.getPosition(); m_recruitingMenu.update( (tilePos.first * 16 + 15) * RENDERING_SCALE, (tilePos.second * 16 + 15) * RENDERING_SCALE); - m_recruitingMenu.setOptions({"Infantery", "Tank", "Artillery", "Medium", "Heavy", "Light"}); + m_recruitingMenu.setOptions( + {"Infantery", "Tank", "Artillery", "Medium", "Heavy", "Light"}); std::cout << "no training here" << std::endl; } } @@ -399,55 +462,28 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event) } } - void Level::handleMovementEvents(Engine& engine, SDL_Event& event) { switch (event.type) { case SDL_KEYDOWN: + handlePositionMarker(engine, event); if (event.key.keysym.sym == SDLK_RETURN) { - std::pair<int, int> tilePos = m_currentPos.getPosition(); - for (auto& [id, unit] : m_units) - { - if (unit.m_x == tilePos.first && unit.m_y == tilePos.second) - { - // unit already at clicked position (maybe even selected unit) - std::cout << "Unit already at clicked position" << std::endl; - return; - } - } - m_units.at(m_selectedUnit).updatePosition(tilePos.first, tilePos.second); - m_selectedUnit = -1; - m_state = LevelState::SELECTING_STATE; - + handleMovement(m_currentPos.getPosition()); } if (event.key.keysym.sym == SDLK_ESCAPE) { m_state = LevelState::MENUACTIVE_STATE; } - if(event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) - { - m_currentPos.handleEvent(engine, event); - } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) { // Bei Movement animation in ANIMATING_STATE gehen std::pair<int, int> tilePos = calcTilePos(event.button.x, event.button.y); - for (auto& [id, unit] : m_units) - { - if (unit.m_x == tilePos.first && unit.m_y == tilePos.second) - { - // unit already at clicked position (maybe even selected unit) - std::cout << "Unit already at clicked position" << std::endl; - return; - } - } - m_units.at(m_selectedUnit).updatePosition(tilePos.first, tilePos.second); - m_selectedUnit = -1; - m_state = LevelState::SELECTING_STATE; + m_currentPos.setPosition(tilePos.first, tilePos.second); + handleMovement(tilePos); } break; default: @@ -460,85 +496,27 @@ void Level::handleAttackingEvents(Engine& engine, SDL_Event& event) switch (event.type) { case SDL_KEYDOWN: + handlePositionMarker(engine, event); if (event.key.keysym.sym == SDLK_ESCAPE) { m_state = LevelState::MENUACTIVE_STATE; } - if(event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN || event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) - { - m_currentPos.handleEvent(engine, event); - } if (event.key.keysym.sym == SDLK_RETURN) { - std::pair<int, int> tilePos = m_currentPos.getPosition(); - int targetedUnit = selectUnit(tilePos.first, tilePos.second); - if (targetedUnit >= 0) - { - if (m_units.at(m_selectedUnit).getFaction() == - m_units.at(targetedUnit).getFaction()) - { - std::cout << "You cannot attack your allies!" << std::endl; - return; - } - - Unit& attacking = m_units.at(m_selectedUnit); - Unit& defending = m_units.at(targetedUnit); - attacking.attack(defending); - if (attacking.m_health <= 0) - { - removeUnit(m_selectedUnit); - } - if (defending.m_health <= 0) - { - removeUnit(targetedUnit); - } - m_selectedUnit = -1; - m_state = LevelState::SELECTING_STATE; - } - else - { - std::cout << "No valid target clicked" << std::endl; - } + handleAttack(m_currentPos.getPosition()); } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) { std::pair<int, int> tilePos = calcTilePos(event.button.x, event.button.y); - int targetedUnit = selectUnit(tilePos.first, tilePos.second); - - if (targetedUnit >= 0) - { - if (m_units.at(m_selectedUnit).getFaction() == - m_units.at(targetedUnit).getFaction()) - { - std::cout << "You cannot attack your allies!" << std::endl; - return; - } - - Unit& attacking = m_units.at(m_selectedUnit); - Unit& defending = m_units.at(targetedUnit); - attacking.attack(defending); - if (attacking.m_health <= 0) - { - removeUnit(m_selectedUnit); - } - if (defending.m_health <= 0) - { - removeUnit(targetedUnit); - } - m_selectedUnit = -1; - m_state = LevelState::SELECTING_STATE; - } - else - { - std::cout << "No valid target clicked" << std::endl; - } + m_currentPos.setPosition(tilePos.first, tilePos.second); + handleAttack(tilePos); } break; default: break; } } - +//************end event handler delegates for different level states***************************** } // namespace advanced_wars diff --git a/src/game/Level.hpp b/src/game/Level.hpp index 16e7928..5ecadb8 100644 --- a/src/game/Level.hpp +++ b/src/game/Level.hpp @@ -96,6 +96,10 @@ class Level : public Scene void handleMenuActiveEvents(Engine& engine, SDL_Event& event); void handleMovementEvents(Engine& engine, SDL_Event& event); void handleAttackingEvents(Engine& engine, SDL_Event& event); + + void handleAttack(std::pair<int, int> tilePos); + void handleMovement(std::pair<int, int> tilePos); + void handlePositionMarker(Engine& engine, SDL_Event& event); }; } // namespace advanced_wars -- GitLab From ce413c0413f0e736ee8abfff830d89750352ab46 Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 18:33:22 +0100 Subject: [PATCH 14/20] Add call to recableUnit --- src/game/Level.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index df984b4..f6d868d 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -272,8 +272,12 @@ void Level::handleRecruitingEvent(Engine& engine, SDL_Event& event) { Building& b = m_buildings.at(m_selectedBuilding); UnitFaction u_faction = static_cast<UnitFaction> (b.m_faction); + + std::vector<UnitId> recruitableUnits = b.recruitableUnits(); //show appropriate interface -> provide vector of UnitId + + //show Interface here //select UnitId UnitId u_id = UnitId::INFANTERY; -- GitLab From 00b4926437cbd3e4878074c297a47e66c935ab6f Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 18:42:27 +0100 Subject: [PATCH 15/20] continue work on recuitable units and ui --- src/game/Level.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index f6d868d..8ab52b6 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -275,6 +275,7 @@ void Level::handleRecruitingEvent(Engine& engine, SDL_Event& event) { std::vector<UnitId> recruitableUnits = b.recruitableUnits(); + //m_recruitingmenu.setoptions(recruitableUnits) //show appropriate interface -> provide vector of UnitId //show Interface here -- GitLab From e4eb883389604eee075818cdf5077e85271edf55 Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 18:47:02 +0100 Subject: [PATCH 16/20] add switch case --- src/game/ui/Recruitingmenu.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp index 46f2e9f..3af25ea 100644 --- a/src/game/ui/Recruitingmenu.cpp +++ b/src/game/ui/Recruitingmenu.cpp @@ -14,6 +14,22 @@ namespace advanced_wars m_selectedOption = 0; renderableunit = {}; } +/* + void RecruitingMenu::setOptions(const std::vector<UnitId> recruitableUnits) { + + std::vector<std::string> options; + for (UnitId id : recruitableUnits) { + switch (id) + { + case UnitId::INFANTERY + options + break; + + default: + break; + } + } + } */ void RecruitingMenu::render(Engine& engine) { -- GitLab From 143fe0c19dd7aa6294dabd24b2f75934c8240ec0 Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 18:57:51 +0100 Subject: [PATCH 17/20] add unitidtipstring map --- src/game/Level.cpp | 3 +-- src/game/ui/Recruitingmenu.cpp | 46 ++++++++++++++++++++++------------ src/game/ui/Recruitingmenu.hpp | 10 +++----- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 7df2700..33be3b3 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -450,8 +450,7 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event) m_recruitingMenu.update( (tilePos.first * 16 + 15) * RENDERING_SCALE, (tilePos.second * 16 + 15) * RENDERING_SCALE); - m_recruitingMenu.setOptions( - {"Infantery", "Tank", "Artillery", "Medium", "Heavy", "Light"}); + m_recruitingMenu.setOptions(); std::cout << "no training here" << std::endl; } } diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp index 3af25ea..098c229 100644 --- a/src/game/ui/Recruitingmenu.cpp +++ b/src/game/ui/Recruitingmenu.cpp @@ -9,27 +9,41 @@ namespace advanced_wars } - void RecruitingMenu::setOptions(const std::vector<std::string>& newOptions) { - m_options = newOptions; - m_selectedOption = 0; - renderableunit = {}; - } -/* void RecruitingMenu::setOptions(const std::vector<UnitId> recruitableUnits) { std::vector<std::string> options; for (UnitId id : recruitableUnits) { - switch (id) - { - case UnitId::INFANTERY - options - break; - - default: - break; - } + options.push_back(unitIdToString(id)); } - } */ + + m_options = options; + m_selectedOption = 0; + } + + std::string RecruitingMenu::unitIdToString(UnitId id) { + static const std::unordered_map<UnitId, std::string> unitNames = { + {UnitId::INFANTERY, "Infantry"}, + {UnitId::MECHANIZED_INFANTERY, "Mechanized Infantry"}, + {UnitId::RECON, "Recon"}, + {UnitId::APC, "APC"}, + {UnitId::ARTILLERY, "Artillery"}, + {UnitId::ANTI_AIR_TANK, "Anti-Air Tank"}, + {UnitId::ANTI_AIR_MISSILE_LAUNCHER, "Missile Launcher"}, + {UnitId::ROCKET_ARTILLERY, "Rocket Artillery"}, + {UnitId::MEDIUM_TANK, "Medium Tank"}, + {UnitId::NEO_TANK, "Neo Tank"}, + {UnitId::HEAVY_TANK, "Heavy Tank"}, + {UnitId::LANDER, "Lander"}, + {UnitId::CRUISER, "Cruiser"}, + {UnitId::SUBMARINE, "Submarine"}, + {UnitId::BATTLESHIP, "Battleship"}, + {UnitId::TRANSPORT_HELICOPTER, "Transport Helicopter"}, + {UnitId::BATTLE_HELICOPTER, "Battle Helicopter"}, + {UnitId::FIGHTER, "Fighter"}, + {UnitId::BOMBER, "Bomber"} + }; + + } void RecruitingMenu::render(Engine& engine) { diff --git a/src/game/ui/Recruitingmenu.hpp b/src/game/ui/Recruitingmenu.hpp index c19c1c4..7577ca6 100644 --- a/src/game/ui/Recruitingmenu.hpp +++ b/src/game/ui/Recruitingmenu.hpp @@ -13,11 +13,7 @@ namespace advanced_wars std::vector<std::string> m_options; int m_x; int m_y; - - std::vector<std::vector<std::vector<std::pair<SDL_Texture *, int>>>> renderableunit; - - - + void handleEvent(Engine& engine, SDL_Event& event); @@ -26,13 +22,15 @@ namespace advanced_wars std::string getSelectedOption(); + std::string unitIdToString(UnitId id); + public: void update(int x, int y); RecruitingMenu(); - void setOptions(const std::vector<std::string>& newOptions); + void setOptions(const std::vector<UnitId> recruitableUnits); void render(Engine& engine) override; -- GitLab From 4abb8ad51d8b4a775939510c69f9d1bde594eddb Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 20:28:13 +0100 Subject: [PATCH 18/20] Add correct sprite rendering for all unit types --- src/game/Level.cpp | 13 ++++- src/game/ui/Recruitingmenu.cpp | 93 ++++++++++++++++++++-------------- src/game/ui/Recruitingmenu.hpp | 9 ++-- 3 files changed, 71 insertions(+), 44 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 33be3b3..b235b10 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -450,7 +450,18 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event) m_recruitingMenu.update( (tilePos.first * 16 + 15) * RENDERING_SCALE, (tilePos.second * 16 + 15) * RENDERING_SCALE); - m_recruitingMenu.setOptions(); + m_recruitingMenu.setOptions({ + UnitId::INFANTERY, + UnitId::MECHANIZED_INFANTERY, + UnitId::RECON, + UnitId::APC, + UnitId::ARTILLERY, + UnitId::ANTI_AIR_TANK, + UnitId::ANTI_AIR_MISSILE_LAUNCHER, + UnitId::ROCKET_ARTILLERY, + UnitId::MEDIUM_TANK, + UnitId::NEO_TANK, + UnitId::HEAVY_TANK}); std::cout << "no training here" << std::endl; } } diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp index 098c229..fee0fc1 100644 --- a/src/game/ui/Recruitingmenu.cpp +++ b/src/game/ui/Recruitingmenu.cpp @@ -1,50 +1,47 @@ #include "Recruitingmenu.hpp" #include <iostream> #include <SDL_ttf.h> -#include "../Unit.hpp" namespace advanced_wars { - RecruitingMenu::RecruitingMenu() : m_selectedOption(0) { + RecruitingMenu::RecruitingMenu() : m_selectedOption(0), unitNames({ + {UnitId::INFANTERY, {"Infantry", 100}}, + {UnitId::MECHANIZED_INFANTERY, {"Bazooka", 200}}, + {UnitId::RECON, {"Recon", 300}}, + {UnitId::APC, {"APC", 400}}, + {UnitId::ARTILLERY, {"Artillery", 500}}, + {UnitId::ANTI_AIR_TANK, {"AA Tank", 600}}, + {UnitId::ANTI_AIR_MISSILE_LAUNCHER, {"Rocket AA", 700}}, + {UnitId::ROCKET_ARTILLERY, {"MLRS", 800}}, + {UnitId::MEDIUM_TANK, {"Medium Tank", 900}}, + {UnitId::NEO_TANK, {"Neo Tank", 1000}}, + {UnitId::HEAVY_TANK, {"Heavy Tank", 1100}}, + {UnitId::LANDER, {"Lander", 1200}}, + {UnitId::CRUISER, {"Cruiser", 1300}}, + {UnitId::SUBMARINE, {"Submarine", 1400}}, + {UnitId::BATTLESHIP, {"Battleship", 1500}}, + {UnitId::TRANSPORT_HELICOPTER, {"Chinook", 1600}}, + {UnitId::BATTLE_HELICOPTER, {"Helicopter", 1700}}, + {UnitId::FIGHTER, {"Fighter", 1800}}, + {UnitId::BOMBER, {"Bomber", 1900}} + }) { } void RecruitingMenu::setOptions(const std::vector<UnitId> recruitableUnits) { - std::vector<std::string> options; + std::vector<std::pair<std::string, int>> options; + for (UnitId id : recruitableUnits) { - options.push_back(unitIdToString(id)); + options.push_back(unitNames.at(id)); + cost2UnitId.insert(std::make_pair(unitNames.at(id).second, id)); + } m_options = options; m_selectedOption = 0; } - std::string RecruitingMenu::unitIdToString(UnitId id) { - static const std::unordered_map<UnitId, std::string> unitNames = { - {UnitId::INFANTERY, "Infantry"}, - {UnitId::MECHANIZED_INFANTERY, "Mechanized Infantry"}, - {UnitId::RECON, "Recon"}, - {UnitId::APC, "APC"}, - {UnitId::ARTILLERY, "Artillery"}, - {UnitId::ANTI_AIR_TANK, "Anti-Air Tank"}, - {UnitId::ANTI_AIR_MISSILE_LAUNCHER, "Missile Launcher"}, - {UnitId::ROCKET_ARTILLERY, "Rocket Artillery"}, - {UnitId::MEDIUM_TANK, "Medium Tank"}, - {UnitId::NEO_TANK, "Neo Tank"}, - {UnitId::HEAVY_TANK, "Heavy Tank"}, - {UnitId::LANDER, "Lander"}, - {UnitId::CRUISER, "Cruiser"}, - {UnitId::SUBMARINE, "Submarine"}, - {UnitId::BATTLESHIP, "Battleship"}, - {UnitId::TRANSPORT_HELICOPTER, "Transport Helicopter"}, - {UnitId::BATTLE_HELICOPTER, "Battle Helicopter"}, - {UnitId::FIGHTER, "Fighter"}, - {UnitId::BOMBER, "Bomber"} - }; - - } - void RecruitingMenu::render(Engine& engine) { @@ -78,15 +75,18 @@ namespace advanced_wars int spacing = 20; // Abstand zwischen den Optionen // box around options SDL_SetRenderDrawColor(engine.renderer(), 0, 0, 255, 255); - SDL_Rect box = {m_x, m_y - 3, 125, static_cast<int>(m_options.size() * spacing)}; + SDL_Rect box = {m_x, m_y - 3, 150, static_cast<int>(m_options.size() * spacing)}; SDL_RenderFillRect(engine.renderer(), &box); SDL_SetRenderDrawColor(engine.renderer(), 0, 0, 0, 255); + int i = 0; - for (size_t i = 0; i < m_options.size(); ++i) + for (auto& [render_name, cost] : m_options) { + //std::pair<std::string, int> unit_option = unitNames.at(cost2UnitId.at(cost)); + SDL_Surface* textSurface = TTF_RenderText_Solid( - font, m_options[i].c_str(), (i == m_selectedOption) ? yellow : white); + font, render_name.c_str(), (i == m_selectedOption) ? yellow : white); if (!textSurface) { continue; @@ -100,7 +100,7 @@ namespace advanced_wars SDL_Texture* unit_texture = spritesheet->getUnitTextures() .at(static_cast<int>(UnitFaction::URED)) - .at(static_cast<int>(UnitId::INFANTERY)) + .at(static_cast<int>(cost2UnitId.at(cost))) .at(static_cast<int>(UnitState::IDLE)) .first; @@ -119,9 +119,29 @@ namespace advanced_wars }; SDL_RenderCopy(engine.renderer(), unit_texture, &src_rect, &trgt_rect); - + + SDL_Surface* costSurface = TTF_RenderText_Solid( + font, std::to_string(cost).c_str(), (i == m_selectedOption) ? yellow : white); + if (!textSurface) + { + continue; + } + + SDL_Texture* costTexture = SDL_CreateTextureFromSurface(engine.renderer(), costSurface); + + SDL_Rect cost_rect { + m_x + 120 , + m_y + static_cast<int>(i * spacing), + costSurface->w, + costSurface->h + }; + SDL_RenderCopy(engine.renderer(), costTexture, nullptr, &cost_rect); + + SDL_DestroyTexture(costTexture); + SDL_FreeSurface(costSurface); SDL_DestroyTexture(textTexture); SDL_FreeSurface(textSurface); + i++; } TTF_CloseFont(font); @@ -143,11 +163,6 @@ void RecruitingMenu::handleEvent(Engine& engine, SDL_Event& event) } } -std::string RecruitingMenu::getSelectedOption() -{ - return m_options[m_selectedOption]; -} - void RecruitingMenu::update(int x, int y) { this->m_x = x; diff --git a/src/game/ui/Recruitingmenu.hpp b/src/game/ui/Recruitingmenu.hpp index 7577ca6..a2bfdcb 100644 --- a/src/game/ui/Recruitingmenu.hpp +++ b/src/game/ui/Recruitingmenu.hpp @@ -1,6 +1,7 @@ #pragma once #include "../Scene.hpp" +#include "../Unit.hpp" namespace advanced_wars { @@ -10,10 +11,12 @@ namespace advanced_wars private: size_t m_selectedOption; - std::vector<std::string> m_options; + std::vector<std::pair<std::string, int>> m_options; int m_x; int m_y; - + const std::unordered_map <UnitId ,std::pair <std::string, int>> unitNames; + std::unordered_map<int, UnitId> cost2UnitId; + void handleEvent(Engine& engine, SDL_Event& event); @@ -22,8 +25,6 @@ namespace advanced_wars std::string getSelectedOption(); - std::string unitIdToString(UnitId id); - public: void update(int x, int y); -- GitLab From b912622ee97b758fe0bc89d01dbe81272949589b Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 20:35:15 +0100 Subject: [PATCH 19/20] minor change --- src/game/Level.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 8ab52b6..117ff38 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -280,11 +280,11 @@ void Level::handleRecruitingEvent(Engine& engine, SDL_Event& event) { //show Interface here //select UnitId - UnitId u_id = UnitId::INFANTERY; + UnitId unit_id = UnitId::INFANTERY; if(b.check_money(500)) { if(b.check_spawn(m_units)){ - addUnit(Unit(b.m_x, b.m_y, u_faction, u_id, UnitState::IDLE)); + addUnit(Unit(b.m_x, b.m_y, u_faction, unit_id, UnitState::IDLE)); m_state = LevelState::SELECTING_STATE; m_selectedBuilding = -1; } -- GitLab From 987d6913ab9966d94cbefe5a6be261b16a5051d8 Mon Sep 17 00:00:00 2001 From: Max Cherris <MCherris@protonmail.com> Date: Wed, 5 Feb 2025 20:59:57 +0100 Subject: [PATCH 20/20] Got the actual recruiting to work :) --- src/game/Level.cpp | 44 +++++++++++++++++++--------------- src/game/ui/Recruitingmenu.cpp | 9 ++++++- src/game/ui/Recruitingmenu.hpp | 11 ++++----- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 3af9f1f..9f6a4df 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -277,26 +277,32 @@ Effect Level::removeEffect(int id) void Level::handleRecruitingEvent(Engine& engine, SDL_Event& event) { - Building& b = m_buildings.at(m_selectedBuilding); - UnitFaction u_faction = static_cast<UnitFaction> (b.m_faction); - - - std::vector<UnitId> recruitableUnits = b.recruitableUnits(); - //m_recruitingmenu.setoptions(recruitableUnits) - //show appropriate interface -> provide vector of UnitId - - //show Interface here - //select UnitId - UnitId unit_id = UnitId::INFANTERY; - - if(b.check_money(500)) { - if(b.check_spawn(m_units)){ - addUnit(Unit(b.m_x, b.m_y, u_faction, unit_id, UnitState::IDLE)); - m_state = LevelState::SELECTING_STATE; - m_selectedBuilding = -1; + switch (event.type) + { + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_ESCAPE) + { + m_state = LevelState::MENUACTIVE_STATE; } - } -} + if (event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN) + { + m_recruitingMenu.handleEvent(engine, event); + } + if (event.key.keysym.sym == SDLK_RETURN) + { + Building& b = m_buildings.at(m_selectedBuilding); + UnitFaction u_faction = static_cast<UnitFaction> (b.m_faction); + UnitId unit_id = m_recruitingMenu.getSelectedOption(); + + if(b.check_money(500)) { + if(b.check_spawn(m_units)){ + addUnit(Unit(b.m_x, b.m_y, u_faction, unit_id, UnitState::IDLE)); + m_state = LevelState::SELECTING_STATE; + m_selectedBuilding = -1; + } + } + } +}} //*******************helper functions for event Handling************************************* diff --git a/src/game/ui/Recruitingmenu.cpp b/src/game/ui/Recruitingmenu.cpp index fee0fc1..1ca6289 100644 --- a/src/game/ui/Recruitingmenu.cpp +++ b/src/game/ui/Recruitingmenu.cpp @@ -84,7 +84,10 @@ namespace advanced_wars for (auto& [render_name, cost] : m_options) { //std::pair<std::string, int> unit_option = unitNames.at(cost2UnitId.at(cost)); - + if(i == m_selectedOption) { + m_selectedId = cost2UnitId.at(cost); + } + SDL_Surface* textSurface = TTF_RenderText_Solid( font, render_name.c_str(), (i == m_selectedOption) ? yellow : white); if (!textSurface) @@ -169,4 +172,8 @@ void RecruitingMenu::update(int x, int y) this->m_y = y; } +UnitId RecruitingMenu::getSelectedOption(){ + return m_selectedId; +} + }//namespace advance_wars \ No newline at end of file diff --git a/src/game/ui/Recruitingmenu.hpp b/src/game/ui/Recruitingmenu.hpp index a2bfdcb..01bfdb8 100644 --- a/src/game/ui/Recruitingmenu.hpp +++ b/src/game/ui/Recruitingmenu.hpp @@ -16,17 +16,16 @@ namespace advanced_wars int m_y; const std::unordered_map <UnitId ,std::pair <std::string, int>> unitNames; std::unordered_map<int, UnitId> cost2UnitId; + UnitId m_selectedId; - void handleEvent(Engine& engine, SDL_Event& event); - - - void selectSprite(); - std::string getSelectedOption(); - public: + UnitId getSelectedOption(); + + void handleEvent(Engine& engine, SDL_Event& event); + void update(int x, int y); RecruitingMenu(); -- GitLab