Skip to content
Snippets Groups Projects
Commit f16cae9b authored by Frederik's avatar Frederik
Browse files

Merge remote-tracking branch 'origin/main' into leveleditor

parents f4af0eb0 c3814c85
Branches
No related tags found
2 merge requests!38Merge the level editor,!29Merge main into box2d to implement physics
Showing with 3024 additions and 23 deletions
---
BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: AlwaysBreak
AlignArrayOfStructures: Right
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: Consecutive
AlignConsecutiveMacros: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterJavaFieldAnnotations: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
BreakBeforeConceptDeclarations: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: ^"(llvm|llvm-c|clang|clang-c)/
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: ^(<|"(gtest|gmock|isl|json)/)
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: .*
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: (Test)?$
IncludeIsMainSourceRegex: ""
IndentAccessModifiers: true
IndentCaseBlocks: true
IndentCaseLabels: false
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
Language: Cpp
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PPIndentWidth: -1
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
QualifierAlignment: Leave
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDeclarationName: false
AfterFunctionDefinitionName: false
AfterIfMacros: true
AfterOverloadedOperator: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
---
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
......@@ -54,9 +54,9 @@ Thumbs.db
*.gcov
coverage/
*.png
docs/generated/
clang-tidy-warnings.txt
bin/
lib/
......@@ -8,6 +8,8 @@ project(ADVANCED_WARS
)
include(FetchContent)
# HighFive einbinden
FetchContent_Declare(
highfive
GIT_REPOSITORY https://github.com/highfive-devs/highfive.git
......@@ -19,7 +21,23 @@ set(HIGHFIVE_UNIT_TESTS OFF)
FetchContent_MakeAvailable(highfive)
# Box2D einbinden
FetchContent_Declare(
box2d
GIT_REPOSITORY https://github.com/erincatto/box2d.git
GIT_TAG v3.0.0
)
set(BOX2D_BUILD_TESTBED OFF CACHE BOOL "" FORCE)
set(BOX2D_BUILD_UNIT_TESTS OFF CACHE BOOL "" FORCE)
set(BOX2D_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(box2d)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.71.0 REQUIRED COMPONENTS graph)
# Quellen sammeln
file(GLOB_RECURSE ADVANCED_WARS_SOURCES
......@@ -31,6 +49,12 @@ file(GLOB_RECURSE ADVANCED_WARS_SOURCES
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Wpedantic")
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Wpedantic")
add_definitions(-DDEBUG)
# Compiler-Warnungen aktivieren
if(MSVC)
......@@ -40,27 +64,16 @@ else()
endif()
# Ressourcen kopieren
set(ASSETS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/assets)
set(OUTPUT_ASSETS_DIR ${CMAKE_CURRENT_BINARY_DIR}/assets)
file(MAKE_DIRECTORY ${OUTPUT_ASSETS_DIR})
file(GLOB FONT_FILES ${ASSETS_DIR}/*.ttf)
set(RES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/res)
set(OUTPUT_RES_DIR ${CMAKE_CURRENT_BINARY_DIR}/res)
file(MAKE_DIRECTORY ${OUTPUT_RES_DIR})
file(GLOB FONT_FILES ${RES_DIR}/*.TTF)
file(GLOB IMAGE_FILES ${RES_DIR}/*.png)
file(GLOB HDF5_FILES ${RES_DIR}/*.h5)
# Executable erstellen
add_executable(advanced_wars ${ADVANCED_WARS_SOURCES})
target_include_directories(advanced_wars
PRIVATE
${highfive_SOURCE_DIR}/include
)
foreach(FONT ${FONT_FILES})
add_custom_command(
TARGET advanced_wars PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${FONT} ${OUTPUT_ASSETS_DIR}
COMMENT "Kopiere Font: ${FONT} nach ${OUTPUT_ASSETS_DIR}"
)
endforeach()
set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH})
# Plattform-spezifische Konfiguration
......@@ -68,6 +81,7 @@ if(APPLE)
# SDL2 Frameworks für macOS
set(SDL2_PATH "/Library/Frameworks")
set(CMAKE_OSX_ARCHITECTURES "arm64")
target_include_directories(
advanced_wars PRIVATE
${SDL2_PATH}/SDL2.framework/Headers
......@@ -80,20 +94,30 @@ if(APPLE)
${SDL2_PATH}/SDL2.framework/SDL2
${SDL2_PATH}/SDL2_image.framework/SDL2_image
${SDL2_PATH}/SDL2_ttf.framework/SDL2_ttf
Boost::graph
box2d
)
# Debug-Ausgaben
# HDF5 für macOS korrekt einbinden
find_package(HDF5 REQUIRED COMPONENTS CXX HL)
target_include_directories(advanced_wars PRIVATE ${HDF5_INCLUDE_DIRS} ${highfive_SOURCE_DIR}/include)
target_link_libraries(advanced_wars PRIVATE ${HDF5_LIBRARIES})
message(STATUS "Include Dir (SDL2): ${SDL2_PATH}/SDL2.framework/Headers")
message(STATUS "Include Dir (SDL2_image): ${SDL2_PATH}/SDL2_image.framework/Headers")
message(STATUS "Include Dir (SDL2_ttf): ${SDL2_PATH}/SDL2_ttf.framework/Headers")
message(STATUS "HDF5 Include Dirs: ${HDF5_INCLUDE_DIRS}")
message(STATUS "HDF5 Libraries: ${HDF5_LIBRARIES}")
message(STATUS "Boost Include Dirs: ${Boost_INCLUDE_DIRS}")
else()
# Linux Konfiguration
find_package(SDL2 REQUIRED)
find_package(SDL2_IMAGE REQUIRED)
find_package(SDL2_ttf REQUIRED)
find_package(HDF5 REQUIRED COMPONENTS CXX)
find_package(HDF5 REQUIRED COMPONENTS CXX HL)
include_directories(/usr/include/SDL2)
include_directories(${SDL2_INCLUDE_DIR})
include_directories(${SDL2_IMG_INCLUDE_DIR})
include_directories(${SDL2_TTF_INCLUDE_DIR})
......@@ -104,6 +128,8 @@ else()
-lSDL2
-lSDL2_image
-lSDL2_ttf
Boost::graph
box2d
m
)
endif()
......@@ -138,3 +164,30 @@ target_include_directories(writelevel
target_link_libraries(writelevel
${HDF5_LIBRARIES}
)
target_include_directories(advanced_wars PRIVATE ${highfive_SOURCE_DIR}/include)
# Ressourcen kopieren (plattformübergreifend)
foreach(FONT ${FONT_FILES})
add_custom_command(
TARGET advanced_wars PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${FONT} ${OUTPUT_RES_DIR}
COMMENT "Kopiere Font: ${FONT} nach ${OUTPUT_RES_DIR}"
)
endforeach()
foreach(IMAGE ${IMAGE_FILES})
add_custom_command(
TARGET advanced_wars PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${IMAGE} ${OUTPUT_RES_DIR}
COMMENT "Kopiere Image: ${IMAGE} nach ${OUTPUT_RES_DIR}"
)
endforeach()
foreach(H5_FILE ${HDF5_FILES})
add_custom_command(
TARGET advanced_wars PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${H5_FILE} ${OUTPUT_RES_DIR}
COMMENT "Kopiere HDF5 File: ${H5_FILE} nach ${OUTPUT_RES_DIR}"
)
endforeach()
# 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
......@@ -49,6 +58,31 @@
4. Visual Studio erkennt automatisch das CMake-Projekt
5. Build über "Build All" ausführen
#### Falls Syntax errors
1. Erstelle .vscode/c_cpp_properties.json Datei
2. Füge die folgende JSON so oder so ähnlich ein:
```json
{
"configurations": [
{
"name": "Fedora",
"includePath": [
"/usr/include",
"/usr/include/SDL2"
],
"defines": [],
"intelliSenseMode": "linux-gcc-x64",
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++17"
}
],
"version": 4
}
```
## Build-Optionen
CMake kann mit verschiedenen Optionen konfiguriert werden:
......
This diff is collapsed.
# Levelspezifikation
Das Level wird ueber 2 Datasets in der HDF5-Datei repraesentiert.
Ein Dataset in XML Format, das die Level Metadaten (Breite, Hoehe, Dataset ID Tiles Array) angibt.
Ein weiters Dataset, das letztlich ein array<uint8_t> ist, welches die Levelmap ueber ein Array von Tile IDs definiert.
## 1. XML Dataset mit Level Metadaten
```xml
<?xml version="1.0" encoding="ASCII"?>
<level>
<width>20</width> <!-- Breite des Levels -->
<height>20</height> <!-- Hoehe des Levels -->
<name>Geiles Level<name><!-- Name des Levels -->
</level>
```
## 2. Tiles Array
Das Tiles Array wird als array<uint8_t> in einem Dataset in der HDF5-Datei gespeichert.
Die Laenge des Arrays ist Breite X Hoehe (kann man aus XML Leveldefinition entnehmen).
Aus den einzelnen Werte in dem Array lassen sich die IDs der entsprechenden Gebaudes/Terrains ableiten.
0 - 29 sind Terrain IDs => Zuordnung siehe entsprechendes Enum in Tile.hpp
30-49 sind undefiniert
50-79 sind Gebaeude IDs:
50 => Faction ID 0, Gebaeude ID 0
51 => Faction ID 0, Gebaeude ID 1
...
55 => Faction ID 1, Gebaeude ID 0
56 => Faction ID 1, Gebaeude ID 1
57 => Faction ID 1, Gebaeude ID 2
...
Allgemein:
Sei t ein Wert im Tiles Array, dann gillt
falls t < 30: Terrain ID = t
falls t >= 50: Faction ID = (t - 50) / 5 Gebaeude ID = (t - 50) % 5
t wird ermittelt mit entweder t = Terrain ID fuer Terrains
oder t = 50 + 5*Faction Id + Gebaeude ID fuer Gebaeude
\ No newline at end of file
File added
res/main_background.png

2.57 KiB

File added
#include "Building.hpp"
#include "Spritesheet.hpp"
#include <iostream>
namespace advanced_wars
{
Building::Building(int x, int y, BuildingId id, BuildingFaction faction)
: m_x(x), m_y(y), m_id(id), m_faction(faction) {};
void Building::render(Engine& engine, int scale)
{
Spritesheet* spritesheet = engine.getSpritesheet();
SDL_Rect src;
src.x = static_cast<int>(m_id) * spritesheet->getBuildingWidth();
src.y = 0;
src.w = spritesheet->getBuildingWidth();
src.h = spritesheet->getBuildingHeight();
SDL_Rect dst;
dst.x = m_x * spritesheet->getTileWidth() * scale;
dst.y = (m_y - 1) * spritesheet->getTileHeight() * scale;
dst.w = spritesheet->getBuildingWidth() * scale;
dst.h = spritesheet->getBuildingHeight() * scale;
SDL_RenderCopyEx(
engine.renderer(), spritesheet->getBuildingTextures()[static_cast<int>(m_faction)], &src,
&dst, 0, NULL, SDL_FLIP_NONE);
}
BuildingFaction Building::getFaction()
{
return this->m_faction;
}
bool Building::switch_faction(BuildingFaction faction)
{
this->m_faction = faction;
if (this->m_id == BuildingId::HEADQUARTER)
{
return true;
}
return false;
}
// implement call to UI to show available units
void Building::on_click()
{
std::cout << "A building is selected!" << std::endl;
};
bool Building::check_spawn(std::unordered_map<int, advanced_wars::Unit>& units)
{
for (auto& [id, unit] : units)
{
if (unit.m_x == this->m_x && unit.m_y == this->m_y)
{
return false;
}
}
return true;
}
// can be added as soon as the playerobject is available
bool Building::check_money(int price, int playerMoney)
{
// replace 400 with player.money and replace price with chosenUnit.price
return (playerMoney >= price);
}
std::vector<UnitId> Building::recruitableUnits()
{
if (this->m_id == BuildingId::FACTORY)
{
return {
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};
}
if (this->m_id == BuildingId::PORT)
{
return {UnitId::LANDER, UnitId::CRUISER, UnitId::SUBMARINE, UnitId::BATTLESHIP};
}
if (this->m_id == BuildingId::AIRPORT)
{
return {
UnitId::TRANSPORT_HELICOPTER, UnitId::BATTLE_HELICOPTER, UnitId::FIGHTER,
UnitId::BOMBER};
}
return {};
}
BuildingId Building::getBuildingId()
{
return this->m_id;
}
} // namespace advanced_wars
\ No newline at end of file
#pragma once
#include "Engine.hpp"
#include "Scene.hpp"
#include "Unit.hpp"
#include <unordered_map>
namespace advanced_wars
{
class Building
{
public:
Building(int x, int y, BuildingId id, BuildingFaction faction);
int m_x;
int m_y;
BuildingId m_id;
BuildingFaction m_faction;
void render(Engine& engine, int scale);
BuildingFaction getFaction();
/**
Changes the faction to the specified one
@param faction The new faction the unit will belong to
@return true if building was a headquarter
*/
bool switch_faction(BuildingFaction faction);
/*
checks if the tile ontop of the building is free
*/
bool check_spawn(std::unordered_map<int, advanced_wars::Unit>& units);
/*
checks if the player has enough money for the unit to be recruited
*/
bool check_money(int price, int playerMoney);
/**
If the building is clicked, it shows information to the player, here it will be a list of
all available units
*/
void on_click();
/**
* Provides a vector of recruitable units, depending on the building id
*
*/
std::vector<UnitId> recruitableUnits();
BuildingId getBuildingId();
};
} // namespace advanced_wars
\ No newline at end of file
#include "Config.hpp"
#include "Unit.hpp"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_map>
namespace advanced_wars
{
Config::Config(std::string filename)
{
namespace pt = boost::property_tree;
pt::ptree tree;
pt::read_xml(filename, tree);
for (const auto& unit : tree.get_child("Units"))
{
if (unit.first != "Unit")
continue;
const auto& unitData = unit.second;
std::string unit_key = unitData.get<std::string>("<xmlattr>.key");
try
{
UnitId unitId = mapUnitKeyToID(unit_key);
m_unitCosts[unitId] = unitData.get<int>("Cost");
m_unitMovementPoints[unitId] = unitData.get<int>("MovementPoints");
m_unitAmmo[unitId] = unitData.get<int>("Ammo");
m_unitMinRange[unitId] = unitData.get<int>("minRange", 0);
m_unitMaxRange[unitId] = unitData.get<int>("maxRange", 0);
std::string movement_type_str = unitData.get<std::string>("MovementType");
try
{
m_unitMovementType[unitId] = mapMovementType(movement_type_str);
}
catch (const std::out_of_range& e)
{
std::cerr << "Unknown movement type: " << movement_type_str
<< " for unit key: " << unit_key << std::endl;
continue;
}
for (const auto& weapon : unitData.get_child("Weapons"))
{
if (weapon.first == "PrimaryWeapon")
{
m_unitPrimaryWeapon[unitId] = weapon.second.get<std::string>("<xmlattr>.name");
for (const auto& damage : weapon.second.get_child("DamageTable"))
{
if (damage.first != "Damage")
continue;
std::string target_key = damage.second.get<std::string>("<xmlattr>.unitId");
UnitId targetId = mapUnitKeyToID(target_key);
m_primaryWeaponDamage[unitId][targetId] =
damage.second.get<int>("<xmlattr>.value");
}
}
else if (weapon.first == "SecondaryWeapon")
{
m_unitSecondaryWeapon[unitId] =
weapon.second.get<std::string>("<xmlattr>.name");
for (const auto& damage : weapon.second.get_child("DamageTable"))
{
if (damage.first != "Damage")
continue;
std::string target_key = damage.second.get<std::string>("<xmlattr>.unitId");
UnitId targetId = mapUnitKeyToID(target_key);
m_secondaryWeaponDamage[unitId][targetId] =
damage.second.get<int>("<xmlattr>.value");
}
}
}
}
catch (const std::out_of_range& e)
{
// std::cerr << "Unknown unit key: " << unit_key << std::endl;
continue;
}
}
}
UnitId Config::mapUnitKeyToID(const std::string& unit_key) const
{
static const std::unordered_map<std::string, UnitId> unit_map = {
{ "infantry", UnitId::INFANTERY},
{ "mechanized_infantry", UnitId::MECHANIZED_INFANTERY},
{ "recon", UnitId::RECON},
{ "apc", UnitId::APC},
{ "anti_air_tank", UnitId::ANTI_AIR_TANK},
{ "medium_tank", UnitId::MEDIUM_TANK},
{ "heavy_tank", UnitId::HEAVY_TANK},
{ "neotank", UnitId::NEO_TANK},
{ "artillery", UnitId::ARTILLERY},
{ "rocket_artillery", UnitId::ROCKET_ARTILLERY},
{"anti_air_missile_launcher", UnitId::ANTI_AIR_MISSILE_LAUNCHER},
{ "lander", UnitId::LANDER},
{ "cruiser", UnitId::CRUISER},
{ "submarine", UnitId::SUBMARINE},
{ "battleship", UnitId::BATTLESHIP},
{ "transport_helicopter", UnitId::TRANSPORT_HELICOPTER},
{ "battle_helicopter", UnitId::BATTLE_HELICOPTER},
{ "fighter", UnitId::FIGHTER},
{ "bomber", UnitId::BOMBER}
};
auto it = unit_map.find(unit_key);
if (it != unit_map.end())
{
return it->second;
}
throw std::out_of_range("Unknown unit key: " + unit_key);
}
MovementType Config::mapMovementType(const std::string& movementTypeStr) const
{
static const std::unordered_map<std::string, MovementType> movement_map = {
{ "Foot", MovementType::FOOT},
{"Wheeled", MovementType::WHEELED},
{ "Tread", MovementType::TREAD},
{ "Air", MovementType::AIR},
{ "Sea", MovementType::SEA},
{ "Lander", MovementType::LANDER}
};
auto it = movement_map.find(movementTypeStr);
if (it != movement_map.end())
{
return it->second;
}
throw std::out_of_range("Unknown movement type: " + movementTypeStr);
}
int Config::getUnitCost(UnitId id) const
{
auto it = m_unitCosts.find(id);
if (it != m_unitCosts.end())
{
return it->second;
}
throw std::runtime_error("Cost for unit ID not found");
}
int Config::getUnitMovementPoints(UnitId id) const
{
auto it = m_unitMovementPoints.find(id);
if (it != m_unitMovementPoints.end())
{
return it->second;
}
throw std::runtime_error("Movement points for unit ID not found");
}
MovementType Config::getUnitMovementType(UnitId id) const
{
auto it = m_unitMovementType.find(id);
if (it != m_unitMovementType.end())
{
return it->second;
}
throw std::runtime_error("Movement type for unit ID not found");
}
int Config::getUnitAmmo(UnitId id) const
{
auto it = m_unitAmmo.find(id);
if (it != m_unitAmmo.end())
{
return it->second;
}
throw std::runtime_error("Ammo for unit ID not found");
}
int Config::getUnitMinRange(UnitId id) const
{
auto it = m_unitMinRange.find(id);
if (it != m_unitMinRange.end())
{
return it->second;
}
throw std::runtime_error("Min range for unit ID not found");
}
int Config::getUnitMaxRange(UnitId id) const
{
auto it = m_unitMaxRange.find(id);
if (it != m_unitMaxRange.end())
{
return it->second;
}
throw std::runtime_error("Max range for unit ID not found");
}
std::string Config::getUnitPrimaryWeapon(UnitId id) const
{
auto it = m_unitPrimaryWeapon.find(id);
if (it != m_unitPrimaryWeapon.end())
{
return it->second;
}
return "";
}
std::string Config::getUnitSecondaryWeapon(UnitId id) const
{
auto it = m_unitSecondaryWeapon.find(id);
if (it != m_unitSecondaryWeapon.end())
{
return it->second;
}
return "";
}
std::optional<int> Config::getUnitPrimaryWeaponDamage(UnitId attackerId, UnitId targetId) const
{
auto attackerMapIt = m_primaryWeaponDamage.find(attackerId);
if (attackerMapIt != m_primaryWeaponDamage.end())
{
auto damageIt = attackerMapIt->second.find(targetId);
if (damageIt != attackerMapIt->second.end())
{
return damageIt->second;
}
}
// Kein spezifischer Schaden vorhanden
return std::nullopt;
}
std::optional<int> Config::getUnitSecondaryWeaponDamage(UnitId attackerId, UnitId targetId) const
{
auto attackerMapIt = m_secondaryWeaponDamage.find(attackerId);
if (attackerMapIt != m_secondaryWeaponDamage.end())
{
auto damageIt = attackerMapIt->second.find(targetId);
if (damageIt != attackerMapIt->second.end())
{
return damageIt->second;
}
}
// Kein spezifischer Schaden vorhanden
return std::nullopt;
}
} // namespace advanced_wars
\ No newline at end of file
#pragma once
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_map>
namespace advanced_wars
{
/* ENUMS FOR GLOBAL USE*/
enum class BuildingFaction
{
URED = 0,
UBLUE = 1,
UGREEN = 2,
UYELLOW = 3,
UPURPLE = 4,
};
enum class BuildingId
{
HEADQUARTER = 0,
CITY = 1,
FACTORY = 2,
AIRPORT = 3,
PORT = 4,
};
enum class UnitFaction
{
URED = 0,
UBLUE = 1,
UGREEN = 2,
UYELLOW = 3,
UPURPLE = 4,
};
enum class UnitId
{
INFANTERY = 0,
MECHANIZED_INFANTERY = 1,
RECON = 2,
MEDIUM_TANK = 3,
HEAVY_TANK = 4,
NEO_TANK = 5,
APC = 6,
ANTI_AIR_TANK = 7,
ARTILLERY = 8,
ROCKET_ARTILLERY = 9,
ANTI_AIR_MISSILE_LAUNCHER = 10,
FIGHTER = 11,
BOMBER = 12,
BATTLE_HELICOPTER = 13,
TRANSPORT_HELICOPTER = 14,
BATTLESHIP = 15,
CRUISER = 16,
LANDER = 17,
SUBMARINE = 18,
FIRST = INFANTERY,
LAST = SUBMARINE
};
enum class UnitState
{
IDLE = 0,
UNAVAILABLE = 1,
MOVEMENTLEFT = 2,
MOVEMENTRIGHT = 3,
MOVEMENTDOWN = 4,
MOVEMENTUP = 5,
};
enum class MovementType
{
FOOT = 0,
WHEELED = 1,
TREAD = 2,
AIR = 3,
SEA = 4,
LANDER = 5,
};
enum class TileId
{
PLAIN = 0,
WATER = 1,
FOREST = 2,
MOUNTAIN = 3,
BRIDGE_HORIZONTAL = 4,
BRIDGE_VERTICAL = 5,
STREET_HORIZONTAL = 6,
STREET_VERTICAL = 7,
STREET_CROSSING = 8,
STREET_JUNCTION_RIGHT = 9,
STREET_JUNCTION_LEFT = 10,
STREET_JUNCTION_DOWN = 11,
STREET_JUNCTION_UP = 12,
STREET_CORNER_TOP_LEFT = 13,
STREET_CORNER_TOP_RIGHT = 14,
STREET_CORNER_BOTTOM_LEFT = 15,
STREET_CORNER_BOTTOM_RIGHT = 16,
RIFF = 17,
CLIFF_TOP = 18,
CLIFF_BOTTOM = 19,
CLIFF_LEFT = 20,
CLIFF_RIGHT = 21,
CLIFF_CORNER_TOP_LEFT = 22,
CLIFF_CORNER_TOP_RIGHT = 23,
CLIFF_CORNER_BOTTOM_LEFT = 24,
CLIFF_CORNER_BOTTOM_RIGHT = 25,
CLIFF_INVERSE_CORNER_TOP_LEFT = 26,
CLIFF_INVERSE_CORNER_TOP_RIGHT = 27,
CLIFF_INVERSE_CORNER_BOTTOM_LEFT = 28,
CLIFF_INVERSE_CORNER_BOTTOM_RIGHT = 29,
};
/* END OF ALL ENUMS*/
/**
* @class Config
* @brief Parses and stores unit configuration data from an XML file.
*
* This class reads unit attributes, movement types, weapon data, and damage tables
* from an XML configuration file and provides access to this data through getter methods.
*/
class Config
{
public:
/**
* @brief Constructs a Config object and loads data from an XML file.
*
* The constructor reads the XML file, extracts unit properties, movement types,
* and weapon damage tables, and stores them in internal data structures.
*
* @param filename Path to the XML configuration file.
* @throws std::runtime_error if the file cannot be read or parsed.
*/
Config(std::string filename);
/** @brief Retrieves the cost of a given unit type. */
int getUnitCost(UnitId id) const;
/** @brief Retrieves the movement points of a given unit type. */
int getUnitMovementPoints(UnitId id) const;
/** @brief Retrieves the maximum ammunition capacity of a given unit type. */
int getUnitAmmo(UnitId id) const;
/** @brief Retrieves the minimum attack range of a given unit type. */
int getUnitMinRange(UnitId id) const;
/** @brief Retrieves the maximum attack range of a given unit type. */
int getUnitMaxRange(UnitId id) const;
/** @brief Retrieves the name of the primary weapon of a given unit type. */
std::string getUnitPrimaryWeapon(UnitId id) const;
/** @brief Retrieves the name of the secondary weapon of a given unit type. */
std::string getUnitSecondaryWeapon(UnitId id) const;
/** @brief Retrieves the damage value of a unit's primary weapon against a target unit type.
*/
std::optional<int> getUnitPrimaryWeaponDamage(UnitId attackerid, UnitId defenderid) const;
/** @brief Retrieves the damage value of a unit's secondary weapon against a target unit
* type. */
std::optional<int> getUnitSecondaryWeaponDamage(UnitId attackerid, UnitId defenderid) const;
/** @brief Retrieves the movement type of a given unit type. */
MovementType getUnitMovementType(UnitId id) const;
private:
/** @brief Maps unit IDs to their cost values. */
std::unordered_map<UnitId, int> m_unitCosts;
/** @brief Maps unit IDs to their movement points. */
std::unordered_map<UnitId, int> m_unitMovementPoints;
/** @brief Maps unit IDs to their maximum ammunition capacity. */
std::unordered_map<UnitId, int> m_unitAmmo;
/** @brief Maps unit IDs to their minimum attack range. */
std::unordered_map<UnitId, int> m_unitMinRange;
/** @brief Maps unit IDs to their maximum attack range. */
std::unordered_map<UnitId, int> m_unitMaxRange;
/** @brief Maps unit IDs to their primary weapon names. */
std::unordered_map<UnitId, std::string> m_unitPrimaryWeapon;
/** @brief Maps unit IDs to their secondary weapon names. */
std::unordered_map<UnitId, std::string> m_unitSecondaryWeapon;
/** @brief Stores primary weapon damage values for attacker-defender unit combinations. */
std::unordered_map<UnitId, std::unordered_map<UnitId, int>> m_primaryWeaponDamage;
/** @brief Stores secondary weapon damage values for attacker-defender unit combinations. */
std::unordered_map<UnitId, std::unordered_map<UnitId, int>> m_secondaryWeaponDamage;
/** @brief Maps unit IDs to their movement types. */
std::unordered_map<UnitId, MovementType> m_unitMovementType;
/**
* @brief Converts a unit key string from the XML file to its corresponding UnitId.
*
* If the key is unknown, it returns UnitId::UNKNOWN.
*
* @param unit_key The string key representing a unit type.
* @return The corresponding UnitId.
*/
UnitId mapUnitKeyToID(const std::string& unit_key) const;
/**
* @brief Converts a movement type string from the XML file to its corresponding
* MovementType.
*
* If the movement type is unknown, it returns MovementType::UNKNOWN.
*
* @param movementTypeStr The string representation of the movement type.
* @return The corresponding MovementType.
*/
MovementType mapMovementType(const std::string& movementTypeStr) const;
};
} // namespace advanced_wars
#include "Effect.hpp"
#include "Spritesheet.hpp"
#include <vector>
namespace advanced_wars
{
Effect::Effect(int x, int y, EffectId id, bool repeat)
: m_x(x), m_y(y), m_id(id), m_repeat(repeat), m_start(0) {
};
void Effect::render(Engine& engine, int scale)
{
Spritesheet* spritesheet = engine.getSpritesheet();
if (m_start == 0)
{
m_start = engine.getStage();
}
int step =
engine.getStage() % spritesheet->getEffectTextures().at(static_cast<int>(m_id)).second;
SDL_Rect src;
src.x = step * spritesheet->getEffectWidth() + step * spritesheet->getEffectHeight();
src.y = 0;
src.w = spritesheet->getEffectWidth();
src.h = spritesheet->getEffectHeight();
SDL_Rect dest;
dest.x = (m_x * spritesheet->getTileWidth() * scale) - 8;
dest.y = (m_y * spritesheet->getTileHeight() * scale) - 8;
dest.w = spritesheet->getEffectWidth() * scale;
dest.h = spritesheet->getEffectHeight() * scale;
SDL_RenderCopyEx(
engine.renderer(), spritesheet->getEffectTextures().at(static_cast<int>(m_id)).first, &src,
&dest, 0, NULL, SDL_FLIP_NONE);
}
bool Effect::is_finished(Engine& engine)
{
return !(
engine.getStage() - m_start <=
engine.getSpritesheet()->getEffectTextures().at(static_cast<int>(m_id)).second ||
m_repeat);
}
} // namespace advanced_wars
\ No newline at end of file
#pragma once
#include "Engine.hpp"
namespace advanced_wars
{
enum class EffectId
{
LAND_EXPLOSION = 0,
AIR_EXPLOSION = 1,
NAVAL_EXPLOSION = 2,
SUBMARINE_HIDE = 3,
SUBMARINE_APPEAR = 4
};
class Effect
{
public:
Effect(int x, int y, EffectId id, bool repeat);
void render(Engine& engine, int scale);
bool is_finished(Engine& engine);
int m_x;
int m_y;
EffectId m_id;
bool m_repeat;
int m_start;
};
} // namespace advanced_wars
\ No newline at end of file
#include "Engine.hpp"
#include "SDL_events.h"
#include "SDL_timer.h"
#include "Scene.hpp"
#include "Spritesheet.hpp"
#include "Window.hpp"
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_render.h>
#include <deque>
#include <memory>
#include <optional>
#include <stdexcept>
namespace advanced_wars
{
Engine::Engine(Window& window) : m_window(window), m_quit(false), m_unitConfig("../config.xml")
{
this->m_SDLRenderer = SDL_CreateRenderer(
this->m_window.sdl_window(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (m_SDLRenderer == nullptr)
{
throw std::runtime_error("SDL could not generate renderer: " + std::string(SDL_GetError()));
}
}
std::deque<SDL_Event>& Engine::events()
{
return this->m_events;
}
void Engine::pushScene(std::shared_ptr<Scene> scene)
{
this->m_scenes.push_back(scene);
}
void Engine::returnToMenu()
{
// TODO: discuss if we outsource this to a separate function
// clear everything except the first scene
while (this->m_scenes.size() > 1)
{
this->m_scenes.pop_back();
}
}
std::optional<std::shared_ptr<Scene>> Engine::popScene()
{
if (this->m_scenes.empty())
{
return std::nullopt;
}
std::shared_ptr<Scene> tmp = m_scenes.back();
this->m_scenes.pop_back();
return tmp;
}
void Engine::setSpritesheet(Spritesheet& spritesheet)
{
this->m_spritesheet = &spritesheet;
}
void Engine::pump()
{
SDL_Event e;
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
{
this->m_quit = true;
}
else
{
this->m_events.push_back(e);
}
}
std::shared_ptr<Scene> currentScene = m_scenes.back();
while (m_events.size() > 0)
{
currentScene->handleEvent(*this, m_events.at(0));
m_events.pop_front();
}
}
void Engine::exit()
{
this->m_quit = true;
}
bool Engine::exited()
{
return this->m_quit;
}
void Engine::render()
{
if (SDL_RenderClear(this->m_SDLRenderer) != 0)
{
throw std::runtime_error("Could not clear renderer: " + std::string(SDL_GetError()));
}
std::shared_ptr<Scene> currentScene = m_scenes.back();
currentScene->render(*this);
// prevent epilepsy
SDL_SetRenderDrawColor(this->m_SDLRenderer, 128, 128, 128, 128);
SDL_RenderPresent(this->m_SDLRenderer);
}
int Engine::getStage()
{
return SDL_GetTicks() / 300;
}
Spritesheet* Engine::getSpritesheet()
{
return m_spritesheet.value();
}
Config& Engine::getUnitConfig()
{
return m_unitConfig;
}
SDL_Renderer* Engine::renderer()
{
return this->m_SDLRenderer;
}
Engine::~Engine()
{
SDL_DestroyRenderer(m_SDLRenderer);
IMG_Quit();
SDL_Quit();
}
} // namespace advanced_wars
#pragma once
#include "Config.hpp"
#include "SDL_events.h"
#include "Scene.hpp"
#include "Spritesheet.hpp"
#include "Window.hpp"
#include <SDL.h>
#include <SDL_render.h>
#include <deque>
#include <memory>
#include <optional>
namespace advanced_wars
{
// Forward declaration
class Scene;
class Config;
/**
* @brief The main window of the game
*/
class Engine
{
public:
Engine(Window& window);
Engine(const Engine&) = delete;
Engine& operator=(const Engine&) = delete;
bool exited();
void exit();
void pump();
void pushScene(std::shared_ptr<Scene> scene);
std::optional<std::shared_ptr<Scene>> popScene();
void returnToMenu();
std::deque<SDL_Event>& events();
void setSpritesheet(Spritesheet& spritesheet);
Spritesheet* getSpritesheet();
int getStage();
Config& getUnitConfig();
void render();
SDL_Renderer* renderer();
~Engine();
private:
Window& m_window;
SDL_Renderer* m_SDLRenderer;
std::vector<std::shared_ptr<Scene>> m_scenes;
std::optional<Spritesheet*> m_spritesheet;
std::deque<SDL_Event> m_events;
bool m_quit;
int m_stage;
Config m_unitConfig;
};
} // namespace advanced_wars
This diff is collapsed.
#pragma once
#include "Building.hpp"
#include "Effect.hpp"
#include "Engine.hpp"
#include "Player.hpp"
#include "Scene.hpp"
#include "Tile.hpp"
#include "Unit.hpp"
#include "ui/Contextmenu.hpp"
#include "ui/Helpmenu.hpp"
#include "ui/Recruitingmenu.hpp"
#include "ui/TileMarker.hpp"
#include "ui/UnitInfoMenu.hpp"
#include <SDL.h>
#include <array>
#include <queue>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace advanced_wars
{
const int NUM_TILE_IDS = 30; // Aktualisieren, falls weitere IDs hinzugefügt werden
const int NUM_MOVEMENT_TYPES = 6;
const std::array<std::array<int, NUM_MOVEMENT_TYPES>, NUM_TILE_IDS> moveCostTable = {
{
// FOOT, WHEELED, TREAD, AIR, SEA, LANDER
{1, 2, 1, 1, 999, 999}, // PLAIN
{999, 999, 999, 1, 1, 1}, // WATER
{1, 3, 2, 1, 999, 999}, // FOREST
{2, 999, 999, 1, 999, 999}, // MOUNTAIN
{1, 1, 1, 1, 999, 999}, // BRIDGE_HORIZONTAL
{1, 1, 1, 1, 999, 999}, // BRIDE_VERTICAL
{1, 1, 1, 1, 999, 999}, // STREET_HORIZONTAL
{1, 1, 1, 1, 999, 999}, // STREET_VERTICAL
{1, 1, 1, 1, 999, 999}, // STREET_CROSSING
{1, 1, 1, 1, 999, 999}, // STREET_JUNCTION_RIGHT
{1, 1, 1, 1, 999, 999}, // STREET_JUNCTION_LEFT
{1, 1, 1, 1, 999, 999}, // STREET_JUNCTION_DOWN
{1, 1, 1, 1, 999, 999}, // STREET_JUNCTION_UP
{1, 1, 1, 1, 999, 999}, // STREET_CORNER_TOP_LEFT
{1, 1, 1, 1, 999, 999}, // STREET_CORNER_TOP_RIGHT
{1, 1, 1, 1, 999, 999}, // STREET_CORNER_BOTTOM_LEFT
{1, 1, 1, 1, 999, 999}, // STREET_CORNER_BOTTOM_RIGHT
{999, 999, 999, 1, 2, 2}, // RIFF
{999, 999, 999, 1, 1, 1}, // CLIFF_TOP
{999, 999, 999, 1, 1, 1}, // CLIFF_BOTTOM
{999, 999, 999, 1, 1, 1}, // CLIFF_LEFT
{999, 999, 999, 1, 1, 1}, // CLIFF_RIGHT
{999, 999, 999, 1, 1, 1}, // CLIFF_CORNER_TOP_LEFT
{999, 999, 999, 1, 1, 1}, // CLIFF_CORNER_TOP_RIGHT
{999, 999, 999, 1, 1, 1}, // CLIFF_CORNER_BOTTOM_LEFT
{999, 999, 999, 1, 1, 1}, // CLIFF_CORNER_BOTTOM_RIGHT
{999, 999, 999, 1, 1, 1}, // CLIFF_INVERSE_CORNER_TOP_LEFT
{999, 999, 999, 1, 1, 1}, // CLIFF_INVERSE_CORNER_TOP_RIGHT
{999, 999, 999, 1, 1, 1}, // CLIFF_INVERSE_CORNER_BOTTOM_LEFT
{999, 999, 999, 1, 1, 1}, // CLIFF_INVERSE_CORNER_BOTTOM_RIGHT
}
};
enum class LevelState
{
SELECTING_STATE,
MOVEMENT_STATE,
ANIMATING_STATE,
MENUACTIVE_STATE,
ATTACKING_STATE,
RECRUITING_STATE,
};
/**
* @brief The main window of the game
*/
class Level : public Scene
{
public:
Level(
std::string name, int width, int height, std::vector<Tile> tiles,
std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect> effects,
std::queue<Player> turnQ);
static std::shared_ptr<Level> loadLevel(const std::string& path, Engine& engine);
void render(Engine& engine);
/*
on event
key down
escape -> deselect/ open pause menu
key left -> move one tile left
key right -> move one tile right
key up -> move one tile up / change context menu selection up
key down -> move one tile down / change context menu selection down
key enter -> confirm selection in context menu /
confirm selected position(moving)/
select entity on tile
mousebutton down
button left -> select field/building/unit/
move to position
*/
void handleEvent(Engine& engine, SDL_Event& event);
int addBuilding(Building building);
Building removeBuilding(int id);
int addUnit(Unit unit);
Unit removeUnit(int id);
int addEffect(Effect effect);
Effect removeEffect(int id);
std::vector<std::pair<int, int>> calculateMovementRange(Unit& unit);
int getMoveCost(TileId type, MovementType movementType);
std::vector<std::pair<int, int>> m_reachableTiles;
std::vector<std::pair<int, int>> m_attackableTiles;
bool m_gameOver;
private:
std::string m_name;
int m_width;
int m_height;
std::vector<Tile> m_tiles;
std::unordered_map<int, Building> m_buildings;
std::unordered_map<int, Unit> m_units;
std::unordered_map<int, Effect> m_effects;
std::queue<Player> m_turnQ;
int m_selectedUnit;
int m_selectedBuilding;
int m_captureBuilding;
ContextMenu m_contextMenu;
RecruitingMenu m_recruitingMenu;
bool toggle_Helpmenu = false;
HelpMenu m_helpMenu;
int m_id;
LevelState m_state;
std::pair<int, int> calcTilePos(int mouseX, int mouseY);
void selectEntity(int x, int y);
int selectUnit(int tileX, int tileY);
int selectBuilding(int tileX, int tileY);
TileMarker m_currentPos;
void handleSelectingEvents(Engine& engine, SDL_Event& event);
void handleMenuActiveEvents(Engine& engine, SDL_Event& event);
void handleMovementEvents(Engine& engine, SDL_Event& event);
void handleAttackingEvents(Engine& engine, SDL_Event& event);
void handleRecruitingEvent(Engine& engine, SDL_Event& event);
bool clickCheckLeft(int mouseX, int mouseY);
bool clickCheckRight(int mouseX, int mouseY);
void changeTurn();
bool m_showReachableTiles;
bool m_showAttackableTiles;
std::unordered_set<int> m_attackableUnitIds;
void handleAttack(std::pair<int, int> tilePos);
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;
};
} // namespace advanced_wars
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment