From 080165d767fbd245874c2cca8141d21a8b05ac4d Mon Sep 17 00:00:00 2001 From: Lorenz <lorenz-martin.diel@informatik.hs-fulda.de> Date: Tue, 28 Jan 2025 22:11:44 +0100 Subject: [PATCH 1/3] started loading XML --- XML/config.xml | 41 ++++++++++++++ src/config.cpp | 148 +++++++++++++++++++++++++++++++++++++++++++++++++ src/unit.hpp | 25 ++++++++- 3 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 XML/config.xml create mode 100644 src/config.cpp diff --git a/XML/config.xml b/XML/config.xml new file mode 100644 index 0000000..b2ba653 --- /dev/null +++ b/XML/config.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Units> + <Unit key="infantry"> + <Cost>1000</Cost> + <MovementPoints>3</MovementPoints> + <MovementType>Foot</MovementType> + <minRange>1</minRange> + <maxRange>1</maxRange> + <Ammo>0</Ammo> + <Weapons> + <SecondaryWeapon name="Machine-Gun"> + <DamageTable> + <Damage unitId="infantry" value="55"/> + <Damage unitId="Mech" value="45"/> + </DamageTable> + </SecondaryWeapon> + </Weapons> + </Unit> + <Unit key="Mech"> + <Cost>3000</Cost> + <MovementPoints>2</MovementPoints> + <MovementType>Foot</MovementType> + <Ammo>9</Ammo> + <minRange>1</minRange> + <maxRange>1</maxRange> + <Weapons> + <PrimaryWeapon name="Rockets"> + <DamageTable> + <Damage unitId="infantry" value="65"/> + <Damage unitId="infantry" value="55"/> + </DamageTable> + </PrimaryWeapon> + <SecondaryWeapon name="Machine-Gun"> + <DamageTable> + <Damage unitId="infantry" value="65"/> + <Damage unitId="infantry" value="55"/> + </DamageTable> + </SecondaryWeapon> + </Weapons> + </Unit> +</Units> diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..771870f --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,148 @@ +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/xml_parser.hpp> +#include <unordered_map> +#include <string> +#include <iostream> +#include <stdexcept> // Für die Ausnahmebehandlung +#include "unit.hpp" // Include für UnitId + +namespace pt = boost::property_tree; + +namespace advanced_wars +{ + + class Config + { + public: + void loadFromXML(const char *filename); + + int get_unit_cost(UnitId id) const; + int get_unit_movementPoints(UnitId id) const; + int get_unit_ammo(UnitId id) const; + int get_unit_minRange(UnitId id) const; + int get_unit_maxRange(UnitId id) const; + std::string get_unit_secondaryweapon(UnitId id) const; + std::string get_unit_primaryweapon(UnitId id) const; + + private: + std::unordered_map<UnitId, int> unit_costs; + std::unordered_map<UnitId, int> unit_movementPoints; + std::unordered_map<UnitId, int> unit_ammo; + std::unordered_map<UnitId, int> unit_minRange; + std::unordered_map<UnitId, int> unit_maxRange; + std::unordered_map<UnitId, std::string> unit_secondaryweapon; + std::unordered_map<UnitId, std::string> unit_primaryweapon; + }; + + void Config::loadFromXML(const char *filename) + { + pt::ptree tree; + pt::read_xml(filename, tree); + + for (const auto &unit : tree.get_child("Units")) + { + if (unit.first == "Unit") + { + std::string unitKey = unit.second.get<std::string>("<xmlattr>.key"); + + UnitId unitId; + if (unitKey == "infantry") + { + unitId = UnitId::INFANTERY; + } + else if (unitKey == "Mech") + { + unitId = UnitId::MECH; + } + else + { + continue; // Überspringt nicht unterstützte Einheiten + } + + int cost = unit.second.get<int>("Cost"); + int movementPoints = unit.second.get<int>("MovementPoints"); + int ammo = unit.second.get<int>("Ammo"); + int minRange = unit.second.get<int>("minRange", 0); + int maxRange = unit.second.get<int>("maxRange", 0); + + unit_costs[unitId] = cost; + unit_movementPoints[unitId] = movementPoints; + unit_ammo[unitId] = ammo; + unit_minRange[unitId] = minRange; + unit_maxRange[unitId] = maxRange; + + for (const auto &weapon : unit.second.get_child("Weapons")) + { + if (weapon.first == "PrimaryWeapon") + { + std::string weaponName = weapon.second.get<std::string>("<xmlattr>.name"); + unit_primaryweapon[unitId] = weaponName; + } + else if (weapon.first == "SecondaryWeapon") + { + std::string weaponName = weapon.second.get<std::string>("<xmlattr>.name"); + unit_secondaryweapon[unitId] = weaponName; + } + } + } + } + } + + // Definitions for the accessor methods + int Config::get_unit_cost(UnitId id) const + { + auto it = unit_costs.find(id); + if (it != unit_costs.end()) + return it->second; + throw std::runtime_error("Cost for unit ID not found"); + } + + int Config::get_unit_movementPoints(UnitId id) const + { + auto it = unit_movementPoints.find(id); + if (it != unit_movementPoints.end()) + return it->second; + throw std::runtime_error("Movement points for unit ID not found"); + } + + int Config::get_unit_ammo(UnitId id) const + { + auto it = unit_ammo.find(id); + if (it != unit_ammo.end()) + return it->second; + throw std::runtime_error("Ammo for unit ID not found"); + } + + int Config::get_unit_minRange(UnitId id) const + { + auto it = unit_minRange.find(id); + if (it != unit_minRange.end()) + return it->second; + throw std::runtime_error("Min range for unit ID not found"); + } + + int Config::get_unit_maxRange(UnitId id) const + { + auto it = unit_maxRange.find(id); + if (it != unit_maxRange.end()) + return it->second; + throw std::runtime_error("Max range for unit ID not found"); + } + + std::string Config::get_unit_secondaryweapon(UnitId id) const + { + auto it = unit_secondaryweapon.find(id); + if (it != unit_secondaryweapon.end()) + return it->second; + throw std::runtime_error("Secondary weapon for unit ID not found"); + } + + std::string Config::get_unit_primaryweapon(UnitId id) const + { + auto it = unit_primaryweapon.find(id); + if (it != unit_primaryweapon.end()) + return it->second; + throw std::runtime_error("Primary weapon for unit ID not found"); + } + +} // namespace advanced_wars diff --git a/src/unit.hpp b/src/unit.hpp index dfb5fc0..172233e 100644 --- a/src/unit.hpp +++ b/src/unit.hpp @@ -14,7 +14,7 @@ enum class UnitFaction { UYELLOW = 3, UPURPLE = 4, }; - +/* enum class UnitId { INFANTERY = 0, MECHANIZED_INFANTERY = 1, @@ -36,6 +36,29 @@ enum class UnitId { LANDER = 17, SUBMARINE = 18, }; +*/ + +enum class UnitId { + INFANTERY, + MECH, + RECON, + MEDIUM_TANK, + HEAVY_TANK, + NEO_TANK, + APC, + ANTI_AIR_TANK, + ARTILLERY, + ROCKET_ARTILLERY, + ANTI_AIR_MISSILE_LAUNCHER, + FIGHTER, + BOMBER, + BATTLE_HELICOPTER, + TRANSPORT_HELICOPTER, + BATTLESHIP, + CRUISER, + LANDER, + SUBMARINE, +}; enum class UnitState { IDLE = 0, -- GitLab From a42d1514aa980772151ff595ad816e0548aea09f Mon Sep 17 00:00:00 2001 From: Lorenz <lorenz-martin.diel@informatik.hs-fulda.de> Date: Wed, 29 Jan 2025 10:38:54 +0100 Subject: [PATCH 2/3] added damageTable --- src/config.cpp | 92 ++++++++++++++++++++++++++++++----------- src/config.hpp | 39 +++++++++++++++++ src/level.cpp | 2 + src/main.cpp | 36 +++++++++++----- src/unit.cpp | 84 ++++++++++++++++++++++++++++++++++++- src/unit.hpp | 12 ++++-- {XML => xml}/config.xml | 0 7 files changed, 226 insertions(+), 39 deletions(-) create mode 100644 src/config.hpp rename {XML => xml}/config.xml (100%) diff --git a/src/config.cpp b/src/config.cpp index 771870f..692f166 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -5,35 +5,17 @@ #include <iostream> #include <stdexcept> // Für die Ausnahmebehandlung #include "unit.hpp" // Include für UnitId - +#include "config.hpp" namespace pt = boost::property_tree; namespace advanced_wars { - class Config + Config::Config(MatchupTabel_secondaryweapon& secWeapon, MatchupTabel_primaryweapon& primWeapon) + : secondary_weapon_damage(secWeapon), primary_weapon_damage(primWeapon) { - public: - void loadFromXML(const char *filename); - - int get_unit_cost(UnitId id) const; - int get_unit_movementPoints(UnitId id) const; - int get_unit_ammo(UnitId id) const; - int get_unit_minRange(UnitId id) const; - int get_unit_maxRange(UnitId id) const; - std::string get_unit_secondaryweapon(UnitId id) const; - std::string get_unit_primaryweapon(UnitId id) const; - - private: - std::unordered_map<UnitId, int> unit_costs; - std::unordered_map<UnitId, int> unit_movementPoints; - std::unordered_map<UnitId, int> unit_ammo; - std::unordered_map<UnitId, int> unit_minRange; - std::unordered_map<UnitId, int> unit_maxRange; - std::unordered_map<UnitId, std::string> unit_secondaryweapon; - std::unordered_map<UnitId, std::string> unit_primaryweapon; - }; - + // Initialisierung hier wenn nötig + } void Config::loadFromXML(const char *filename) { pt::ptree tree; @@ -52,7 +34,7 @@ namespace advanced_wars } else if (unitKey == "Mech") { - unitId = UnitId::MECH; + unitId = UnitId::MECHANIZED_INFANTERY; } else { @@ -84,6 +66,68 @@ namespace advanced_wars unit_secondaryweapon[unitId] = weaponName; } } + + for (const auto &weapon : unit.second.get_child("Weapons")) + { + if (weapon.first == "PrimaryWeapon") + { + std::string weaponName = weapon.second.get<std::string>("<xmlattr>.name"); + unit_primaryweapon[unitId] = weaponName; + for (const auto &damage_entry : weapon.second.get_child("DamageTable")) + { + if (damage_entry.first == "Damage") + { + std::string targetUnitId = damage_entry.second.get<std::string>("<xmlattr>.unitId"); + int damageValue = damage_entry.second.get<int>("<xmlattr>.value"); + + UnitId targetId; + if (targetUnitId == "infantry") + { + targetId = UnitId::INFANTERY; + } + else if (targetUnitId == "Mech") + { + targetId = UnitId::MECHANIZED_INFANTERY; + } + else + { + continue; // Überspringt nicht unterstützte Ziele + } + + primary_weapon_damage[unitId][targetId] = damageValue; + } + } + } + else if (weapon.first == "SecondaryWeapon") + { + for (const auto &damage_entry : weapon.second.get_child("DamageTable")) + { + std::string weaponName = weapon.second.get<std::string>("<xmlattr>.name"); + unit_secondaryweapon[unitId] = weaponName; + if (damage_entry.first == "Damage") + { + std::string targetUnitId = damage_entry.second.get<std::string>("<xmlattr>.unitId"); + int damageValue = damage_entry.second.get<int>("<xmlattr>.value"); + + UnitId targetId; + if (targetUnitId == "infantry") + { + targetId = UnitId::INFANTERY; + } + else if (targetUnitId == "Mech") + { + targetId = UnitId::MECHANIZED_INFANTERY; + } + else + { + continue; // Überspringt nicht unterstützte Ziele + } + + secondary_weapon_damage[unitId][targetId] = damageValue; + } + } + } + } } } } diff --git a/src/config.hpp b/src/config.hpp new file mode 100644 index 0000000..d5b8109 --- /dev/null +++ b/src/config.hpp @@ -0,0 +1,39 @@ +#ifndef CONFIG_HPP +#define CONFIG_HPP + +#include <unordered_map> +#include <string> +#include <stdexcept> +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/xml_parser.hpp> +#include "unit.hpp" // Include für UnitId + +namespace advanced_wars { + +class Config { + public: + Config(MatchupTabel_secondaryweapon& secWeapon, MatchupTabel_primaryweapon& primWeapon); + void loadFromXML(const char* filename); + int get_unit_cost(UnitId id) const; + int get_unit_movementPoints(UnitId id) const; + int get_unit_ammo(UnitId id) const; + int get_unit_minRange(UnitId id) const; + int get_unit_maxRange(UnitId id) const; + std::string get_unit_secondaryweapon(UnitId id) const; + std::string get_unit_primaryweapon(UnitId id) const; + + private: + std::unordered_map<UnitId, int> unit_costs; + std::unordered_map<UnitId, int> unit_movementPoints; + std::unordered_map<UnitId, int> unit_ammo; + std::unordered_map<UnitId, int> unit_minRange; + std::unordered_map<UnitId, int> unit_maxRange; + std::unordered_map<UnitId, std::string> unit_secondaryweapon; + std::unordered_map<UnitId, std::string> unit_primaryweapon; + MatchupTabel_secondaryweapon& secondary_weapon_damage; + MatchupTabel_primaryweapon& primary_weapon_damage; + }; + +} // namespace advanced_wars + +#endif // CONFIG_HPP \ No newline at end of file diff --git a/src/level.cpp b/src/level.cpp index 74c1598..e190c3b 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -30,6 +30,8 @@ void Level::render(Engine &engine, std::vector<SDL_Event> &events) { events.erase(events.begin()); } + + // Tiles for (Tile &tile : tiles) { tile.render(engine, RENDERING_SCALE); diff --git a/src/main.cpp b/src/main.cpp index 6bb056f..d7c75d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,25 +8,33 @@ #include "window.hpp" #include <cstddef> #include <vector> +#include "config.hpp" +#include <iostream> using namespace advanced_wars; -int main() { +int main() +{ Window window("Advanced Wars", 960, 960); Engine engine(window); + + Unit::readXML(); // Construct a level std::vector<Tile> tiles; - for (int y = 0; y < 20; y++) { - for (int x = 0; x < 20; x++) { + 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++) { + 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); @@ -36,7 +44,8 @@ int main() { } // Make the edges cliffs - for (size_t n = 1; n < 19; n++) { + 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); @@ -55,8 +64,10 @@ int main() { // Buildings std::vector<Building> buildings; - for (int y = 0; y < 6; y++) { - for (int x = 0; x < 5; x++) { + 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); @@ -67,8 +78,10 @@ int main() { // Units std::vector<Unit> units; - for (int y = 0; y < 19; y++) { - for (int x = 0; x < 6; x++) { + 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))); } @@ -82,12 +95,13 @@ int main() { engine.set_scene(level); - Spritesheet spritesheet("/media/data/rust/sprite-extractor/spritesheet.h5", + Spritesheet spritesheet("/home/lorenz/Hochschule/5.Semester/C++/Projekt2/spritesheet.h5", engine); engine.set_spritesheet(spritesheet); - while (!engine.exited()) { + while (!engine.exited()) + { engine.pump(); engine.render(); } diff --git a/src/unit.cpp b/src/unit.cpp index 3a678b8..cecbae1 100644 --- a/src/unit.cpp +++ b/src/unit.cpp @@ -1,6 +1,7 @@ #include "unit.hpp" #include <tinyxml2.h> #include <iostream> +#include "config.hpp" namespace advanced_wars { @@ -71,7 +72,7 @@ namespace advanced_wars } MatchupTabel damageMatrix; - std::vector<Unit*> units; + std::vector<Unit *> units; void Unit::attack(Unit *ally, Unit *enemy) { @@ -174,6 +175,87 @@ namespace advanced_wars } return false; } + + // Config test start + + void Unit::readXML() + { + MatchupTabel_secondaryweapon secWeapon; + MatchupTabel_secondaryweapon primWeapon; + + Config config(secWeapon, primWeapon); + // Lade Konfigurationsdaten von XML + try + { + config.loadFromXML("../xml/config.xml"); + } + catch (const std::exception &e) + { + std::cerr << "Error loading XML: " << e.what() << std::endl; + } + + // Liste der zu testenden UnitIds + std::vector<UnitId> testUnits = {UnitId::INFANTERY, UnitId::MECHANIZED_INFANTERY}; + + for (auto id : testUnits) + { + try + { + int cost = config.get_unit_cost(id); + int movement = config.get_unit_movementPoints(id); + int ammo = config.get_unit_ammo(id); + int minRange = config.get_unit_minRange(id); + int maxRange = config.get_unit_maxRange(id); + + std::string primaryWeapon = "None"; + std::string secondaryWeapon = "None"; + + if (id == UnitId::INFANTERY || id == UnitId::MECHANIZED_INFANTERY) + { // Bsp.-Fall, hier müssten je nach Wunschbedingungen ID's ergänzt werden + try + { + primaryWeapon = config.get_unit_primaryweapon(id); + } + catch (...) + { + // Es passiert nichts, wenn die Primärwaffe fehlt + } + try + { + secondaryWeapon = config.get_unit_secondaryweapon(id); + } + catch (...) + { + // Es passiert nichts, wenn die Sekundärwaffe fehlt + } + } + + std::cout << "Unit ID: " << static_cast<int>(id) << std::endl; + std::cout << " Cost: " << cost << std::endl; + std::cout << " Movement Points: " << movement << std::endl; + std::cout << " Ammo: " << ammo << std::endl; + std::cout << " Primary Weapon: " << primaryWeapon << "; Range: " << minRange << "-" << maxRange << std::endl; + std::cout << " Secondary Weapon: " << secondaryWeapon << std::endl; + } + catch (const std::exception &e) + { + std::cerr << "Error retrieving unit data for ID " << static_cast<int>(id) << ": " << e.what() << std::endl; + } + } + std::cout << "Debug secWeapon Inhalt:" << std::endl; + for (const auto &outer : secWeapon) + { + std::cout << "Einheit ID: " << static_cast<int>(outer.first) << std::endl; + for (const auto &inner : outer.second) + { + std::cout << " Ziel ID: " << static_cast<int>(inner.first) + << " Schaden: " << inner.second << std::endl; + } + } + } + + // Config test end + /* void Unit::loadXML(const char *filename) { diff --git a/src/unit.hpp b/src/unit.hpp index 172233e..2e631b4 100644 --- a/src/unit.hpp +++ b/src/unit.hpp @@ -5,6 +5,7 @@ #include "weapon.hpp" #include <optional> + namespace advanced_wars { enum class UnitFaction { @@ -14,7 +15,7 @@ enum class UnitFaction { UYELLOW = 3, UPURPLE = 4, }; -/* + enum class UnitId { INFANTERY = 0, MECHANIZED_INFANTERY = 1, @@ -36,8 +37,8 @@ enum class UnitId { LANDER = 17, SUBMARINE = 18, }; -*/ +/* enum class UnitId { INFANTERY, MECH, @@ -58,7 +59,7 @@ enum class UnitId { CRUISER, LANDER, SUBMARINE, -}; +};*/ enum class UnitState { IDLE = 0, @@ -81,6 +82,9 @@ enum class MovementType { //Fill the MatchupTabel using MatchupTabel = std::unordered_map<u_int8_t, std::unordered_map<u_int8_t, int>>; +using MatchupTabel_secondaryweapon = std::unordered_map<UnitId, std::unordered_map<UnitId, int>>; +using MatchupTabel_primaryweapon = std::unordered_map<UnitId, std::unordered_map<UnitId, int>>; + class Unit { public: Unit(int x, int y, UnitFaction faction, UnitId id, UnitState state); @@ -127,6 +131,8 @@ public: */ void loadXML(const char* filename); +static void readXML(); + /* This function will be called by an external event-handler, eventually. diff --git a/XML/config.xml b/xml/config.xml similarity index 100% rename from XML/config.xml rename to xml/config.xml -- GitLab From 60811ac695c8921528c3203b05ff8f6a20ee17ef Mon Sep 17 00:00:00 2001 From: Lorenz <lorenz-martin.diel@informatik.hs-fulda.de> Date: Wed, 29 Jan 2025 12:55:44 +0100 Subject: [PATCH 3/3] small changes on xml --- src/config.cpp | 3 ++- src/unit.cpp | 5 +++-- xml/config.xml | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 692f166..d0353fb 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -53,6 +53,7 @@ namespace advanced_wars unit_minRange[unitId] = minRange; unit_maxRange[unitId] = maxRange; + /* for (const auto &weapon : unit.second.get_child("Weapons")) { if (weapon.first == "PrimaryWeapon") @@ -65,7 +66,7 @@ namespace advanced_wars std::string weaponName = weapon.second.get<std::string>("<xmlattr>.name"); unit_secondaryweapon[unitId] = weaponName; } - } + }*/ for (const auto &weapon : unit.second.get_child("Weapons")) { diff --git a/src/unit.cpp b/src/unit.cpp index cecbae1..6b3fc1b 100644 --- a/src/unit.cpp +++ b/src/unit.cpp @@ -6,6 +6,9 @@ namespace advanced_wars { + MatchupTabel_secondaryweapon secWeapon; + MatchupTabel_secondaryweapon primWeapon; + Unit::Unit(int x, int y, UnitFaction faction, UnitId id, UnitState state) : x(x), y(y), faction(faction), id(id), state(state) { @@ -180,8 +183,6 @@ namespace advanced_wars void Unit::readXML() { - MatchupTabel_secondaryweapon secWeapon; - MatchupTabel_secondaryweapon primWeapon; Config config(secWeapon, primWeapon); // Lade Konfigurationsdaten von XML diff --git a/xml/config.xml b/xml/config.xml index b2ba653..ab212cb 100644 --- a/xml/config.xml +++ b/xml/config.xml @@ -27,13 +27,13 @@ <PrimaryWeapon name="Rockets"> <DamageTable> <Damage unitId="infantry" value="65"/> - <Damage unitId="infantry" value="55"/> + <Damage unitId="Mech" value="55"/> </DamageTable> </PrimaryWeapon> <SecondaryWeapon name="Machine-Gun"> <DamageTable> <Damage unitId="infantry" value="65"/> - <Damage unitId="infantry" value="55"/> + <Damage unitId="Mech" value="55"/> </DamageTable> </SecondaryWeapon> </Weapons> -- GitLab