diff --git a/.gitignore b/.gitignore index ca66a88978fc923bb6160eb3522421a686fd5c2f..cfe248684bf25a7f01a66fe526f9080b9d1f0c42 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,14 @@ build/ out/ cmake-build-*/ +test.png + .idea/ .vscode/ *.swp *.swo *~ +.cache/ *.o *.obj diff --git a/CMakeLists.txt b/CMakeLists.txt index f410ba906e8bd0ee84af72691b2ef4cb60630140..b6ceb5df22c964fdaedb6ec8a3aa0ab0e42d1c49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,13 +7,9 @@ project(ADVANCED_WARS LANGUAGES CXX ) -set(ADVANCED_WARS_SOURCES - src/scene.hpp - src/unit.cpp - src/building.cpp - src/level.cpp - src/engine.cpp - src/window.cpp +file(GLOB ADVANCED_WARS_SOURCES + "${PROJECT_SOURCE_DIR}/src/*.cpp" + "${PROJECT_SOURCE_DIR}/src/*.hpp" ) # C++ Standard festlegen @@ -34,11 +30,17 @@ set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH}) # SDL2 find_package(SDL2 REQUIRED) find_package(SDL2_IMAGE REQUIRED) +find_package(HDF5 REQUIRED COMPONENTS CXX) include_directories(${SDL2_INCLUDE_DIR}) include_directories(${SDL2_IMG_INCLUDE_DIR}) +include_directories(${HDF5_INCLUDE_DIRS}) # Executable erstellen add_executable(advanced_wars src/main.cpp ${ADVANCED_WARS_SOURCES}) -target_link_libraries(advanced_wars ${SDL2_LIBRARY} ${SDL2_IMG_LIBRARY}) -target_link_libraries(advanced_wars m) +target_link_libraries(advanced_wars + ${SDL2_LIBRARY} + ${SDL2_IMG_LIBRARY} + ${HDF5_LIBRARIES} + m +) \ No newline at end of file diff --git a/src/engine.cpp b/src/engine.cpp index 976bfbd0bd02baa420c95c04944456e8288f7a25..69da6ac3d21535c764e35273a38c07758ee094b9 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1,47 +1,79 @@ +#include "engine.hpp" +#include "SDL_render.h" #include "scene.hpp" +#include "spritesheet.hpp" #include "window.hpp" -#include "engine.hpp" -#include <vector> -#include <stdexcept> #include <SDL.h> +#include <SDL_image.h> +#include <stdexcept> +#include <vector> namespace advanced_wars { -Engine::Engine(Window &window, Scene &scene): window(window), scene(scene) { - this->renderer = SDL_CreateRenderer( - this->window.sdl_window(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); +Engine::Engine(Window &window) : window(window), quit(false) { + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + throw std::runtime_error("SDL could not initialize: " + + std::string(SDL_GetError())); + } + + int imgFlags = IMG_INIT_PNG; + if (!(IMG_Init(imgFlags) & imgFlags)) { + throw std::runtime_error( + "SDL_image could not initialize! SDL_image Error: " + + std::string(IMG_GetError())); + } + + this->sdl_renderer = + SDL_CreateRenderer(this->window.sdl_window(), -1, + SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (renderer == nullptr) { + if (sdl_renderer == nullptr) { throw std::runtime_error("SDL could not generate renderer: " + std::string(SDL_GetError())); } } -void Engine::set_scene() {} +void Engine::set_scene(Scene &scene) { this->scene = &scene; } + +void Engine::set_spritesheet(Spritesheet spritesheet) { + this->spritesheet = spritesheet; +} void Engine::pump() { - SDL_Event e; - while(SDL_PollEvent(&e)) { - if(e.type == SDL_QUIT) { - this->quit = true; - } else { - this->events.push_back(e); - } + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) { + this->quit = true; + } else { + this->events.push_back(e); } + } } -bool Engine::exited() { - return this->quit; -} +bool Engine::exited() { return this->quit; } void Engine::render() { - if(SDL_RenderClear(this->renderer) != 0) { - throw std::runtime_error("Could not clear renderer: " + std::string(SDL_GetError())); - } + if (SDL_RenderClear(this->sdl_renderer) != 0) { + throw std::runtime_error("Could not clear renderer: " + + std::string(SDL_GetError())); + } + + if (!scene.has_value()) { + return; + } + + this->scene.value()->render(this->sdl_renderer, this->events); + + SDL_RenderPresent(this->sdl_renderer); +} - this->scene.render(this->renderer, this->events); +SDL_Renderer *Engine::renderer() { return this->sdl_renderer; } - SDL_RenderPresent(this->renderer); +Engine::~Engine() { + SDL_DestroyRenderer(sdl_renderer); + IMG_Quit(); + SDL_Quit(); } } // namespace advanced_wars diff --git a/src/engine.hpp b/src/engine.hpp index 6d4396777806e6b1ef5733cd1c7a79968a33cfd1..2eb4341fe1977992698d823e77d843460ccd5656 100644 --- a/src/engine.hpp +++ b/src/engine.hpp @@ -1,45 +1,46 @@ -#ifndef ENGINE_HPP -#define ENGINE_HPP +#pragma once -#include "window.hpp" +#include "SDL_render.h" #include "scene.hpp" +#include "spritesheet.hpp" +#include "window.hpp" #include <SDL.h> +#include <optional> #include <vector> -namespace advanced_wars -{ +namespace advanced_wars { /** * @brief The main window of the game */ -class Engine -{ +class Engine { public: + Engine(Window &window); + + Engine(const Engine &) = delete; + Engine &operator=(const Engine &) = delete; - Engine(Window &window, Scene &scene); + bool exited(); - /** - * Forbids the creation of copies of a window - */ - Engine(const Engine&) = delete; - Engine& operator=(const Engine&) = delete; + void pump(); - bool exited(); + void set_scene(Scene &scene); - void pump(); + void set_spritesheet(Spritesheet spritesheet); - void set_scene(); + void render(); - void render(); + SDL_Renderer *renderer(); + + ~Engine(); private: - Window &window; - Scene &scene; - SDL_Renderer* renderer; - std::vector<SDL_Event> events; - bool quit; + Window &window; + SDL_Renderer *sdl_renderer; + std::optional<Scene *> scene; + std::optional<Spritesheet> spritesheet; + std::vector<SDL_Event> events; + bool quit; }; -} - -#endif +} // namespace advanced_wars diff --git a/src/level.hpp b/src/level.hpp index c76a6f13002711af310cda1bf84a605756b1f466..367615b316415fe786a4f3239a008f2a20eaaaa3 100644 --- a/src/level.hpp +++ b/src/level.hpp @@ -1,35 +1,31 @@ -#ifndef LEVEL_HPP -#define LEVEL_HPP +#pragma once +#include "building.hpp" #include "scene.hpp" #include "tile.hpp" #include "unit.hpp" -#include "building.hpp" +#include <SDL.h> #include <string> #include <vector> -#include <SDL.h> -namespace advanced_wars -{ +namespace advanced_wars { /** * @brief The main window of the game */ -class Level: public Scene -{ +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); + Level(std::string name, int width, int height, std::vector<Tile> tiles, + std::vector<Building> buildings, std::vector<Unit> units); - void render(SDL_Renderer *renderer, std::vector<SDL_Event> &events); + void render(SDL_Renderer *renderer, std::vector<SDL_Event> &events); private: - std::string name; - int width; - int height; - std::vector<Building> buildings; - std::vector<Unit> units; + std::string name; + int width; + int height; + std::vector<Building> buildings; + std::vector<Unit> units; }; -} - -#endif +} // namespace advanced_wars diff --git a/src/main.cpp b/src/main.cpp index 4e26a6ab800db30830cadc30ca281d01cbc78e20..3afc6058195b1333fc8490093b6a6cdd9b1641f7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,22 +1,30 @@ -#include "window.hpp" #include "engine.hpp" #include "level.hpp" +#include "spritesheet.hpp" +#include "window.hpp" #include <vector> using namespace advanced_wars; int main() { - Window window("Advanced Wars", 800, 600); + Window window("Advanced Wars", 800, 600); + + Engine engine(window); + + Level level("Osnabrück", 20, 20, std::vector<Tile>(), std::vector<Building>(), + std::vector<Unit>()); + + engine.set_scene(level); - Level level("Osnabrück",20,20, std::vector<Tile>(), std::vector<Building>(),std::vector<Unit>()); + Spritesheet spritesheet("../test.png", engine); - Engine engine(window, level); + engine.set_spritesheet(spritesheet); - while(!engine.exited()) { - engine.pump(); - engine.render(); - } + while (!engine.exited()) { + engine.pump(); + engine.render(); + } - return 0; + return 0; } diff --git a/src/scene.hpp b/src/scene.hpp index 220c2ef0d7c20db2c9cc1b61fbcb2fede43db9dc..9730ff57ef2d0861eea0dcbb442b5bd9d9b1a2b1 100644 --- a/src/scene.hpp +++ b/src/scene.hpp @@ -1,5 +1,4 @@ -#ifndef SCENE_HPP -#define SCENE_HPP +#pragma once #include <SDL.h> #include <vector> @@ -8,8 +7,7 @@ namespace advanced_wars { class Scene { public: -virtual void render(SDL_Renderer *renderer, std::vector<SDL_Event> &events) = 0; + virtual void render(SDL_Renderer *renderer, + std::vector<SDL_Event> &events) = 0; }; -} - -#endif +} // namespace advanced_wars diff --git a/src/spritesheet.cpp b/src/spritesheet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75125b2c6459aa37e84da9d325249836f91c7e51 --- /dev/null +++ b/src/spritesheet.cpp @@ -0,0 +1,53 @@ +#include "spritesheet.hpp" +#include "SDL_render.h" +#include "SDL_surface.h" +#include "engine.hpp" + +#include <SDL_image.h> +#include <stdexcept> + +namespace advanced_wars { + +Spritesheet::Spritesheet(std::string path, Engine &engine) { + SDL_Surface *loadedSurface = IMG_Load(path.c_str()); + if (loadedSurface == nullptr) { + throw std::runtime_error("Fehler beim Laden des Bildes " + path + ": " + + std::string(IMG_GetError())); + } + + texture = SDL_CreateTextureFromSurface(engine.renderer(), loadedSurface); + + if (texture == nullptr) { + throw std::runtime_error("Fehler beim Erstellen der Textur: " + + std::string(SDL_GetError())); + } + + SDL_FreeSurface(loadedSurface); +} + +int Spritesheet::get_tile_steps(int tile) { return tiles.at(tile).second; } + +int Spritesheet::get_tile_width() { return tile_width; } + +int Spritesheet::get_tile_height() { return tile_height; } + +int Spritesheet::render_tile(SDL_Renderer *renderer, int tile, int step, + SDL_Rect *rect) { + if (step >= this->get_tile_steps(tile) || step < 0) { + throw std::runtime_error("Tried to access step " + std::to_string(step) + + " for tile " + std::to_string(tile)); + } + + SDL_Rect src; + src.x = tile * tile_width; + src.y = 0; + src.w = tile_width; + src.h = tile_height; + + return SDL_RenderCopyEx(renderer, texture, &src, rect, 0, NULL, + SDL_FLIP_NONE); +} + +Spritesheet::~Spritesheet() { SDL_DestroyTexture(texture); } + +} // namespace advanced_wars \ No newline at end of file diff --git a/src/spritesheet.hpp b/src/spritesheet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f9d60e1ac2300c8064ca755b369cb8e65b3d10d8 --- /dev/null +++ b/src/spritesheet.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "SDL_render.h" +#include <SDL.h> +#include <string> +#include <vector> + +namespace advanced_wars { + +// Forward declaration +class Engine; + +class Spritesheet { +public: + Spritesheet(std::string path, Engine &engine); + + ~Spritesheet(); + + // Tiles + int get_tile_steps(int tile); + + int get_tile_width(); + + int get_tile_height(); + + int render_tile(SDL_Renderer *renderer, int tile, int step, SDL_Rect *rect); + + // Units: TODO + + // Buildings: TODO + +private: + SDL_Texture *texture; + // Tiles + int tile_width; + int tile_height; + std::vector<std::pair<int, int>> tiles; +}; +} // namespace advanced_wars diff --git a/src/window.cpp b/src/window.cpp index f312289db361a23c90fd0864cd1110b2b42fe705..aa7568152015a5a476320381b6caafe34e11f0eb 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,53 +1,35 @@ #include "window.hpp" #include <stdexcept> -namespace advanced_wars -{ - -Window::Window(std::string title, int w, int h) -{ - /// Init width and height - width = w; - height = h; - - // Generate SDL main window - window = SDL_CreateWindow( - title.c_str(), - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - width, - height, - SDL_WINDOW_SHOWN ); - - if(window == nullptr) - { - throw std::runtime_error("SDL window could not be generated: " + std::string(SDL_GetError())); - } +namespace advanced_wars { + +Window::Window(std::string title, int w, int h) { + /// Init width and height + width = w; + height = h; + + // Generate SDL main window + window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, width, height, + SDL_WINDOW_SHOWN); + + if (window == nullptr) { + throw std::runtime_error("SDL window could not be generated: " + + std::string(SDL_GetError())); + } } +int Window::w() { return width; } -int Window::w() -{ - return width; -} +int Window::h() { return height; } -int Window::h() -{ - return height; -} +SDL_Window *Window::sdl_window() { return window; } -SDL_Window* Window::sdl_window() -{ - return window; +Window::~Window() { + if (window) { + SDL_DestroyWindow(window); + window = nullptr; + } } -Window::~Window() -{ - if(window) - { - SDL_DestroyWindow(window); - window = nullptr; - } -} - -} +} // namespace advanced_wars diff --git a/src/window.hpp b/src/window.hpp index 1637accc97a2f2c04e9904fea18225f836c807aa..9cd664dc9f4a22e9384b668f41735309e0d412b3 100644 --- a/src/window.hpp +++ b/src/window.hpp @@ -1,59 +1,52 @@ -#ifndef WINDOW_HPP -#define WINDOW_HPP +#pragma once -#include <string> #include <SDL.h> +#include <string> -namespace advanced_wars -{ +namespace advanced_wars { /** * @brief The main window of the game */ -class Window -{ +class Window { public: - - /*** - * Creates a main window with given \ref title, width \ref w and height \ref h - * - * @param title Title of the window - * @param w Width - * @param h Height - */ - Window(std::string title, int w, int h); - - /** - * Forbids the creation of copies of a window - */ - Window(const Window&) = delete; - //Window& operator=(const Window&) = delete; - - /*** - * Destructor. - */ - ~Window(); - - /// Retruns the current width of the window - int w(); - - /// Returns the current height of the window - int h(); - - SDL_Window* sdl_window(); + /*** + * Creates a main window with given \ref title, width \ref w and height \ref h + * + * @param title Title of the window + * @param w Width + * @param h Height + */ + Window(std::string title, int w, int h); + + /** + * Forbids the creation of copies of a window + */ + Window(const Window &) = delete; + // Window& operator=(const Window&) = delete; + + /*** + * Destructor. + */ + ~Window(); + + /// Retruns the current width of the window + int w(); + + /// Returns the current height of the window + int h(); + + SDL_Window *sdl_window(); private: + /// SDL main window struct + SDL_Window *window; - /// SDL main window struct - SDL_Window* window; + /// Window width + int width; - /// Window width - int width; - - /// Window height - int height; + /// Window height + int height; }; -} - -#endif +} // namespace advanced_wars