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

Fix problems from units branch merge conflicts

parent 07726a73
No related branches found
No related tags found
1 merge request!15Merge units into main
---
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
...@@ -19,7 +19,23 @@ set(HIGHFIVE_UNIT_TESTS OFF) ...@@ -19,7 +19,23 @@ set(HIGHFIVE_UNIT_TESTS OFF)
FetchContent_MakeAvailable(highfive) FetchContent_MakeAvailable(highfive)
FetchContent_Declare(
box2d
GIT_REPOSITORY https://github.com/erincatto/box2d.git
GIT_TAG v3.0.0
)
# Box2D Build-Optionen konfigurieren
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 # Quellen sammeln
file(GLOB_RECURSE ADVANCED_WARS_SOURCES file(GLOB_RECURSE ADVANCED_WARS_SOURCES
...@@ -31,6 +47,12 @@ file(GLOB_RECURSE ADVANCED_WARS_SOURCES ...@@ -31,6 +47,12 @@ file(GLOB_RECURSE ADVANCED_WARS_SOURCES
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) 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 # Compiler-Warnungen aktivieren
if(MSVC) if(MSVC)
...@@ -43,7 +65,8 @@ endif() ...@@ -43,7 +65,8 @@ endif()
set(ASSETS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/assets) set(ASSETS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/assets)
set(OUTPUT_ASSETS_DIR ${CMAKE_CURRENT_BINARY_DIR}/assets) set(OUTPUT_ASSETS_DIR ${CMAKE_CURRENT_BINARY_DIR}/assets)
file(MAKE_DIRECTORY ${OUTPUT_ASSETS_DIR}) file(MAKE_DIRECTORY ${OUTPUT_ASSETS_DIR})
file(GLOB FONT_FILES ${ASSETS_DIR}/*.ttf) file(GLOB FONT_FILES ${ASSETS_DIR}/*.TTF)
file(GLOB IMAGE_FILES ${ASSETS_DIR}/*.png)
# Executable erstellen # Executable erstellen
add_executable(advanced_wars ${ADVANCED_WARS_SOURCES}) add_executable(advanced_wars ${ADVANCED_WARS_SOURCES})
...@@ -51,6 +74,7 @@ add_executable(advanced_wars ${ADVANCED_WARS_SOURCES}) ...@@ -51,6 +74,7 @@ add_executable(advanced_wars ${ADVANCED_WARS_SOURCES})
target_include_directories(advanced_wars target_include_directories(advanced_wars
PRIVATE PRIVATE
${highfive_SOURCE_DIR}/include ${highfive_SOURCE_DIR}/include
${Boost_INCLUDE_DIRS}
) )
foreach(FONT ${FONT_FILES}) foreach(FONT ${FONT_FILES})
...@@ -61,6 +85,14 @@ foreach(FONT ${FONT_FILES}) ...@@ -61,6 +85,14 @@ foreach(FONT ${FONT_FILES})
) )
endforeach() endforeach()
foreach(IMAGE ${IMAGE_FILES})
add_custom_command(
TARGET advanced_wars PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${IMAGE} ${OUTPUT_ASSETS_DIR}
COMMENT "Kopiere Image: ${IMAGE} nach ${OUTPUT_ASSETS_DIR}"
)
endforeach()
set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH})
# Plattform-spezifische Konfiguration # Plattform-spezifische Konfiguration
...@@ -80,12 +112,14 @@ if(APPLE) ...@@ -80,12 +112,14 @@ if(APPLE)
${SDL2_PATH}/SDL2.framework/SDL2 ${SDL2_PATH}/SDL2.framework/SDL2
${SDL2_PATH}/SDL2_image.framework/SDL2_image ${SDL2_PATH}/SDL2_image.framework/SDL2_image
${SDL2_PATH}/SDL2_ttf.framework/SDL2_ttf ${SDL2_PATH}/SDL2_ttf.framework/SDL2_ttf
Boost::graph
box2d
) )
# Debug-Ausgaben
message(STATUS "Include Dir (SDL2): ${SDL2_PATH}/SDL2.framework/Headers") 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_image): ${SDL2_PATH}/SDL2_image.framework/Headers")
message(STATUS "Include Dir (SDL2_ttf): ${SDL2_PATH}/SDL2_ttf.framework/Headers") message(STATUS "Include Dir (SDL2_ttf): ${SDL2_PATH}/SDL2_ttf.framework/Headers")
message(STATUS "Boost Include Dirs: ${Boost_INCLUDE_DIRS}")
else() else()
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
find_package(SDL2_IMAGE REQUIRED) find_package(SDL2_IMAGE REQUIRED)
...@@ -104,9 +138,8 @@ else() ...@@ -104,9 +138,8 @@ else()
-lSDL2 -lSDL2
-lSDL2_image -lSDL2_image
-lSDL2_ttf -lSDL2_ttf
Boost::graph
box2d
m m
) )
endif() endif()
...@@ -49,6 +49,31 @@ ...@@ -49,6 +49,31 @@
4. Visual Studio erkennt automatisch das CMake-Projekt 4. Visual Studio erkennt automatisch das CMake-Projekt
5. Build über "Build All" ausführen 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 ## Build-Optionen
CMake kann mit verschiedenen Optionen konfiguriert werden: CMake kann mit verschiedenen Optionen konfiguriert werden:
......
# 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
src/assets/main_background.png

2.57 KiB

#include "building.hpp" #include "building.hpp"
#include "spritesheet.hpp" #include "spritesheet.hpp"
namespace advanced_wars { namespace advanced_wars
{
Building::Building(int x, int y, BuildingId id, BuildingFaction faction) Building::Building(int x, int y, BuildingId id, BuildingFaction faction)
: x(x), y(y), id(id), faction(faction){}; : x(x), y(y), id(id), faction(faction){};
void Building::render(Engine &engine, int scale) { void Building::render(Engine* engine, int scale)
Spritesheet *spritesheet = engine.get_spritesheet(); {
Spritesheet* spritesheet = engine->get_spritesheet();
SDL_Rect src; SDL_Rect src;
src.x = static_cast<int>(id) * spritesheet->get_building_width(); src.x = static_cast<int>(id) * spritesheet->get_building_width();
...@@ -22,8 +24,7 @@ void Building::render(Engine &engine, int scale) { ...@@ -22,8 +24,7 @@ void Building::render(Engine &engine, int scale) {
dst.h = spritesheet->get_building_height() * scale; dst.h = spritesheet->get_building_height() * scale;
SDL_RenderCopyEx( SDL_RenderCopyEx(
engine.renderer(), engine->renderer(), spritesheet->get_building_textures()[static_cast<int>(faction)], &src,
spritesheet->get_building_textures()[static_cast<int>(faction)], &src,
&dst, 0, NULL, SDL_FLIP_NONE); &dst, 0, NULL, SDL_FLIP_NONE);
} }
......
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
#include "engine.hpp" #include "engine.hpp"
#include "scene.hpp" #include "scene.hpp"
namespace advanced_wars { namespace advanced_wars
{
enum class BuildingFaction { enum class BuildingFaction
{
RED = 0, RED = 0,
BLUE = 1, BLUE = 1,
YELLOW = 2, YELLOW = 2,
...@@ -14,7 +16,8 @@ enum class BuildingFaction { ...@@ -14,7 +16,8 @@ enum class BuildingFaction {
NEUTRAL = 5, NEUTRAL = 5,
}; };
enum class BuildingId { enum class BuildingId
{
HEADQUARTER = 0, HEADQUARTER = 0,
CITY = 1, CITY = 1,
FACTORY = 2, FACTORY = 2,
...@@ -22,7 +25,8 @@ enum class BuildingId { ...@@ -22,7 +25,8 @@ enum class BuildingId {
SATELLITE = 4, SATELLITE = 4,
}; };
class Building { class Building
{
public: public:
Building(int x, int y, BuildingId id, BuildingFaction faction); Building(int x, int y, BuildingId id, BuildingFaction faction);
...@@ -31,7 +35,7 @@ public: ...@@ -31,7 +35,7 @@ public:
BuildingId id; BuildingId id;
BuildingFaction faction; BuildingFaction faction;
void render(Engine &engine, int scale); void render(Engine* engine, int scale);
}; };
} // namespace advanced_wars } // namespace advanced_wars
\ No newline at end of file
...@@ -2,28 +2,27 @@ ...@@ -2,28 +2,27 @@
#include "spritesheet.hpp" #include "spritesheet.hpp"
#include <vector> #include <vector>
namespace advanced_wars { namespace advanced_wars
{
Effect::Effect(int x, int y, EffectId id, bool repeat) Effect::Effect(int x, int y, EffectId id, bool repeat)
: x(x), y(y), id(id), repeat(repeat), start(0){ : x(x), y(y), id(id), repeat(repeat), start(0){
}; };
void Effect::render(Engine &engine, int scale) { void Effect::render(Engine* engine, int scale)
Spritesheet *spritesheet = engine.get_spritesheet(); {
if (start == 0) { Spritesheet* spritesheet = engine->get_spritesheet();
start = engine.get_stage(); if (start == 0)
{
start = engine->get_stage();
} }
int step = engine.get_stage() % int step =
spritesheet->get_effect_textures().at(static_cast<int>(id)).second; engine->get_stage() % spritesheet->get_effect_textures().at(static_cast<int>(id)).second;
if (engine.get_stage() - start <=
spritesheet->get_effect_textures().at(static_cast<int>(id)).second ||
repeat) {
SDL_Rect src; SDL_Rect src;
src.x = step * spritesheet->get_effect_width() + src.x = step * spritesheet->get_effect_width() + step * spritesheet->get_effect_height();
step * spritesheet->get_effect_height();
src.y = 0; src.y = 0;
src.w = spritesheet->get_effect_width(); src.w = spritesheet->get_effect_width();
src.h = spritesheet->get_effect_height(); src.h = spritesheet->get_effect_height();
...@@ -35,10 +34,16 @@ void Effect::render(Engine &engine, int scale) { ...@@ -35,10 +34,16 @@ void Effect::render(Engine &engine, int scale) {
dest.h = spritesheet->get_effect_height() * scale; dest.h = spritesheet->get_effect_height() * scale;
SDL_RenderCopyEx( SDL_RenderCopyEx(
engine.renderer(), engine->renderer(), spritesheet->get_effect_textures().at(static_cast<int>(id)).first, &src,
spritesheet->get_effect_textures().at(static_cast<int>(id)).first, &src,
&dest, 0, NULL, SDL_FLIP_NONE); &dest, 0, NULL, SDL_FLIP_NONE);
} }
bool Effect::is_finished(Engine* engine)
{
return !(
engine->get_stage() - start <=
engine->get_spritesheet()->get_effect_textures().at(static_cast<int>(id)).second ||
repeat);
} }
} // namespace advanced_wars } // namespace advanced_wars
\ No newline at end of file
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
#include "engine.hpp" #include "engine.hpp"
namespace advanced_wars { namespace advanced_wars
{
enum class EffectId { enum class EffectId
{
LAND_EXPLOSION = 0, LAND_EXPLOSION = 0,
AIR_EXPLOSION = 1, AIR_EXPLOSION = 1,
NAVAL_EXPLOSION = 2, NAVAL_EXPLOSION = 2,
...@@ -12,11 +14,14 @@ enum class EffectId { ...@@ -12,11 +14,14 @@ enum class EffectId {
SUBMARINE_APPEAR = 4 SUBMARINE_APPEAR = 4
}; };
class Effect { class Effect
{
public: public:
Effect(int x, int y, EffectId id, bool repeat); Effect(int x, int y, EffectId id, bool repeat);
void render(Engine &engine, int scale); void render(Engine* engine, int scale);
bool is_finished(Engine* engine);
int x; int x;
int y; int y;
......
#include "engine.hpp" #include "engine.hpp"
#include "SDL_events.h"
#include "SDL_timer.h"
#include "scene.hpp" #include "scene.hpp"
#include "spritesheet.hpp" #include "spritesheet.hpp"
#include "window.hpp" #include "window.hpp"
#include <SDL.h> #include <SDL.h>
#include <SDL_image.h> #include <SDL_image.h>
#include <SDL_render.h> #include <SDL_render.h>
#include <deque>
#include <memory>
#include <optional>
#include <stdexcept> #include <stdexcept>
#include <vector>
namespace advanced_wars { namespace advanced_wars
{
Engine::Engine(Window &window) : window(window), quit(false) { Engine::Engine(Window& window) : window(window), quit(false)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) { this->sdl_renderer = SDL_CreateRenderer(
throw std::runtime_error("SDL could not initialize: " + this->window.sdl_window(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
std::string(SDL_GetError()));
if (sdl_renderer == nullptr)
{
throw std::runtime_error("SDL could not generate renderer: " + std::string(SDL_GetError()));
}
} }
int imgFlags = IMG_INIT_PNG; std::deque<SDL_Event>& Engine::events()
if (!(IMG_Init(imgFlags) & imgFlags)) { {
throw std::runtime_error( return this->_events;
"SDL_image could not initialize! SDL_image Error: " +
std::string(IMG_GetError()));
} }
this->sdl_renderer = void Engine::push_scene(std::shared_ptr<Scene> scene)
SDL_CreateRenderer(this->window.sdl_window(), -1, {
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); this->scenes.push_back(scene);
}
if (sdl_renderer == nullptr) { void Engine::return_to_menu()
throw std::runtime_error("SDL could not generate renderer: " + {
std::string(SDL_GetError())); // TODO: discuss if we outsource this to a separate function
// clear everything except the first scene
while (this->scenes.size() > 1)
{
this->scenes.pop_back();
}
} }
std::optional<std::shared_ptr<Scene>> Engine::pop_scene()
{
if (this->scenes.empty())
{
return std::nullopt;
} }
std::shared_ptr<Scene> tmp = scenes.back();
this->scenes.pop_back();
void Engine::set_scene(Scene &scene) { this->scene = &scene; } return tmp;
}
void Engine::set_spritesheet(Spritesheet &spritesheet) { void Engine::set_spritesheet(Spritesheet& spritesheet)
{
this->spritesheet = &spritesheet; this->spritesheet = &spritesheet;
} }
Spritesheet *Engine::get_spritesheet() { return spritesheet.value(); } void Engine::pump()
{
void Engine::pump() {
SDL_Event e; SDL_Event e;
while (SDL_PollEvent(&e)) { while (SDL_PollEvent(&e))
if (e.type == SDL_QUIT) { {
if (e.type == SDL_QUIT)
{
this->quit = true; this->quit = true;
} else { }
this->events.push_back(e); else
{
this->_events.push_back(e);
} }
} }
} }
bool Engine::exited() { return this->quit; } void Engine::exit()
{
int Engine::get_stage() { return this->stage; } this->quit = true;
}
void Engine::render() { bool Engine::exited()
if (SDL_RenderClear(this->sdl_renderer) != 0) { {
throw std::runtime_error("Could not clear renderer: " + return this->quit;
std::string(SDL_GetError()));
} }
if (!scene.has_value()) { void Engine::render()
return; {
if (SDL_RenderClear(this->sdl_renderer) != 0)
{
throw std::runtime_error("Could not clear renderer: " + std::string(SDL_GetError()));
} }
stage = SDL_GetTicks() / 300; std::shared_ptr<Scene> currentScene = scenes.back();
this->scene.value()->render(*this, this->events); currentScene->render(this);
SDL_RenderPresent(this->sdl_renderer); SDL_RenderPresent(this->sdl_renderer);
} }
SDL_Renderer *Engine::renderer() { return this->sdl_renderer; } int Engine::get_stage()
{
return SDL_GetTicks() / 300;
}
Spritesheet* Engine::get_spritesheet()
{
return spritesheet.value();
}
SDL_Renderer* Engine::renderer()
{
return this->sdl_renderer;
}
Engine::~Engine() { Engine::~Engine()
{
SDL_DestroyRenderer(sdl_renderer); SDL_DestroyRenderer(sdl_renderer);
IMG_Quit(); IMG_Quit();
SDL_Quit(); SDL_Quit();
......
#pragma once #pragma once
#include "SDL_events.h"
#include "scene.hpp" #include "scene.hpp"
#include "spritesheet.hpp" #include "spritesheet.hpp"
#include "window.hpp" #include "window.hpp"
#include <SDL.h> #include <SDL.h>
#include <SDL_render.h> #include <SDL_render.h>
#include <deque>
#include <memory>
#include <optional> #include <optional>
#include <vector>
namespace advanced_wars { namespace advanced_wars
{
// Forward declaration
class Scene;
/** /**
* @brief The main window of the game * @brief The main window of the game
*/ */
class Engine { class Engine
{
public: public:
Engine(Window& window); Engine(Window& window);
...@@ -22,9 +29,17 @@ public: ...@@ -22,9 +29,17 @@ public:
bool exited(); bool exited();
void exit();
void pump(); void pump();
void set_scene(Scene &scene); void push_scene(std::shared_ptr<Scene> scene);
std::optional<std::shared_ptr<Scene>> pop_scene();
void return_to_menu();
std::deque<SDL_Event>& events();
void set_spritesheet(Spritesheet& spritesheet); void set_spritesheet(Spritesheet& spritesheet);
...@@ -41,9 +56,9 @@ public: ...@@ -41,9 +56,9 @@ public:
private: private:
Window& window; Window& window;
SDL_Renderer* sdl_renderer; SDL_Renderer* sdl_renderer;
std::optional<Scene *> scene; std::vector<std::shared_ptr<Scene>> scenes;
std::optional<Spritesheet*> spritesheet; std::optional<Spritesheet*> spritesheet;
std::vector<SDL_Event> events; std::deque<SDL_Event> _events;
bool quit; bool quit;
int stage; int stage;
}; };
......
#include "level.hpp" #include "level.hpp"
#include "SDL_error.h"
#include "building.hpp" #include "building.hpp"
#include "effect.hpp" #include "effect.hpp"
#include "engine.hpp" #include "engine.hpp"
#include "spritesheet.hpp" #include "spritesheet.hpp"
#include "ui/contextmenu.hpp"
#include "ui/pausemenu.hpp"
#include "unit.hpp" #include "unit.hpp"
#include <SDL.h> #include <SDL.h>
#include <algorithm>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <algorithm>
namespace advanced_wars namespace advanced_wars
{ {
Level::Level(std::string name, int width, int height, std::vector<Tile> tiles, Level::Level(
std::vector<Building> buildings, std::vector<Unit> units, std::string name, int width, int height, std::vector<Tile> tiles,
std::vector<Effect> effects) std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect> effects)
: name(name), width(width), height(height), tiles(tiles), : name(name), width(width), height(height), tiles(tiles), context_menu(ContextMenu()),
buildings(buildings), units(units), effects(effects) context_menu_active(false), id(0)
{
context_menu.setOptions({"Move", "Info", "Wait"});
for (Building building : buildings)
{ {
this->add_building(building);
}
for (Unit unit : units)
{
this->add_unit(unit);
}
for (Effect effect : effects)
{
this->add_effect(effect);
}
if ((size_t)(width * height) != tiles.size()) if ((size_t)(width * height) != tiles.size())
{ {
...@@ -59,14 +77,14 @@ namespace advanced_wars ...@@ -59,14 +77,14 @@ namespace advanced_wars
{ {
// std::cout << "tileX:" << tileX << "tileX:" << tileY << std::endl; // std::cout << "tileX:" << tileX << "tileX:" << tileY << std::endl;
for (auto &unit : units) for (auto& [id, unit] : units)
{ {
if (unit.x == tileX && unit.y == tileY) if (unit.x == tileX && unit.y == tileY)
{ {
// std::cout << "unitX:" << unit.x << "unitY:" << unit.y << std::endl; // std::cout << "unitX:" << unit.x << "unitY:" << unit.y << std::endl;
selectedUnit = &unit; selectedUnit = id;
return true; return true;
} }
} }
...@@ -78,14 +96,14 @@ namespace advanced_wars ...@@ -78,14 +96,14 @@ namespace advanced_wars
{ {
// std::cout << "tileX:" << tileX << "tileX:" << tileY << std::endl; // std::cout << "tileX:" << tileX << "tileX:" << tileY << std::endl;
for (auto &unit : units) for (auto& [id, unit] : units)
{ {
if (unit.x == tileX && unit.y == tileY) if (unit.x == tileX && unit.y == tileY)
{ {
// std::cout << "unitX:" << unit.x << "unitY:" << unit.y << std::endl; // std::cout << "unitX:" << unit.x << "unitY:" << unit.y << std::endl;
targetedUnit = &unit; targetedUnit = id;
return true; return true;
} }
} }
...@@ -96,13 +114,13 @@ namespace advanced_wars ...@@ -96,13 +114,13 @@ namespace advanced_wars
bool Level::selectBuilding(int tileX, int tileY) bool Level::selectBuilding(int tileX, int tileY)
{ {
for (auto &building : buildings) for (auto& [id, building] : buildings)
{ {
if (building.x == tileX && building.y == tileY) if (building.x == tileX && building.y == tileY)
{ {
// std::cout << "X:" << unit.x << "Y:" << unit.y << std::endl; // std::cout << "X:" << unit.x << "Y:" << unit.y << std::endl;
selectedBuilding = &building; selectedBuilding = id;
return true; return true;
} }
} }
...@@ -125,12 +143,12 @@ namespace advanced_wars ...@@ -125,12 +143,12 @@ namespace advanced_wars
if (click_check_left(tileX, tileY)) if (click_check_left(tileX, tileY))
{ {
if (selectedUnit) if (selectedUnit > -1)
{ {
selectedUnit->on_left_click(event, units); units.at(selectedUnit).on_left_click(event);
} }
if (selectedBuilding) if (selectedBuilding > -1)
{ {
// building stuff // building stuff
} }
...@@ -139,14 +157,14 @@ namespace advanced_wars ...@@ -139,14 +157,14 @@ namespace advanced_wars
{ {
std::cout << "Neither building nor unit clicked!" << std::endl; std::cout << "Neither building nor unit clicked!" << std::endl;
selectedUnit = nullptr; selectedUnit = -1;
selectedBuilding = nullptr; selectedBuilding = -1;
} }
} }
else if (event.button.button == SDL_BUTTON_RIGHT) else if (event.button.button == SDL_BUTTON_RIGHT)
{ {
if (selectedUnit) if (selectedUnit > -1)
{ {
int tileX = event.button.x / (16 * RENDERING_SCALE); int tileX = event.button.x / (16 * RENDERING_SCALE);
...@@ -155,18 +173,17 @@ namespace advanced_wars ...@@ -155,18 +173,17 @@ namespace advanced_wars
if (click_check_right(tileX, tileY)) if (click_check_right(tileX, tileY))
{ {
selectedUnit->attack(targetedUnit); units.at(selectedUnit).attack(&(units.at(targetedUnit)));
units.erase( if (units.at(selectedUnit).health <= 0)
std::remove_if(units.begin(), units.end(), {
[](const Unit &unit) remove_unit(selectedUnit);
{ return unit.health <= 0; }), }
units.end());
} }
else else
{ {
selectedUnit->update_position(tileX, tileY); units.at(selectedUnit).update_position(tileX, tileY);
} }
} }
else else
...@@ -178,16 +195,15 @@ namespace advanced_wars ...@@ -178,16 +195,15 @@ namespace advanced_wars
} }
} }
void Level::render(Engine &engine, std::vector<SDL_Event> &events) void Level::render(Engine* engine)
{ {
// Iterate over all events // Iterate over all events
while (!events.empty()) while (!engine->events().empty())
{ {
// events.erase(events.begin()); // handleEvent(engine, engine->events().at(0));
handleEvent(*engine, engine->events().at(0));
handleEvent(engine, events.at(0)); engine->events().pop_front();
events.erase(events.begin());
} }
// Tiles // Tiles
...@@ -197,29 +213,130 @@ namespace advanced_wars ...@@ -197,29 +213,130 @@ namespace advanced_wars
} }
// Buildings // Buildings
for (Building &building : buildings) for (auto& [id, building] : buildings)
{ {
building.render(engine, RENDERING_SCALE); building.render(engine, RENDERING_SCALE);
} }
// Units // Units
for (Unit &unit : units) for (auto& [id, unit] : units)
{ {
unit.render(engine, RENDERING_SCALE); unit.render(engine, RENDERING_SCALE);
} }
// Effects // Effects
for (Effect &effect : effects) std::vector<int> effects_to_remove;
for (auto& [id, effect] : effects)
{
if (effect.is_finished(engine))
{
effects_to_remove.push_back(id);
}
else
{ {
effect.render(engine, RENDERING_SCALE); effect.render(engine, RENDERING_SCALE);
} }
}
// Set background color for renderer // Remove finished effects after iteration
if (SDL_SetRenderDrawColor(engine.renderer(), 255, 0, 0, 0)) for (int id : effects_to_remove)
{ {
std::cout << "Could not set render draw color: " << SDL_GetError() this->remove_effect(id);
<< std::endl;
} }
if (context_menu_active)
{
context_menu.render(engine);
}
}
void Level::handleEvent(Engine* engine, SDL_Event& event)
{
// Handle events for the level
if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.sym == SDLK_ESCAPE)
{
// Pause the game
std::cout << "Pausing game..." << std::endl;
SDL_Texture* currentTexture = SDL_CreateTexture(
engine->renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 800, 600);
PauseMenu pauseMenu(0, currentTexture);
engine->push_scene(std::make_shared<PauseMenu>(pauseMenu));
}
if (context_menu_active)
{
if (event.key.keysym.sym == SDLK_DOWN)
{
context_menu.handleEvent(event);
}
if (event.key.keysym.sym == SDLK_UP)
{
context_menu.handleEvent(event);
}
if (event.key.keysym.sym == SDLK_RETURN)
{
if (context_menu.getSelectedOption() == "Wait")
{
context_menu_active = false;
}
}
}
}
if (event.type == SDL_MOUSEBUTTONDOWN)
{
context_menu.update(event.button.x, event.button.y);
context_menu_active = true;
}
}
int Level::add_building(Building building)
{
buildings.insert({id, building});
id += 1;
return id - 1;
}
Building Level::remove_building(int id)
{
Building value = buildings.at(id);
buildings.erase(id);
return value;
}
int Level::add_unit(Unit unit)
{
units.insert({id, unit});
id += 1;
return id - 1;
}
Unit Level::remove_unit(int id)
{
Unit value = units.at(id);
units.erase(id);
return value;
}
int Level::add_effect(Effect effect)
{
effects.insert({id, effect});
id += 1;
return id - 1;
}
Effect Level::remove_effect(int id)
{
Effect value = effects.at(id);
effects.erase(id);
return value;
} }
} // namespace advanced_wars } // namespace advanced_wars
\ No newline at end of file
...@@ -5,23 +5,41 @@ ...@@ -5,23 +5,41 @@
#include "engine.hpp" #include "engine.hpp"
#include "scene.hpp" #include "scene.hpp"
#include "tile.hpp" #include "tile.hpp"
#include "ui/contextmenu.hpp"
#include "unit.hpp" #include "unit.hpp"
#include <SDL.h> #include <SDL.h>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
namespace advanced_wars { namespace advanced_wars
{
/** /**
* @brief The main window of the game * @brief The main window of the game
*/ */
class Level : public Scene { class Level : public Scene
{
public: public:
Level(std::string name, int width, int height, std::vector<Tile> tiles, Level(
std::vector<Building> buildings, std::vector<Unit> units, std::string name, int width, int height, std::vector<Tile> tiles,
std::vector<Effect>); std::vector<Building> buildings, std::vector<Unit> units, std::vector<Effect>);
void render(Engine &engine, std::vector<SDL_Event> &events); void render(Engine* engine);
void handleEvent(Engine* engine, SDL_Event& event);
int add_building(Building building);
Building remove_building(int id);
int add_unit(Unit unit);
Unit remove_unit(int id);
int add_effect(Effect effect);
Effect remove_effect(int id);
void handleEvent(Engine& engine, SDL_Event& event); void handleEvent(Engine& engine, SDL_Event& event);
...@@ -29,19 +47,25 @@ private: ...@@ -29,19 +47,25 @@ private:
std::string name; std::string name;
int width; int width;
int height; int height;
std::vector<Tile> tiles; std::vector<Tile> tiles;
std::vector<Building> buildings; std::unordered_map<int, Building> buildings;
std::vector<Unit> units; std::unordered_map<int, Unit> units;
std::vector<Effect> effects; std::unordered_map<int, Effect> effects;
Unit* selectedUnit; int selectedUnit;
Unit* targetedUnit; int targetedUnit;
Building* selectedBuilding; int selectedBuilding;
bool selectUnit(int tileX, int tileY); bool selectUnit(int tileX, int tileY);
bool target_unit(int tileX, int tileY); bool target_unit(int tileX, int tileY);
bool selectBuilding(int tileX, int tileY); bool selectBuilding(int tileX, int tileY);
bool click_check_left(int mouseX, int mouseY); bool click_check_left(int mouseX, int mouseY);
bool click_check_right(int mouseX, int mouseY); bool click_check_right(int mouseX, int mouseY);
ContextMenu context_menu;
bool context_menu_active;
int id;
}; };
} // namespace advanced_wars } // namespace advanced_wars
#include "building.hpp"
#include "effect.hpp"
#include "engine.hpp" #include "engine.hpp"
#include "level.hpp"
#include "spritesheet.hpp" #include "spritesheet.hpp"
#include "tile.hpp" #include "ui/contextmenu.hpp"
#include "unit.hpp" #include "ui/menu.hpp"
#include "window.hpp" #include "window.hpp"
#include <cstddef> #include <SDL2/SDL.h>
#include <SDL_image.h>
#include <memory>
#include <stdexcept>
#include <vector> #include <vector>
using namespace advanced_wars; using namespace advanced_wars;
int main() { int main()
{
Window window("Advanced Wars", 960, 960); if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
Engine engine(window); throw std::runtime_error("SDL could not initialize: " + std::string(SDL_GetError()));
// Construct a level
std::vector<Tile> tiles;
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++) {
// Vertical
tiles.at(n * 20) = Tile(TileId::WATER, 0, n);
tiles.at(n * 20 + 19) = Tile(TileId::WATER, 19, n);
// Horizontal
tiles.at(n) = Tile(TileId::WATER, n, 0);
tiles.at(19 * 20 + n) = Tile(TileId::WATER, n, 19);
}
// Make the edges cliffs
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);
// Horizontal
tiles.at(20 + n) = Tile(TileId::CLIFF_BOTTOM, n, 1);
tiles.at(18 * 20 + n) = Tile(TileId::CLIFF_TOP, n, 18);
} }
// Fix the corners int imgFlags = IMG_INIT_PNG;
tiles.at(20 + 1) = Tile(TileId::CLIFF_CORNER_TOP_LEFT, 1, 1); if (!(IMG_Init(imgFlags) & imgFlags))
tiles.at(20 + 18) = Tile(TileId::CLIFF_CORNER_TOP_RIGHT, 18, 1); {
tiles.at(18 * 20 + 1) = Tile(TileId::CLIFF_CORNER_BOTTOM_LEFT, 1, 18); throw std::runtime_error(
tiles.at(18 * 20 + 18) = Tile(TileId::CLIFF_CORNER_BOTTOM_RIGHT, 18, 18); "SDL_image could not initialize! SDL_image Error: " + std::string(IMG_GetError()));
// Buildings
std::vector<Building> buildings;
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);
buildings.push_back(Building(3 + x, 3 + 2 * y, id, faction));
}
} }
// Units Window window("Advanced Wars", 960, 960);
std::vector<Unit> units;
for (int y = 0; y < 19; y++) { Engine engine(window);
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)));
}
}
std::vector<Effect> effects({Effect(3, 15, EffectId::LAND_EXPLOSION, true), Spritesheet spritesheet("/media/data/rust/sprite-extractor/spritesheet.h5", engine);
Effect(5, 15, EffectId::AIR_EXPLOSION, true),
Effect(5, 18, EffectId::NAVAL_EXPLOSION, true)});
Level level("Osnabrück", 20, 20, tiles, buildings, units, effects); engine.set_spritesheet(spritesheet);
engine.set_scene(level); std::shared_ptr<Menu> menu = std::make_shared<Menu>(0);
std::shared_ptr<ContextMenu> context_menu = std::make_shared<ContextMenu>();
context_menu->setOptions({"Move", "Info", "Wait"});
Spritesheet spritesheet("./spritesheet.h5", std::string basePath = SDL_GetBasePath();
engine); std::string relativePath = "assets/main_background.png";
std::string fullPath = basePath + relativePath;
menu->loadBackground(engine.renderer(), fullPath.c_str());
engine.set_spritesheet(spritesheet); engine.push_scene(menu);
while (!engine.exited()) { while (!engine.exited())
{
engine.pump(); engine.pump();
engine.render(); engine.render();
} }
......
#pragma once #pragma once
#include "engine.hpp"
#include <SDL.h> #include <SDL.h>
#include <vector>
namespace advanced_wars { namespace advanced_wars
{
// Forward declaration // Forward declaration
class Engine; class Engine;
class Scene { class Scene
{
public: public:
virtual void render(Engine &engine, std::vector<SDL_Event> &events) = 0; virtual void render(Engine* engine) = 0;
}; };
} // namespace advanced_wars } // namespace advanced_wars
/**
* Spritesheet.hpp
*
* @date 30.1.2025
* @author Frederik Keens
* @author David Maul
*/
#include "spritesheet.hpp" #include "spritesheet.hpp"
#include "SDL_pixels.h"
#include "engine.hpp" #include "engine.hpp"
#include "highfive/H5File.hpp" #include "highfive/H5File.hpp"
#include <SDL_image.h> #include <SDL_image.h>
...@@ -10,14 +17,17 @@ ...@@ -10,14 +17,17 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace advanced_wars { namespace advanced_wars
{
Spritesheet::Spritesheet(std::string path, Engine &engine) { Spritesheet::Spritesheet(std::string path, Engine& engine)
{
HighFive::File file(path, HighFive::File::ReadOnly); HighFive::File file(path, HighFive::File::ReadOnly);
// Tiles // Tiles
std::vector<std::string> tiles({"plain", std::vector<std::string> tiles(
{"plain",
"water", "water",
"forest", "forest",
"mountain", "mountain",
...@@ -48,7 +58,9 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -48,7 +58,9 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
"cliff_inverse_corner_bottom_left", "cliff_inverse_corner_bottom_left",
"cliff_inverse_corner_bottom_right"}); "cliff_inverse_corner_bottom_right"});
for (size_t tile_idx = 0; tile_idx < tiles.size(); tile_idx++) { // every sub data set of tiles
for (size_t tile_idx = 0; tile_idx < tiles.size(); tile_idx++)
{
HighFive::DataSet units_ds = file.getDataSet("tiles/" + tiles[tile_idx]); HighFive::DataSet units_ds = file.getDataSet("tiles/" + tiles[tile_idx]);
std::vector<std::vector<std::vector<uint32_t>>> tile_frames; std::vector<std::vector<std::vector<uint32_t>>> tile_frames;
...@@ -56,9 +68,13 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -56,9 +68,13 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
std::vector<uint32_t> tile_buffer(16 * 16 * tile_frames.size(), 0); std::vector<uint32_t> tile_buffer(16 * 16 * tile_frames.size(), 0);
for (size_t n = 0; n < tile_frames.size(); n++) { // every animation frame
for (size_t y = 0; y < 16; y++) { for (size_t n = 0; n < tile_frames.size(); n++)
for (size_t x = 0; x < 16; x++) { {
for (size_t y = 0; y < 16; y++)
{
for (size_t x = 0; x < 16; x++)
{
size_t index = (y * tile_frames.size() * 16) + (n * 16 + x); size_t index = (y * tile_frames.size() * 16) + (n * 16 + x);
tile_buffer.at(index) = tile_frames.at(n).at(16 - y - 1).at(x); tile_buffer.at(index) = tile_frames.at(n).at(16 - y - 1).at(x);
...@@ -72,21 +88,20 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -72,21 +88,20 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr) { if (tmp == nullptr)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Units: " + "Fehler beim Erstellen der Textur für die Units: " + std::string(SDL_GetError()));
std::string(SDL_GetError()));
} }
if (SDL_UpdateTexture(tmp, NULL, tile_buffer.data(), if (SDL_UpdateTexture(
tile_frames.size() * 16 * sizeof(int32_t)) != 0) { tmp, NULL, tile_buffer.data(), tile_frames.size() * 16 * sizeof(int32_t)) != 0)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim updaten der Textur für die Units: " + "Fehler beim updaten der Textur für die Units: " + std::string(SDL_GetError()));
std::string(SDL_GetError()));
} }
tile_textures.push_back( tile_textures.push_back(std::pair<SDL_Texture*, int>(tmp, tile_frames.size()));
std::pair<SDL_Texture *, int>(tmp, tile_frames.size()));
} }
this->tile_width = 16; this->tile_width = 16;
...@@ -96,7 +111,9 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -96,7 +111,9 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
std::vector<std::string> building_factions( std::vector<std::string> building_factions(
{"red", "blue", "yellow", "green", "purple", "neutral"}); {"red", "blue", "yellow", "green", "purple", "neutral"});
for (std::string faction : building_factions) { // every sub data set of buildings
for (std::string faction : building_factions)
{
HighFive::DataSet buildings_ds = file.getDataSet("buildings/" + faction); HighFive::DataSet buildings_ds = file.getDataSet("buildings/" + faction);
std::vector<std::vector<std::vector<uint32_t>>> buildings_frames; std::vector<std::vector<std::vector<uint32_t>>> buildings_frames;
...@@ -105,13 +122,16 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -105,13 +122,16 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
std::vector<uint32_t> building_buffer(32 * 16 * buildings_frames.size(), 0); std::vector<uint32_t> building_buffer(32 * 16 * buildings_frames.size(), 0);
for (size_t n = 0; n < buildings_frames.size(); n++) { // every type of building
for (size_t y = 0; y < 32; y++) { for (size_t n = 0; n < buildings_frames.size(); n++)
for (size_t x = 0; x < 16; x++) { {
for (size_t y = 0; y < 32; y++)
{
for (size_t x = 0; x < 16; x++)
{
size_t index = (y * buildings_frames.size() * 16) + (n * 16 + x); size_t index = (y * buildings_frames.size() * 16) + (n * 16 + x);
building_buffer.at(index) = building_buffer.at(index) = buildings_frames.at(n).at(32 - y - 1).at(x);
buildings_frames.at(n).at(32 - y - 1).at(x);
} }
} }
} }
...@@ -122,18 +142,19 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -122,18 +142,19 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr) { if (tmp == nullptr)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Buildings: " + "Fehler beim Erstellen der Textur für die Buildings: " +
std::string(SDL_GetError())); std::string(SDL_GetError()));
} }
if (SDL_UpdateTexture(tmp, NULL, building_buffer.data(), if (SDL_UpdateTexture(
buildings_frames.size() * 16 * sizeof(int32_t)) != tmp, NULL, building_buffer.data(),
0) { buildings_frames.size() * 16 * sizeof(int32_t)) != 0)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim updaten der Textur für die Buildings: " + "Fehler beim updaten der Textur für die Buildings: " + std::string(SDL_GetError()));
std::string(SDL_GetError()));
} }
this->building_textures.push_back(tmp); this->building_textures.push_back(tmp);
...@@ -143,35 +164,35 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -143,35 +164,35 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
this->building_height = 32; this->building_height = 32;
// Units // Units
std::vector<std::string> unit_factions( std::vector<std::string> unit_factions({"red", "blue", "green", "yellow", "purple"});
{"red", "blue", "green", "yellow", "purple"});
std::vector<std::string> units( std::vector<std::string> units(
{"infantery", "mechanized_infantery", "recon", "medium_tank", {"infantery", "mechanized_infantery", "recon", "medium_tank", "heavy_tank", "neo_tank",
"heavy_tank", "neo_tank", "apc", "anti_air_tank", "artillery", "apc", "anti_air_tank", "artillery", "rocket_artillery", "anti_air_missile_launcher",
"rocket_artillery", "anti_air_missile_launcher", "fighter", "bomber", "fighter", "bomber", "battle_helicopter", "transport_helicopter", "battleship", "cruiser",
"battle_helicopter", "transport_helicopter", "battleship", "cruiser",
"lander", "submarine"}); "lander", "submarine"});
std::vector<std::string> unit_states({"idle", "unavailable"}); std::vector<std::string> unit_states({"idle", "unavailable"});
std::vector<std::string> unit_movement_states( std::vector<std::string> unit_movement_states({"left", "right", "down", "up"});
{"left", "right", "down", "up"});
for (size_t faction_idx = 0; faction_idx < unit_factions.size(); // every factions sub data set
faction_idx++) { for (size_t faction_idx = 0; faction_idx < unit_factions.size(); faction_idx++)
{
std::string faction = unit_factions.at(faction_idx); std::string faction = unit_factions.at(faction_idx);
// Create entry for units for in a faction // Create entry for units for in a faction
unit_textures.push_back( unit_textures.push_back(std::vector<std::vector<std::pair<SDL_Texture*, int>>>());
std::vector<std::vector<std::pair<SDL_Texture *, int>>>());
for (size_t unit_idx = 0; unit_idx < units.size(); unit_idx++) { // every unit sub data set
for (size_t unit_idx = 0; unit_idx < units.size(); unit_idx++)
{
std::string unit = units.at(unit_idx); std::string unit = units.at(unit_idx);
// Create entry for states for a unit // Create entry for states for a unit
unit_textures.at(faction_idx) unit_textures.at(faction_idx).push_back(std::vector<std::pair<SDL_Texture*, int>>());
.push_back(std::vector<std::pair<SDL_Texture *, int>>());
for (size_t state_idx = 0; state_idx < unit_states.size(); state_idx++) { // every state sub data set
for (size_t state_idx = 0; state_idx < unit_states.size(); state_idx++)
{
std::string unit_state = unit_states.at(state_idx); std::string unit_state = unit_states.at(state_idx);
HighFive::DataSet units_ds = HighFive::DataSet units_ds =
...@@ -182,9 +203,12 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -182,9 +203,12 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
std::vector<uint32_t> unit_buffer(16 * 16 * unit_frames.size(), 0); std::vector<uint32_t> unit_buffer(16 * 16 * unit_frames.size(), 0);
for (size_t n = 0; n < unit_frames.size(); n++) { for (size_t n = 0; n < unit_frames.size(); n++)
for (size_t y = 0; y < 16; y++) { {
for (size_t x = 0; x < 16; x++) { for (size_t y = 0; y < 16; y++)
{
for (size_t x = 0; x < 16; x++)
{
size_t index = (y * unit_frames.size() * 16) + (n * 16 + x); size_t index = (y * unit_frames.size() * 16) + (n * 16 + x);
unit_buffer.at(index) = unit_frames.at(n).at(16 - y - 1).at(x); unit_buffer.at(index) = unit_frames.at(n).at(16 - y - 1).at(x);
...@@ -193,19 +217,22 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -193,19 +217,22 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
} }
SDL_Texture* tmp = SDL_CreateTexture( SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC,
SDL_TEXTUREACCESS_STATIC, unit_frames.size() * 16, 16); unit_frames.size() * 16, 16);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr) { if (tmp == nullptr)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Units: " + "Fehler beim Erstellen der Textur für die Units: " +
std::string(SDL_GetError())); std::string(SDL_GetError()));
} }
if (SDL_UpdateTexture(tmp, NULL, unit_buffer.data(), if (SDL_UpdateTexture(
unit_frames.size() * 16 * sizeof(int32_t)) != 0) { tmp, NULL, unit_buffer.data(), unit_frames.size() * 16 * sizeof(int32_t)) !=
0)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim updaten der Textur für die Units: " + "Fehler beim updaten der Textur für die Units: " +
std::string(SDL_GetError())); std::string(SDL_GetError()));
...@@ -216,11 +243,11 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -216,11 +243,11 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
.push_back(std::pair<SDL_Texture*, int>(tmp, unit_frames.size())); .push_back(std::pair<SDL_Texture*, int>(tmp, unit_frames.size()));
} }
for (size_t movement_state_idx = 0; // every movement state sub data set
movement_state_idx < unit_movement_states.size(); for (size_t movement_state_idx = 0; movement_state_idx < unit_movement_states.size();
movement_state_idx++) { movement_state_idx++)
std::string movement_state = {
unit_movement_states.at(movement_state_idx); std::string movement_state = unit_movement_states.at(movement_state_idx);
HighFive::DataSet units_ds = file.getDataSet( HighFive::DataSet units_ds = file.getDataSet(
"units/" + faction + "/" + unit + "/movement/" + movement_state); "units/" + faction + "/" + unit + "/movement/" + movement_state);
...@@ -230,9 +257,12 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -230,9 +257,12 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
std::vector<uint32_t> unit_buffer(24 * 24 * unit_frames.size(), 0); std::vector<uint32_t> unit_buffer(24 * 24 * unit_frames.size(), 0);
for (size_t n = 0; n < unit_frames.size(); n++) { for (size_t n = 0; n < unit_frames.size(); n++)
for (size_t y = 0; y < 24; y++) { {
for (size_t x = 0; x < 24; x++) { for (size_t y = 0; y < 24; y++)
{
for (size_t x = 0; x < 24; x++)
{
size_t index = (y * unit_frames.size() * 24) + (n * 24 + x); size_t index = (y * unit_frames.size() * 24) + (n * 24 + x);
unit_buffer.at(index) = unit_frames.at(n).at(24 - y - 1).at(x); unit_buffer.at(index) = unit_frames.at(n).at(24 - y - 1).at(x);
...@@ -241,19 +271,22 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -241,19 +271,22 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
} }
SDL_Texture* tmp = SDL_CreateTexture( SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC,
SDL_TEXTUREACCESS_STATIC, unit_frames.size() * 24, 24); unit_frames.size() * 24, 24);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr) { if (tmp == nullptr)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Units: " + "Fehler beim Erstellen der Textur für die Units: " +
std::string(SDL_GetError())); std::string(SDL_GetError()));
} }
if (SDL_UpdateTexture(tmp, NULL, unit_buffer.data(), if (SDL_UpdateTexture(
unit_frames.size() * 24 * sizeof(int32_t)) != 0) { tmp, NULL, unit_buffer.data(), unit_frames.size() * 24 * sizeof(int32_t)) !=
0)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim updaten der Textur für die Units: " + "Fehler beim updaten der Textur für die Units: " +
std::string(SDL_GetError())); std::string(SDL_GetError()));
...@@ -272,22 +305,27 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -272,22 +305,27 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
this->unit_moving_height = 24; this->unit_moving_height = 24;
// Effects // Effects
std::vector<std::string> effects({"land_explosion", "air_explosion", std::vector<std::string> effects(
"naval_explosion", "submarine_hide", {"land_explosion", "air_explosion", "naval_explosion", "submarine_hide",
"submarine_appear"}); "submarine_appear"});
for (size_t effect_idx = 0; effect_idx < effects.size(); effect_idx++) { // Every effect sub data set
HighFive::DataSet effect_ds = for (size_t effect_idx = 0; effect_idx < effects.size(); effect_idx++)
file.getDataSet("effects/" + effects[effect_idx]); {
HighFive::DataSet effect_ds = file.getDataSet("effects/" + effects[effect_idx]);
std::vector<std::vector<std::vector<uint32_t>>> effect_frames; std::vector<std::vector<std::vector<uint32_t>>> effect_frames;
effect_ds.read(effect_frames); effect_ds.read(effect_frames);
std::vector<uint32_t> effect_buffer(32 * 32 * effect_frames.size(), 0); std::vector<uint32_t> effect_buffer(32 * 32 * effect_frames.size(), 0);
for (size_t n = 0; n < effect_frames.size(); n++) { // every animation frame
for (size_t y = 0; y < 32; y++) { for (size_t n = 0; n < effect_frames.size(); n++)
for (size_t x = 0; x < 32; x++) { {
for (size_t y = 0; y < 32; y++)
{
for (size_t x = 0; x < 32; x++)
{
size_t index = (y * effect_frames.size() * 32) + (n * 32 + x); size_t index = (y * effect_frames.size() * 32) + (n * 32 + x);
effect_buffer.at(index) = effect_frames.at(n).at(32 - y - 1).at(x); effect_buffer.at(index) = effect_frames.at(n).at(32 - y - 1).at(x);
...@@ -301,21 +339,20 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -301,21 +339,20 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr) { if (tmp == nullptr)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Effects: " + "Fehler beim Erstellen der Textur für die Effects: " + std::string(SDL_GetError()));
std::string(SDL_GetError()));
} }
if (SDL_UpdateTexture(tmp, NULL, effect_buffer.data(), if (SDL_UpdateTexture(
effect_frames.size() * 32 * sizeof(int32_t)) != 0) { tmp, NULL, effect_buffer.data(), effect_frames.size() * 32 * sizeof(int32_t)) != 0)
{
throw std::runtime_error( throw std::runtime_error(
"Fehler beim updaten der Textur für die Tiles: " + "Fehler beim updaten der Textur für die Tiles: " + std::string(SDL_GetError()));
std::string(SDL_GetError()));
} }
effect_textures.push_back( effect_textures.push_back(std::pair<SDL_Texture*, int>(tmp, effect_frames.size()));
std::pair<SDL_Texture *, int>(tmp, effect_frames.size()));
} }
this->effect_width = 32; this->effect_width = 32;
...@@ -324,59 +361,98 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) { ...@@ -324,59 +361,98 @@ Spritesheet::Spritesheet(std::string path, Engine &engine) {
// Tiles // Tiles
int Spritesheet::get_tile_width() { return tile_width; } int Spritesheet::get_tile_width()
{
return tile_width;
}
int Spritesheet::get_tile_height() { return tile_height; } int Spritesheet::get_tile_height()
{
return tile_height;
}
std::vector<std::pair<SDL_Texture *, int>> &Spritesheet::get_tile_textures() { std::vector<std::pair<SDL_Texture*, int>>& Spritesheet::get_tile_textures()
{
return tile_textures; return tile_textures;
} }
// Buildings // Buildings
int Spritesheet::get_building_width() { return this->building_width; } int Spritesheet::get_building_width()
{
return this->building_width;
}
int Spritesheet::get_building_height() { return this->building_height; } int Spritesheet::get_building_height()
{
return this->building_height;
}
std::vector<SDL_Texture *> &Spritesheet::get_building_textures() { std::vector<SDL_Texture*>& Spritesheet::get_building_textures()
{
return building_textures; return building_textures;
} }
// Units // Units
int Spritesheet::get_unit_width() { return this->unit_width; } int Spritesheet::get_unit_width()
{
return this->unit_width;
}
int Spritesheet::get_unit_height() { return this->unit_height; } int Spritesheet::get_unit_height()
{
return this->unit_height;
}
int Spritesheet::get_unit_moving_width() { return this->unit_moving_width; } int Spritesheet::get_unit_moving_width()
{
return this->unit_moving_width;
}
int Spritesheet::get_unit_moving_height() { return this->unit_moving_height; } int Spritesheet::get_unit_moving_height()
{
return this->unit_moving_height;
}
std::vector<std::vector<std::vector<std::pair<SDL_Texture*, int>>>>& std::vector<std::vector<std::vector<std::pair<SDL_Texture*, int>>>>&
Spritesheet::get_unit_textures() { Spritesheet::get_unit_textures()
{
return this->unit_textures; return this->unit_textures;
} }
// Effects // Effects
int Spritesheet::get_effect_width() { return this->effect_width; } int Spritesheet::get_effect_width()
{
return this->effect_width;
}
int Spritesheet::get_effect_height() { return this->effect_height; } int Spritesheet::get_effect_height()
{
return this->effect_height;
}
std::vector<std::pair<SDL_Texture *, int>> &Spritesheet::get_effect_textures() { std::vector<std::pair<SDL_Texture*, int>>& Spritesheet::get_effect_textures()
{
return this->effect_textures; return this->effect_textures;
} }
Spritesheet::~Spritesheet() { Spritesheet::~Spritesheet()
for (std::pair<SDL_Texture *, int> tile_texture : tile_textures) { {
for (std::pair<SDL_Texture*, int> tile_texture : tile_textures)
{
SDL_DestroyTexture(tile_texture.first); SDL_DestroyTexture(tile_texture.first);
} }
for (SDL_Texture *building_texture : building_textures) { for (SDL_Texture* building_texture : building_textures)
{
SDL_DestroyTexture(building_texture); SDL_DestroyTexture(building_texture);
} }
for (std::vector<std::vector<std::pair<SDL_Texture *, int>>> faction : for (std::vector<std::vector<std::pair<SDL_Texture*, int>>> faction : unit_textures)
unit_textures) { {
for (std::vector<std::pair<SDL_Texture *, int>> unit : faction) { for (std::vector<std::pair<SDL_Texture*, int>> unit : faction)
for (std::pair<SDL_Texture *, int> state : unit) { {
for (std::pair<SDL_Texture*, int> state : unit)
{
SDL_DestroyTexture(state.first); SDL_DestroyTexture(state.first);
} }
} }
......
/**
* Spritesheet.hpp
*
* @date 30.1.2025
* @author Frederik Keens
* @author David Maul
*/
#pragma once #pragma once
#include <SDL_render.h>
#include <SDL.h> #include <SDL.h>
#include <SDL_render.h> #include <SDL_render.h>
#include <string> #include <string>
#include <vector> #include <vector>
namespace advanced_wars { namespace advanced_wars
{
// Forward declaration // Forward declaration
class Engine; class Engine;
class Spritesheet { /**
* Spritesheet representation
*/
class Spritesheet
{
public: public:
/**
* Constructor
*
* @param path Path to the file to load the spritesheet from
* @param path Engine object with valid SDL context
*/
Spritesheet(std::string path, Engine& engine); Spritesheet(std::string path, Engine& engine);
/**
* Destructor
*/
~Spritesheet(); ~Spritesheet();
Spritesheet(const Spritesheet&) = delete; Spritesheet(const Spritesheet&) = delete;
...@@ -22,36 +45,113 @@ public: ...@@ -22,36 +45,113 @@ public:
// Tiles // Tiles
/**
* @return The width of a floor tile in pixels
*/
int get_tile_width(); int get_tile_width();
/**
* @return The height of a floor tile in pixels
*/
int get_tile_height(); int get_tile_height();
/**
* Gets vector containing the pairs of an SDL Texture
* and the number animations steps it has.
*
* E.g. The vector at 1 contains a pair of an SDL Texture for water, its animations
* and the number of animation steps. Animation frames are store linearised.
*
* Which index respresents which tile can be found in the enum TileId of tile.hpp
*
* @return A vector of all floor tile textures and their animations
*/
std::vector<std::pair<SDL_Texture*, int>>& get_tile_textures(); std::vector<std::pair<SDL_Texture*, int>>& get_tile_textures();
// Buildings // Buildings
/**
* @return The width of a building in pixels
*/
int get_building_width(); int get_building_width();
/**
* @return The height of a building in pixels
*/
int get_building_height(); int get_building_height();
/**
* Every element represents the texture for all buildings from a faction linearised.
*
* Which FactionId represents which color
* can be found in the BuildingId enum in building.hpp
*
* Order of the building sprites is the same as in buildingId enum in building.hpp
*
* @return Vector of all Building textures
*/
std::vector<SDL_Texture*>& get_building_textures(); std::vector<SDL_Texture*>& get_building_textures();
// Units // Units
/**
* @return The width of a unit while standing still in pixels
*/
int get_unit_width(); int get_unit_width();
/**
* @return The height of a unit while standing still in pixels
*/
int get_unit_height(); int get_unit_height();
/**
* @return The width of a unit while moving in pixels
*/
int get_unit_moving_width(); int get_unit_moving_width();
/**
* @return The height of a unit while moving in pixels
*/
int get_unit_moving_height(); int get_unit_moving_height();
std::vector<std::vector<std::vector<std::pair<SDL_Texture *, int>>>> & /**
get_unit_textures(); * Gets the hierarchical vector of all unit textures.
*
* The vector groups the faction, the UnitId and the state for each unit.
* The pair consist of the texture for that combination and the number of animation steps.
*
* E.g. A red faction(0) Recon(2) Unit that's unavailable(1) would be at [0][2][1].
* Animation frames are linearised.
*
* Indices can be found in the enums of unit.hpp
*
* @return A 3-dimensional vector of pairs consisting of a texture and
* the number of animation steps
*/
std::vector<std::vector<std::vector<std::pair<SDL_Texture*, int>>>>& get_unit_textures();
// Effects // Effects
/**
* @return The width of an effect in pixels
*/
int get_effect_width(); int get_effect_width();
/**
* @return The height of an effect in pixels
*/
int get_effect_height(); int get_effect_height();
/**
* Vector that contains pairs of effect textures and the number of animation steps it has.
*
* Each texture of an element is a pair of an effect
* and all its animation frames linearised.
*
* Which index represents which effect can be found in the EffectId enum in effect.hpp
*
* @return A vector of all effects and its animations
*/
std::vector<std::pair<SDL_Texture*, int>>& get_effect_textures(); std::vector<std::pair<SDL_Texture*, int>>& get_effect_textures();
private: private:
...@@ -66,8 +166,7 @@ private: ...@@ -66,8 +166,7 @@ private:
int building_height; int building_height;
// Units // Units
std::vector<std::vector<std::vector<std::pair<SDL_Texture *, int>>>> std::vector<std::vector<std::vector<std::pair<SDL_Texture*, int>>>> unit_textures;
unit_textures;
int unit_width; int unit_width;
int unit_height; int unit_height;
int unit_moving_width; int unit_moving_width;
......
...@@ -2,18 +2,17 @@ ...@@ -2,18 +2,17 @@
#include "spritesheet.hpp" #include "spritesheet.hpp"
#include <vector> #include <vector>
namespace advanced_wars { namespace advanced_wars
{
Tile::Tile(TileId id, int x, int y) Tile::Tile(TileId id, int x, int y) : id(id), x(x), y(y) {}
: id(id), x(x), y(y) {
}; void Tile::render(Engine* engine, int scale)
{
Spritesheet* spritesheet = engine->get_spritesheet();
void Tile::render(Engine &engine, int scale) { int step =
Spritesheet *spritesheet = engine.get_spritesheet(); engine->get_stage() % spritesheet->get_tile_textures().at(static_cast<int>(id)).second;
int step = engine.get_stage() %
spritesheet->get_tile_textures().at(static_cast<int>(id)).second;
SDL_Rect src; SDL_Rect src;
src.x = step * spritesheet->get_tile_width(); src.x = step * spritesheet->get_tile_width();
...@@ -28,8 +27,7 @@ void Tile::render(Engine &engine, int scale) { ...@@ -28,8 +27,7 @@ void Tile::render(Engine &engine, int scale) {
dest.h = spritesheet->get_tile_height() * scale; dest.h = spritesheet->get_tile_height() * scale;
SDL_RenderCopyEx( SDL_RenderCopyEx(
engine.renderer(), engine->renderer(), spritesheet->get_tile_textures().at(static_cast<int>(id)).first, &src,
spritesheet->get_tile_textures().at(static_cast<int>(id)).first, &src,
&dest, 0, NULL, SDL_FLIP_NONE); &dest, 0, NULL, SDL_FLIP_NONE);
} }
......
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
#include "engine.hpp" #include "engine.hpp"
#include "scene.hpp" #include "scene.hpp"
namespace advanced_wars { namespace advanced_wars
{
enum class TileId { enum class TileId
{
PLAIN = 0, PLAIN = 0,
WATER = 1, WATER = 1,
FOREST = 2, FOREST = 2,
...@@ -38,14 +40,15 @@ enum class TileId { ...@@ -38,14 +40,15 @@ enum class TileId {
CLIFF_INVERSE_CORNER_BOTTOM_RIGHT = 29, CLIFF_INVERSE_CORNER_BOTTOM_RIGHT = 29,
}; };
class Tile { class Tile
{
public: public:
Tile(TileId id, int x, int y); Tile(TileId id, int x, int y);
TileId id; TileId id;
int x; int x;
int y; int y;
void render(Engine &engine, int scale); void render(Engine* engine, int scale);
}; };
} // namespace advanced_wars } // namespace advanced_wars
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment