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

Merge branch 'main' into 'win_end_screen'

# Conflicts:
#   src/game/Engine.cpp
#   src/game/Player.cpp
#   src/game/Player.hpp
parents f01edb68 d1d187b3
Branches
No related tags found
2 merge requests!33Win end screen,!29Merge main into box2d to implement physics
---
Checks: >
bugprone-*,
cert-*,
clang-analyzer-*,
cppcoreguidelines-*,
misc-*,
modernize-*,
performance-*,
portability-*,
readability-*,
-modernize-use-trailing-return-type,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-avoid-magic-numbers,
-readability-magic-numbers
WarningsAsErrors: ''
HeaderFilterRegex: 'src/game/.*'
FormatStyle: file
CheckOptions:
- key: readability-identifier-naming.ClassCase
value: camelBack
- key: readability-identifier-naming.PrivateMemberPrefix
value: m_
- key: readability-identifier-naming.MethodCase
value: camelBack
- key: readability-identifier-naming.ParameterCase
value: camelBack
- key: readability-identifier-naming.VariableCase
value: camelBack
- key: readability-identifier-naming.ConstantCase
value: UPPER_CASE
- key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: true
- key: performance-move-const-arg.CheckTriviallyCopyableMove
value: false
- key: readability-function-cognitive-complexity.Threshold
value: 25
\ No newline at end of file
......@@ -56,5 +56,7 @@ coverage/
docs/generated/
clang-tidy-warnings.txt
bin/
lib/
......@@ -74,6 +74,8 @@ file(GLOB HDF5_FILES ${RES_DIR}/*.h5)
# Executable erstellen
add_executable(advanced_wars ${ADVANCED_WARS_SOURCES})
set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH})
# Plattform-spezifische Konfiguration
if(APPLE)
# SDL2 Frameworks für macOS
......@@ -159,4 +161,3 @@ foreach(H5_FILE ${HDF5_FILES})
)
endforeach()
set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH})
\ No newline at end of file
# Advanced Wars
## clang-tidy
- Um `clang-tidy` für eine einzelne Datei (z.B. `main.cpp`) auszuführen:
`clang-tidy src/game/main.cpp -header-filter="src/game/main\.cpp" -p build/`
- Um `clang-tidy` für das ganze Projekt auszuführen und die Warnings in die Datei `clang-tidy-warnings.txt` zu schreiben:
`find src/game -name '*.cpp' -o -name '*.hpp' | xargs clang-tidy -header-filter="src/game/.*" -p build/ 1> clang-tidy-warnings.txt`
## Build-Anleitung
### Linux/MacOS
......
......@@ -65,14 +65,10 @@ bool Building::check_spawn(std::unordered_map<int, advanced_wars::Unit>& units)
return true;
}
// can be added as soon as the playerobject is available
bool Building::check_money(int price)
bool Building::check_money(int price, int playerMoney)
{
// replace 400 with player.money and replace price with chosenUnit.price
if (400 > price)
{
return false;
}
return true;
return (playerMoney >= price);
}
std::vector<UnitId> Building::recruitableUnits()
......
......@@ -37,7 +37,7 @@ class Building
/*
checks if the player has enough money for the unit to be recruited
*/
bool check_money(int price);
bool check_money(int price, int playerMoney);
/*
When the building is selected, the player should have the ability to recruit a selection of
......
......@@ -8,6 +8,7 @@
#include "highfive/H5File.hpp"
#include "ui/Contextmenu.hpp"
#include "ui/Pausemenu.hpp"
#include "ui/Helpmenu.hpp"
#include <SDL.h>
#include <algorithm>
#include <boost/property_tree/ptree.hpp>
......@@ -57,7 +58,7 @@ Level::Level(
m_selectedUnit = -1;
};
std::shared_ptr<Level> Level::loadLevel(std::string path, Engine& engine)
std::shared_ptr<Level> Level::loadLevel(const std::string& path, Engine& engine)
{
HighFive::File file(path, HighFive::File::ReadOnly);
......@@ -119,7 +120,7 @@ std::shared_ptr<Level> Level::loadLevel(std::string path, Engine& engine)
{
if (has_factions[i])
{
turnQ.push(Player(2000, static_cast<PlayerFaction>(i)));
turnQ.push(Player(2000, static_cast<UnitFaction>(i)));
}
}
......@@ -178,6 +179,11 @@ int Level::selectBuilding(int tileX, int tileY)
void Level::handleEvent(Engine& engine, SDL_Event& event)
{
if (event.type == SDL_KEYDOWN) {
if (event.key.keysym.sym == SDLK_h) {
toggle_Helpmenu = !toggle_Helpmenu;
}
}
switch (m_state)
{
case LevelState::MENUACTIVE_STATE:
......@@ -348,6 +354,11 @@ void Level::render(Engine& engine)
m_recruitingMenu.render(engine);
}
m_currentPos.render(engine);
if(toggle_Helpmenu) {
m_helpMenu.render(engine);
}
}
int Level::addBuilding(Building building)
......@@ -430,17 +441,25 @@ void Level::handleRecruitingEvent(Engine& engine, SDL_Event& event)
Building& b = m_buildings.at(m_selectedBuilding);
UnitFaction u_faction = static_cast<UnitFaction>(b.m_faction);
UnitId unit_id = m_recruitingMenu.getSelectedOption();
int cost = engine.getUnitConfig().getUnitCost(unit_id);
if (b.check_money(500))
if (b.check_money(cost, m_turnQ.front().getMoney()))
{
if (b.check_spawn(m_units))
{
addUnit(Unit(
b.m_x, b.m_y, u_faction, unit_id, UnitState::IDLE, engine.getUnitConfig()));
m_state = LevelState::SELECTING_STATE;
m_turnQ.front().spendMoney(cost);
m_selectedBuilding = -1;
}
}
else
{
std::cout << "You dont have enough money, current money: "
<< m_turnQ.front().getMoney() << " || needed money: " << cost
<< std::endl;
}
}
}
}
......@@ -468,6 +487,10 @@ void Level::handleAttack(std::pair<int, int> tilePos)
{
removeUnit(m_selectedUnit);
}
else
{
attacking.setState(UnitState::UNAVAILABLE);
}
if (defending.m_health <= 0)
{
removeUnit(targetedUnit);
......@@ -514,10 +537,46 @@ void Level::handleMovement(std::pair<int, int> tilePos)
if (isReachable)
{
m_units.at(m_selectedUnit).updatePosition(tilePos.first, tilePos.second);
m_selectedUnit = -1;
m_showAttackableTiles = false;
m_contextMenu.update(
(tilePos.first * 16 + 15) * RENDERING_SCALE,
(tilePos.second * 16 + 15) * RENDERING_SCALE);
std::vector<Unit*> allUnits;
for (auto& [id, unit] : m_units)
{
allUnits.push_back(&unit);
}
std::vector<Unit*> attackableTargets =
m_units.at(m_selectedUnit).getUnitsInRangeWithDamagePotential(allUnits);
m_attackableTiles.clear();
m_showAttackableTiles = true;
m_attackableUnitIds.clear();
for (Unit* target : attackableTargets)
{
// Füge die Position jedes angreifbaren Ziels hinzu
m_attackableTiles.emplace_back(target->m_x, target->m_y);
// Angreifbaren Einheits-ID setzen
for (auto& [id, unit] : m_units)
{
if (&unit == target)
{
m_attackableUnitIds.insert(id);
break;
}
}
}
m_showReachableTiles = false;
m_state = LevelState::SELECTING_STATE;
m_contextMenu.setOptions({"Attack", "Wait", "End Turn"});
m_state = LevelState::MENUACTIVE_STATE;
}
else
{
......@@ -580,6 +639,10 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event)
m_showAttackableTiles = true;
m_attackableUnitIds.clear();
// Set Fallback_position if movement will be canceled
unit_fallback_position = std::make_pair(
m_units.at(m_selectedUnit).m_x, m_units.at(m_selectedUnit).m_y);
for (Unit* target : attackableTargets)
{
// Füge die Position jedes angreifbaren Ziels hinzu
......@@ -596,11 +659,31 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event)
}
}
m_contextMenu.setOptions({"Move", "Attack", "Info", "Wait"});
// Show according menu options if unit has same/different faction than current
// player
if (m_units.at(m_selectedUnit).getFaction() == m_turnQ.front().getFaction() &&
m_units.at(m_selectedUnit).getState() != UnitState::UNAVAILABLE)
{
m_contextMenu.setOptions({"Move", "Attack", "Info", "Wait", "End Turn"});
}
else
{
m_contextMenu.setOptions({"Train", "Info", "Wait"});
m_contextMenu.setOptions({"Info", "End Turn"});
}
}
else
{
// Show according menu options if building has same/different faction than
// current player
if (m_buildings.at(m_selectedBuilding).getFaction() ==
static_cast<BuildingFaction>(m_turnQ.front().getFaction()))
{
m_contextMenu.setOptions({"Train", "Info", "End Turn"});
}
else
{
m_contextMenu.setOptions({"Info", "End Turn"});
}
}
m_state = LevelState::MENUACTIVE_STATE;
}
......@@ -646,6 +729,13 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
if (m_selectedUnit > -1 &&
unit_fallback_position !=
std::make_pair(m_units.at(m_selectedUnit).m_x, m_units.at(m_selectedUnit).m_y))
{
m_units.at(m_selectedUnit)
.updatePosition(unit_fallback_position.first, unit_fallback_position.second);
}
m_selectedUnit = -1;
m_selectedBuilding = -1;
m_state = LevelState::SELECTING_STATE;
......@@ -661,7 +751,21 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
std::string cmd = m_contextMenu.getSelectedOption();
if (cmd == "Wait")
{
auto it = m_units.find(m_selectedUnit);
if (it != m_units.end())
{
it->second.setState(UnitState::UNAVAILABLE);
std::cout << "Unit state set to UNAVAILABLE." << std::endl;
m_state = LevelState::SELECTING_STATE;
m_selectedUnit = -1;
m_selectedBuilding = -1;
m_showAttackableTiles = false;
m_showReachableTiles = false;
}
else
{
std::cerr << "Selected unit id is invalid: " << m_selectedUnit << std::endl;
}
}
if (cmd == "Move")
{
......@@ -701,6 +805,13 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
UnitId::HEAVY_TANK});
std::cout << "no training here" << std::endl;
}
if (cmd == "End Turn")
{
m_state = LevelState::SELECTING_STATE;
m_showAttackableTiles = false;
m_showReachableTiles = false;
changeTurn();
}
}
break;
......@@ -717,6 +828,7 @@ void Level::handleMovementEvents(Engine& engine, SDL_Event& event)
handlePositionMarker(engine, event);
if (event.key.keysym.sym == SDLK_RETURN)
{
handleMovement(m_currentPos.getPosition());
}
if (event.key.keysym.sym == SDLK_ESCAPE)
......@@ -740,6 +852,12 @@ void Level::handleMovementEvents(Engine& engine, SDL_Event& event)
void Level::handleAttackingEvents(Engine& engine, SDL_Event& event)
{
if (m_attackableUnitIds.empty())
{
std::cout << "No units are within attack range." << std::endl;
m_state = LevelState::MENUACTIVE_STATE;
return; // Early exit if no units to attack
}
switch (event.type)
{
case SDL_KEYDOWN:
......
......@@ -10,6 +10,7 @@
#include "ui/Contextmenu.hpp"
#include "ui/Recruitingmenu.hpp"
#include "ui/TileMarker.hpp"
#include "ui/Helpmenu.hpp"
#include <SDL.h>
#include <array>
#include <queue>
......@@ -80,7 +81,7 @@ class Level : public Scene
std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect> effects,
std::queue<Player> turnQ);
static std::shared_ptr<Level> loadLevel(std::string path, Engine& engine);
static std::shared_ptr<Level> loadLevel(const std::string& path, Engine& engine);
void render(Engine& engine);
......@@ -135,6 +136,8 @@ class Level : public Scene
int m_selectedBuilding;
ContextMenu m_contextMenu;
RecruitingMenu m_recruitingMenu;
bool toggle_Helpmenu = false;
HelpMenu m_helpMenu;
int m_id;
LevelState m_state;
......@@ -164,6 +167,9 @@ class Level : public Scene
void handleAttack(std::pair<int, int> tilePos);
void handleMovement(std::pair<int, int> tilePos);
void handlePositionMarker(Engine& engine, SDL_Event& event);
std::pair<int, int> unit_fallback_position;
};
} // namespace advanced_wars
......@@ -4,7 +4,7 @@
namespace advanced_wars
{
Player::Player(int money, PlayerFaction faction)
Player::Player(int money, UnitFaction faction)
: m_money(money), m_alive(true), m_activeTurn(false), m_faction(faction)
{
}
......@@ -16,42 +16,10 @@ void Player::startTurn(
{
for (auto& [id, unit] : lvUnits)
{
switch (m_faction)
{
case PlayerFaction::RED:
if (unit.getFaction() == UnitFaction::URED)
if (unit.getFaction() == m_faction)
{
unit.setState(UnitState::IDLE);
}
break;
case PlayerFaction::BLUE:
if (unit.getFaction() == UnitFaction::UBLUE)
{
unit.setState(UnitState::IDLE);
}
break;
case PlayerFaction::YELLOW:
if (unit.getFaction() == UnitFaction::UYELLOW)
{
unit.setState(UnitState::IDLE);
}
break;
case PlayerFaction::GREEN:
if (unit.getFaction() == UnitFaction::UGREEN)
{
unit.setState(UnitState::IDLE);
}
break;
case PlayerFaction::PURPLE:
if (unit.getFaction() == UnitFaction::UPURPLE)
{
unit.setState(UnitState::IDLE);
}
break;
default:
break;
}
}
int underControl = 0;
......@@ -60,31 +28,31 @@ void Player::startTurn(
{
switch (m_faction)
{
case PlayerFaction::RED:
case UnitFaction::URED:
if (building.getFaction() == BuildingFaction::URED)
{
underControl++;
}
break;
case PlayerFaction::BLUE:
case UnitFaction::UBLUE:
if (building.getFaction() == BuildingFaction::UBLUE)
{
underControl++;
}
break;
case PlayerFaction::YELLOW:
case UnitFaction::UYELLOW:
if (building.getFaction() == BuildingFaction::UYELLOW)
{
underControl++;
}
break;
case PlayerFaction::GREEN:
case UnitFaction::UGREEN:
if (building.getFaction() == BuildingFaction::UGREEN)
{
underControl++;
}
break;
case PlayerFaction::PURPLE:
case UnitFaction::UPURPLE:
if (building.getFaction() == BuildingFaction::UPURPLE)
{
underControl++;
......@@ -105,47 +73,15 @@ void Player::endTurn(std::unordered_map<int, Unit>& lvUnits)
{
for (auto& [id, unit] : lvUnits)
{
switch (m_faction)
{
case PlayerFaction::RED:
if (unit.getFaction() == UnitFaction::URED)
if (unit.getFaction() == m_faction)
{
unit.setState(UnitState::UNAVAILABLE);
}
break;
case PlayerFaction::BLUE:
if (unit.getFaction() == UnitFaction::UBLUE)
{
unit.setState(UnitState::UNAVAILABLE);
}
break;
case PlayerFaction::YELLOW:
if (unit.getFaction() == UnitFaction::UYELLOW)
{
unit.setState(UnitState::UNAVAILABLE);
}
break;
case PlayerFaction::GREEN:
if (unit.getFaction() == UnitFaction::UGREEN)
{
unit.setState(UnitState::UNAVAILABLE);
}
break;
case PlayerFaction::PURPLE:
if (unit.getFaction() == UnitFaction::UPURPLE)
{
unit.setState(UnitState::UNAVAILABLE);
}
break;
default:
break;
}
}
m_activeTurn = false;
}
PlayerFaction Player::getFaction()
UnitFaction Player::getFaction()
{
return m_faction;
}
......@@ -154,4 +90,9 @@ int Player::getMoney()
{
return m_money;
}
void Player::spendMoney(int toSpend)
{
m_money -= toSpend;
}
} // namespace advanced_wars
\ No newline at end of file
......@@ -7,25 +7,16 @@
namespace advanced_wars
{
enum class PlayerFaction
{
RED,
BLUE,
YELLOW,
GREEN,
PURPLE
};
class Player
{
private:
int m_money;
bool m_alive;
bool m_activeTurn;
PlayerFaction m_faction;
UnitFaction m_faction;
public:
Player(int money, PlayerFaction faction);
Player(int money, UnitFaction faction);
~Player();
/**
......@@ -46,8 +37,11 @@ class Player
*/
void endTurn(std::unordered_map<int, Unit>& lvUnits);
PlayerFaction getFaction();
UnitFaction getFaction();
int getMoney();
void spendMoney(int toSpend);
};
} // namespace advanced_wars
......@@ -242,7 +242,7 @@ std::vector<Unit*> Unit::getUnitsInRangeWithDamagePotential(const std::vector<Un
for (Unit* unit : allUnits)
{ // Iterate over all units
// except itself
if (unit == this)
if (unit->getFaction() == this->m_faction)
{
continue;
}
......
......@@ -125,6 +125,8 @@ class Unit
void setState(UnitState state);
inline UnitState getState() const { return m_state; }
/**
* Retrieves units within range that this unit can deal damage to.
* Considers all units provided in 'allUnits', excluding itself, and checks movement and
......
......@@ -11,8 +11,13 @@
using namespace advanced_wars;
int main()
int main(int argc, char* argv[])
{
if (argc <= 1)
{
std::cerr << "Please provide the path to the level that you want to play as a command line argument." << std::endl;
return 1;
}
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
......@@ -34,7 +39,7 @@ int main()
engine.setSpritesheet(spritesheet);
std::shared_ptr<Menu> menu = std::make_shared<Menu>(0);
std::shared_ptr<Menu> menu = std::make_shared<Menu>(0, argv[1]);
std::shared_ptr<ContextMenu> context_menu = std::make_shared<ContextMenu>();
context_menu->setOptions({"Move", "Info", "Wait"});
......
#include "Helpmenu.hpp"
#include <SDL_ttf.h>
#include <iostream>
namespace advanced_wars
{
HelpMenu::HelpMenu() {}
void HelpMenu::handleEvent(Engine& engine, SDL_Event& event) {}
std::vector<std::string> helpTable = {
"Willkommen im Tutorial!", // 0
"Nutzen Sie die PFEILTASTEN zur Navigation in allen Menus! ", // 1
"Wenn Sie an der Reihe sind nutzen Sie die PFEILTASTEN um den " // 2
"Selectioncursor !das kleine farbige Quadrat! auf dem Spielfeld zu verschieben! Nutzen Sie " // 3
"RETURN um eine Einheit zu selektieren! Nutzen Sie die PFEILTASTEN um eine Option " // 4
"auszuwaehlen und RETURN um ihre Auswahl zu bestaetigen! ", // 5
"Spielregeln! ", // 6
"Einheiten daerfen sich in einer Runde nur ein Mal bewegen und ein Mal angreifen! ", // 7
"Gegnerische Einheiten muessen sich in REICHWEITE befinden! ", // 8
"Einheiten kosten Geld! ", // 9
"Am Start ihres Zuges erhalten Sie pro Stadt 1000 Geld! ", // 10
"Angreifer schiessen immer zuerst! ", // 11
"Achten Sie auf die Einheitenklassen um Schadensboni auszunutzen! ", // 12
"Nutzen Sie diese Werkzeuge um das Spiel gegen ihren Gegner zu gewinnen! "}; // 13
void HelpMenu::render(advanced_wars::Engine& engine)
{
if (TTF_Init() == -1)
{
std::cerr << "Failed to initialize TTF: " << TTF_GetError() << std::endl;
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 = {200, 200, 0, 255};
int spacing = 25;
int boxWidth = 600;
int boxHeight = static_cast<int>(610);
SDL_SetRenderDrawColor(engine.renderer(), 75, 87, 219, 255);
SDL_Rect box = {50, 50, boxWidth, boxHeight};
SDL_RenderFillRect(engine.renderer(), &box);
int text_x = 60;
int text_y = 60;
renderTextPortion(engine, helpTable[0], font, white, boxWidth, text_x, text_y);
text_y += spacing;
std::string text = helpTable[1] + helpTable[2] + helpTable[3] + helpTable[4] + helpTable[5];
renderTextPortion(engine, text, font, white, boxWidth, text_x, text_y);
text_y += 150;
text = helpTable[6] + helpTable[7] + helpTable[8] + helpTable[9] + helpTable[10];
renderTextPortion(engine, text, font, white, boxWidth, text_x, text_y);
text_y += 125;
SDL_Rect divider = {60, text_y - 25, boxWidth - 20, 2};
SDL_SetRenderDrawColor(engine.renderer(), 239, 235, 216, 255);
SDL_RenderFillRect(engine.renderer(), &divider);
Spritesheet* spritesheet = engine.getSpritesheet();
SDL_Texture* buildingTexture = spritesheet->getBuildingTextures().at(0);
int renderingScale = 2;
SDL_Rect trgt_rect = {65, text_y, 16 * renderingScale, 16 * renderingScale * 2};
SDL_Rect src_rect = {0, 0, 16, 32};
SDL_RenderCopy(engine.renderer(), buildingTexture, &src_rect, &trgt_rect);
renderTextPortion(
engine, "Das ist das Hauptquartier! Wenn es faellt, haben Sie das Spiel verloren!", font,
white, boxWidth - 120 - 5, 120, text_y);
text_y += 48;
renderTexture(buildingTexture, engine, 55, text_y + 48, 16, 16);
renderTexture(buildingTexture, engine, 55, text_y + 96, 32, 16);
renderTexture(buildingTexture, engine, 55, text_y + 144, 48, 16);
renderTexture(buildingTexture, engine, 55, text_y + 192, 64, 16);
renderTextPortion(
engine,
"Nehmen Sie Staedte auf der Karte ein um jede Runde Geld fuer das Rekrutieren der Einheiten "
"zu bekommen!",
font, white, boxWidth - 120 - 5, 120, text_y + 48);
renderTextPortion(
engine, "Aus der Kaserne koennen Sie Landeinheiten anfordern!", font, white,
boxWidth - 120 - 5, 120, text_y + 96);
renderTextPortion(
engine,
"Mit einem Flughafen koennen Sie die Lufthoheit erkaempfen! Achten Sie auf Flugabwehr!", font,
white, boxWidth - 120 - 5, 120, text_y + 144);
renderTextPortion(
engine,
"Der Hafen stellt ihnen verschiedene Marineeinheiten zur Verfuegung! Um den Sieg zu "
"erringen sollten Sie Ihre Flotte nicht vernachlaessigen!",
font, white, boxWidth - 120 - 5, 120, text_y + 192);
TTF_CloseFont(font);
TTF_Quit();
}
void HelpMenu::renderTextPortion(
Engine& engine, std::string text, TTF_Font* font, SDL_Color color, int boxWidth, int text_x,
int text_y)
{
SDL_Surface* textSurface =
TTF_RenderUTF8_Solid_Wrapped(font, text.c_str(), color, boxWidth - 5);
if (!textSurface)
return;
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(engine.renderer(), textSurface);
SDL_Rect textRect = {text_x, text_y, textSurface->w, textSurface->h};
SDL_RenderCopy(engine.renderer(), textTexture, nullptr, &textRect);
SDL_DestroyTexture(textTexture);
SDL_FreeSurface(textSurface);
}
void HelpMenu::renderTexture(
SDL_Texture* texture, Engine& engine, int x, int y, int src_x, int src_y)
{
SDL_Texture* buildingTexture = texture;
int renderingScale = 2;
SDL_Rect trgt_rect = {65, y, 16 * renderingScale, 16 * renderingScale};
SDL_Rect src_rect = {src_x, src_y, 16, 16};
SDL_RenderCopy(engine.renderer(), buildingTexture, &src_rect, &trgt_rect);
}
} // namespace advanced_wars
\ No newline at end of file
#pragma once
#include "../Scene.hpp"
#include <SDL_ttf.h>
namespace advanced_wars
{
class HelpMenu : public Scene
{
private:
size_t m_selectedOption;
std::vector<std::pair<std::string, int>> m_options;
int m_x;
int m_y;
void renderTextPortion(
Engine& engine, std::string text, TTF_Font* font, SDL_Color color, int boxWidth,
int text_x, int text_y);
void
renderTexture(SDL_Texture* texture, Engine& engine, int x, int y, int src_x, int src_y);
public:
void handleEvent(Engine& engine, SDL_Event& event);
void update(int x, int y);
HelpMenu();
void render(Engine& engine) override;
};
} // namespace advanced_wars
\ No newline at end of file
#include "Menu.hpp"
#include "../Level.hpp"
#include "../Building.hpp"
#include "../Config.hpp"
#include "../Level.hpp"
#include "../Spritesheet.hpp"
#include "../Tile.hpp"
#include "../Unit.hpp"
......@@ -14,8 +14,9 @@
namespace advanced_wars
{
Menu::Menu(int selectedOption)
: m_selectedOption(selectedOption), m_options({"Start Game", "Options", "Exit"}),
Menu::Menu(int selectedOption, const std::string& level_filepath)
: m_selectedOption(selectedOption), m_level_filepath(level_filepath),
m_options({"Start Game", "Options", "Exit"}),
m_backgroundTexture(nullptr)
{
}
......@@ -202,7 +203,7 @@ void Menu::handleEvent(Engine& engine, SDL_Event& event)
// std::make_shared<Level>("Osnabrück", 20, 20, tiles, buildings, units,
// effects, std::queue<Player>{});
engine.pushScene(Level::loadLevel("../res/level.h5", engine));
engine.pushScene(Level::loadLevel(m_level_filepath, engine));
}
else if (m_options[m_selectedOption] == "Options")
{
......
......@@ -23,6 +23,7 @@ class Menu : public Scene
{
private:
size_t m_selectedOption; ///< Index of the currently selected menu option.
std::string m_level_filepath; ///< The path from which the level will be loaded.
std::array<std::string, 3> m_options; ///< The available menu options.
SDL_Texture* m_backgroundTexture; ///< Pointer to the background texture (if any).
......@@ -34,8 +35,9 @@ class Menu : public Scene
* selected option based on the given index.
*
* @param selectedOption The index of the initially selected menu option.
* @param level_filepath The path from which the level will be loaded.
*/
Menu(int selectedOption);
Menu(int selectedOption, const std::string& level_filepath);
/**
* @brief Renders the menu on the screen.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment