diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0353fbf28a46bda73815d4a21a001de66cf1674 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,193 @@ +#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 +#include "config.hpp" +namespace pt = boost::property_tree; + +namespace advanced_wars +{ + + Config::Config(MatchupTabel_secondaryweapon& secWeapon, MatchupTabel_primaryweapon& primWeapon) + : secondary_weapon_damage(secWeapon), primary_weapon_damage(primWeapon) + { + // Initialisierung hier wenn nötig + } + 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::MECHANIZED_INFANTERY; + } + 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; + } + }*/ + + 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; + } + } + } + } + } + } + } + + // 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/config.hpp b/src/config.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d5b8109d23c1f62b651fc1fa5f6bdf70c6fba250 --- /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 74c159800e689266fe4a92ed3ffad76ce0cedc09..e190c3ba488301bdb1b1126db17844925fa58336 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 6bb056ffd35dfa5dc85a9a41bf0790a71f8c4ecd..d7c75d97ce14872d2034a7e3a1a56d77dd30c9e8 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 3a678b8c3c8e1cebd512144fcdc21b917364f935..6b3fc1b9d4e5546d9f42d1e2b34a889528cdc81e 100644 --- a/src/unit.cpp +++ b/src/unit.cpp @@ -1,10 +1,14 @@ #include "unit.hpp" #include <tinyxml2.h> #include <iostream> +#include "config.hpp" 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) { @@ -71,7 +75,7 @@ namespace advanced_wars } MatchupTabel damageMatrix; - std::vector<Unit*> units; + std::vector<Unit *> units; void Unit::attack(Unit *ally, Unit *enemy) { @@ -174,6 +178,85 @@ namespace advanced_wars } return false; } + + // Config test start + + void Unit::readXML() + { + + 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 dfb5fc01e3d3b17727d8b82bdc741b9b29207123..2e631b4e726d9b91ffe0e20b259445c91173615d 100644 --- a/src/unit.hpp +++ b/src/unit.hpp @@ -5,6 +5,7 @@ #include "weapon.hpp" #include <optional> + namespace advanced_wars { enum class UnitFaction { @@ -37,6 +38,29 @@ enum class UnitId { 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, UNAVAILABLE = 1, @@ -58,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); @@ -104,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 new file mode 100644 index 0000000000000000000000000000000000000000..ab212cbdf18367dbdbfd41444186238145c8f9c2 --- /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="Mech" value="55"/> + </DamageTable> + </PrimaryWeapon> + <SecondaryWeapon name="Machine-Gun"> + <DamageTable> + <Damage unitId="infantry" value="65"/> + <Damage unitId="Mech" value="55"/> + </DamageTable> + </SecondaryWeapon> + </Weapons> + </Unit> +</Units>