Skip to content
Snippets Groups Projects
Commit 1f4c1d54 authored by Frederik Alexander Keens's avatar Frederik Alexander Keens
Browse files

Merge branch 'unit_info' into 'main'

Unit info menu

See merge request !36
parents dbdf27fb a1d01845
No related branches found
No related tags found
2 merge requests!36Unit info menu,!29Merge main into box2d to implement physics
......@@ -160,4 +160,3 @@ foreach(H5_FILE ${HDF5_FILES})
COMMENT "Kopiere HDF5 File: ${H5_FILE} nach ${OUTPUT_RES_DIR}"
)
endforeach()
......@@ -173,10 +173,22 @@ void Level::selectEntity(int x, int y)
if ((m_selectedUnit = selectUnit(tilePos.first, tilePos.second)) >= 0)
{
auto it = m_units.find(m_selectedUnit);
if (it != m_units.end())
{
Unit& unit = it->second;
m_unitInfoMenu.setUnit(unit);
// Position das Menu rechts neben der ausgewählten Einheit
m_unitInfoMenu.update(
(tilePos.first * 16 + 20) * RENDERING_SCALE, // x-Position
(tilePos.second * 16) * RENDERING_SCALE // y-Position
);
}
return;
}
if ((m_selectedBuilding = selectBuilding(tilePos.first, tilePos.second)) >= 0)
{
// Optionale Handhabung für Gebäude
return;
}
}
......@@ -389,6 +401,12 @@ void Level::render(Engine& engine)
{
m_recruitingMenu.render(engine);
}
if (m_showUnitInfoMenu)
{
m_unitInfoMenu.render(engine);
}
m_currentPos.render(engine);
if (toggle_Helpmenu)
......@@ -808,6 +826,7 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
m_state = LevelState::SELECTING_STATE;
m_showAttackableTiles = false;
m_showReachableTiles = false;
m_showUnitInfoMenu = false;
}
if (event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN)
{
......@@ -818,6 +837,8 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
std::string cmd = m_contextMenu.getSelectedOption();
if (cmd == "Wait")
{
m_state = LevelState::SELECTING_STATE;
m_showUnitInfoMenu = false;
auto it = m_units.find(m_selectedUnit);
if (it != m_units.end())
{
......@@ -837,11 +858,13 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
if (cmd == "Move")
{
m_state = LevelState::MOVEMENT_STATE;
m_showUnitInfoMenu = false;
// Hier Pathfinding einsetzen
}
if (cmd == "Attack")
{
m_state = LevelState::ATTACKING_STATE;
m_showUnitInfoMenu = false;
}
if (cmd == "Info")
{
......@@ -850,6 +873,7 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
{
Unit& u = m_units.at(m_selectedUnit);
std::cout << "Health: " << u.m_health << std::endl;
m_showUnitInfoMenu = !m_showUnitInfoMenu;
}
if (m_selectedBuilding > -1)
{
......@@ -890,6 +914,7 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
m_showAttackableTiles = false;
m_showReachableTiles = false;
changeTurn();
m_showUnitInfoMenu = false;
}
}
break;
......
......@@ -11,6 +11,7 @@
#include "ui/Helpmenu.hpp"
#include "ui/Recruitingmenu.hpp"
#include "ui/TileMarker.hpp"
#include "ui/UnitInfoMenu.hpp"
#include <SDL.h>
#include <array>
#include <queue>
......@@ -19,6 +20,7 @@
#include <unordered_set>
#include <vector>
namespace advanced_wars
{
......@@ -171,6 +173,10 @@ class Level : public Scene
void handleMovement(std::pair<int, int> tilePos);
void handlePositionMarker(Engine& engine, SDL_Event& event);
UnitInfoMenu m_unitInfoMenu;
bool m_showUnitInfoMenu = false;
std::pair<int, int> unit_fallback_position;
};
......
......@@ -123,6 +123,11 @@ class Unit
UnitFaction getFaction();
int getAmmo() const { return m_ammo; }
int getHealth() const { return m_health; }
int getCost() const { return m_cost; }
UnitId getId() const { return m_id;}
void setState(UnitState state);
inline UnitState getState() const { return m_state; }
......
#include "UnitInfoMenu.hpp"
#include <SDL_ttf.h>
#include <iostream>
#include <unordered_map>
namespace advanced_wars
{
// UnitInfoMenu::UnitInfoMenu() : m_currentUnit(nullptr), m_isVisible(false) {}
UnitInfoMenu::UnitInfoMenu() : m_currentUnit(nullptr) {}
std::string UnitInfoMenu::getMovementTypeString(MovementType type)
{
switch (type)
{
case MovementType::FOOT:
return "Foot";
case MovementType::WHEELED:
return "Wheeled";
case MovementType::TREAD:
return "Tracked";
case MovementType::AIR:
return "Aircraft";
case MovementType::SEA:
return "Ship";
case MovementType::LANDER:
return "Lander";
default:
return "Unknown";
}
}
std::unordered_map<UnitId, std::string> unitDescriptions = {
{ UnitId::INFANTERY,"Infanterie Kostenguenstig und vielseitig einsetzbar" },
{ UnitId::MECHANIZED_INFANTERY,"Mech-Infanterie Stark gegen Panzer langsam aber effizient" },
{ UnitId::RECON, "Aufklaerung Schnell und ideal für frühe Aufklaerung"},
{ UnitId::MEDIUM_TANK, "Mittlerer Panzer Guter Allrounder stark und ausgewogen"},
{ UnitId::HEAVY_TANK, "Schwerer Panzer Langsam aber sehr stark und beschützend"},
{ UnitId::NEO_TANK, "Neo Tank Einer der besten Panzer stark und vielseitig"},
{ UnitId::APC, "Transporter Traeger fuer Infanterie keine Offensivkraefte"},
{ UnitId::ANTI_AIR_TANK, "FlugabwehrPanzer Ideal zur Luftverteidigung"},
{ UnitId::ARTILLERY, "Artillerie Kann aus Distanz zufuegen aber verletzbar im Nahkampf"},
{ UnitId::ROCKET_ARTILLERY,"Raketenartillerie Grosse Reichweite ideal fuer defensive Taktiken" },
{UnitId::ANTI_AIR_MISSILE_LAUNCHER, "Raketenwerfer Kann Flugeinheiten auf grosse Distanz angreifen" },
{ UnitId::FIGHTER, "Jaeger Ideal fuer Luftueberlegenheit"},
{ UnitId::BOMBER, "Bomber Stark gegen Boden- und Seeziele aber verletzbar gegen Luft-und Flak" },
{ UnitId::BATTLE_HELICOPTER, "Kampfhubschrauber Stark gegen Bodenfahrzeuge und Infanterie"},
{ UnitId::TRANSPORT_HELICOPTER, "Transporthubschrauber Kann Einheiten schnell transportieren"},
{ UnitId::BATTLESHIP, "Schlachtschiff Langreichweitenangriff auf See und Land"},
{ UnitId::CRUISER, "Kreuzer Verteidigung gegen Luft und U-Boot-Einheiten"},
{ UnitId::LANDER, "Landungsschiff Transport und Versorgung"},
{ UnitId::SUBMARINE, "U-Boot Versteckt sich und kann Ueberwasserziele angreifen"}
};
void UnitInfoMenu::handleEvent(Engine& engine, SDL_Event& event)
{
// Hier kannst du den Code hinzufügen, um die Ereignisse für das UnitInfoMenu zu behandeln
// Wenn keine spezifische Ereignisbehandlung erforderlich ist, kann diese Methode auch leer
// bleiben.
}
void UnitInfoMenu::setUnit(Unit& unit)
{
m_currentUnit = &unit;
m_isVisible = true;
}
void UnitInfoMenu::render(Engine& engine)
{
if (!m_currentUnit || !m_isVisible)
return;
// TTF Initialisierung
if (TTF_Init() == -1)
{
std::cerr << "TTF konnte nicht initialisiert werden: " << TTF_GetError() << std::endl;
return;
}
std::string basePath = SDL_GetBasePath();
std::string fullPath = basePath + "res/ARCADECLASSIC.TTF";
TTF_Font* font = TTF_OpenFont(fullPath.c_str(), 16);
if (!font)
{
std::cerr << "Failed to load font: " << TTF_GetError() << std::endl;
return;
}
SDL_Color yellow = {255, 255, 0, 255}; // Gelb für den Text
int spacing = 10; // Abstand zwischen den Textzeilen
UnitId unitId = m_currentUnit->getId();
// Textzeilen, einschließlich der Beschreibung
std::vector<std::string> info_lines = {
"HP " + std::to_string(m_currentUnit->getHealth()),
"Movement " + std::to_string(m_currentUnit->m_movementPoints),
"Ammo " + std::to_string(m_currentUnit->getAmmo()),
"Movement Type " + getMovementTypeString(m_currentUnit->m_movementType),
"Cost " + std::to_string(m_currentUnit->getCost()),
unitDescriptions[unitId] // Beschreibung einfügen
};
int max_text_width = 0;
int total_height = 0;
std::vector<SDL_Texture*> textures;
for (const auto& line : info_lines)
{
SDL_Surface* textSurface = TTF_RenderText_Solid(font, line.c_str(), yellow);
if (!textSurface)
continue;
max_text_width = std::max(max_text_width, textSurface->w);
total_height += textSurface->h + spacing;
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(engine.renderer(), textSurface);
textures.push_back(textTexture);
SDL_FreeSurface(textSurface);
}
int width = std::max(max_text_width + 20 * RENDERING_SCALE, 16 * RENDERING_SCALE + 20);
int height =
total_height + 30 * RENDERING_SCALE; // Die Höhe anpassen, um alle Textzeilen zu integrieren
SDL_Rect box = {m_x, m_y, width, height};
SDL_SetRenderDrawColor(engine.renderer(), 75, 87, 219, 255); // Schwarzes Hintergrundrechteck
SDL_RenderFillRect(engine.renderer(), &box);
SDL_SetRenderDrawColor(engine.renderer(), 255, 255, 255, 255); // Weißer Rahmen
SDL_RenderDrawRect(engine.renderer(), &box);
// Render unit sprite
Spritesheet* spritesheet = engine.getSpritesheet();
SDL_Texture* unit_texture = spritesheet->getUnitTextures()
.at(static_cast<int>(m_currentUnit->getFaction()))
.at(static_cast<int>(unitId))
.at(static_cast<int>(UnitState::IDLE))
.first;
SDL_Rect sprite_rect = {m_x + 10, m_y + 10, 16 * RENDERING_SCALE, 16 * RENDERING_SCALE};
SDL_Rect source_rect = {0, 0, 16, 16};
SDL_RenderCopy(engine.renderer(), unit_texture, &source_rect, &sprite_rect);
// Text zeichnen
int text_y = m_y + 20 * RENDERING_SCALE; // Starte etwas unterhalb des Sprites
for (auto* texture : textures)
{
int w, h;
SDL_QueryTexture(texture, nullptr, nullptr, &w, &h);
SDL_Rect textRect = {m_x + 10, text_y, w, h};
SDL_RenderCopy(engine.renderer(), texture, nullptr, &textRect);
SDL_DestroyTexture(texture);
text_y += (h + spacing);
}
TTF_CloseFont(font);
TTF_Quit();
}
void UnitInfoMenu::update(int x, int y)
{
m_x = x;
m_y = y;
}
} // namespace advanced_wars
#pragma once
#include "../Engine.hpp"
#include "../Unit.hpp"
//#include "../Level.hpp"
#include <SDL_events.h>
#include <string>
#include <unordered_map>
namespace advanced_wars {
class UnitInfoMenu : public Scene{
public:
UnitInfoMenu();
void handleEvent(Engine& engine, SDL_Event& event) override;
void setUnit(Unit& unit);
void render(Engine& engine);
void update(int x, int y);
private:
int RENDERING_SCALE = 3;
int m_x;
int m_y;
Unit* m_currentUnit;
bool m_isVisible;
std::string getMovementTypeString(MovementType type);
};
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment