From 68f63f3f660961d5e695481910325f9c8bd5a69f Mon Sep 17 00:00:00 2001 From: Patricia Aas Date: Wed, 16 Jun 2021 12:52:04 +0200 Subject: [PATCH] Canvas rewrite (#6) * Beginning rewrite * Move all constants to canvas, wire sprite handling code * Make Sprite a struct and reformat * Fix warning Co-authored-by: Corentin Jabot --- lib/Board.cpp | 10 +-- lib/Board.hpp | 2 +- lib/Canvas.cpp | 71 ++++++++++++++++++ lib/Canvas.hpp | 34 +++++++++ lib/Game.cpp | 2 +- lib/Game.hpp | 4 +- lib/GameWindow.cpp | 160 ---------------------------------------- lib/GameWindow.hpp | 100 ------------------------- lib/PacMan.cpp | 13 ++-- lib/PacMan.hpp | 3 +- lib/PacManAnimation.cpp | 5 +- lib/Pellets.hpp | 2 +- lib/SDLWindow.cpp | 113 ++++++++++++++++++++++++++++ lib/SDLWindow.hpp | 82 ++++++++++++++++++++ lib/Sprite.cpp | 1 + lib/Sprite.hpp | 9 +++ lib/SuperPellets.cpp | 4 +- lib/SuperPellets.hpp | 2 +- 18 files changed, 333 insertions(+), 284 deletions(-) create mode 100644 lib/Canvas.cpp create mode 100644 lib/Canvas.hpp delete mode 100644 lib/GameWindow.cpp delete mode 100644 lib/GameWindow.hpp create mode 100644 lib/SDLWindow.cpp create mode 100644 lib/SDLWindow.hpp create mode 100644 lib/Sprite.cpp create mode 100644 lib/Sprite.hpp diff --git a/lib/Board.cpp b/lib/Board.cpp index 47f8a02..e0391ec 100644 --- a/lib/Board.cpp +++ b/lib/Board.cpp @@ -49,10 +49,10 @@ Board::Board() { } bool Board::isWalkable(Position point, float position_delta, Direction direction) const { - if(point.x <= 0 || point.x >= COLUMNS-1) - return true; + if (point.x <= 0 || point.x >= COLUMNS - 1) + return true; - switch (direction) { + switch (direction) { case Direction::LEFT: return board_state[int(point.y)][int(point.x - position_delta)] != 0; case Direction::RIGHT: @@ -72,7 +72,7 @@ std::vector Board::initialPelletPositions() const { for (uint8_t row = 0; row < ROWS; row++) { for (uint8_t column = 0; column < COLUMNS; column++) { if (board_state[row][column] == 1) - positions.push_back({column, row}); + positions.push_back({ column, row }); } } return positions; @@ -83,7 +83,7 @@ std::vector Board::initialSuperPelletPositions() const { for (uint8_t row = 0; row < ROWS; row++) { for (uint8_t column = 0; column < COLUMNS; column++) { if (board_state[row][column] == 4) - positions.push_back({column, row}); + positions.push_back({ column, row }); } } return positions; diff --git a/lib/Board.hpp b/lib/Board.hpp index aa035c2..97c0d4b 100644 --- a/lib/Board.hpp +++ b/lib/Board.hpp @@ -20,7 +20,7 @@ public: [[nodiscard]] std::vector initialSuperPelletPositions() const; - static Position initialPacManPosition() { return {14, 23}; } + static Position initialPacManPosition() { return { 14, 23 }; } private: uint8_t board_state[ROWS][COLUMNS]{}; diff --git a/lib/Canvas.cpp b/lib/Canvas.cpp new file mode 100644 index 0000000..2890e1c --- /dev/null +++ b/lib/Canvas.cpp @@ -0,0 +1,71 @@ +#include "Canvas.hpp" + +#include + +#include "PacMan.hpp" +#include "Pellets.hpp" +#include "SuperPellets.hpp" + +Canvas::Canvas() + : window(windowDimensions()) {} + +void Canvas::update(const PacMan & pacMan, const Pellets & pellets, const SuperPellets & superPellets) { + window.clear(); + + renderMaze(); + renderPellets(pellets); + renderSuperPellets(superPellets); + renderPacMan(pacMan); + + window.render(); +} + +void Canvas::renderMaze() const { + SDL_Rect maze_translated = { LEFT_MARGIN, TOP_MARGIN, MAZE_WIDTH, MAZE_HEIGHT }; + Sprite maze = window.getBackground(); + window.renderSprite(maze, maze_translated); +} + +void Canvas::renderPellets(const Pellets & pellets) const { + Sprite pellet = getSprite(pellets.currentSprite()); + std::vector pelletPositions = pellets.currentPositions(); + for (const auto & pos : pelletPositions) { + renderSprite(pellet, pos); + } +} + +void Canvas::renderSuperPellets(const SuperPellets & superPellets) const { + Sprite pellet = getSprite(superPellets.currentSprite()); + std::vector superPelletPositions = superPellets.currentPositions(); + for (const auto & pos : superPelletPositions) { + renderSprite(pellet, pos); + } +} + +void Canvas::renderPacMan(const PacMan & pac_man) const { + Sprite pacmanSprite = getSprite(pac_man.currentSprite()); + const auto & pos = pac_man.position(); + renderSprite(pacmanSprite, SDL_Point{ int(pos.x), int(pos.y) }); +} + +SDL_Rect Canvas::windowDimensions() const { + return { 0, 0, LEFT_MARGIN + MAZE_WIDTH + SCORE_WIDTH, TOP_MARGIN + MAZE_HEIGHT + BOTTOM_MARGIN }; +} + +Sprite Canvas::getSprite(SDL_Point coordinate) const { + return window.getSprite( + { coordinate.x * DEFAULT_SPRITE_WIDTH, + coordinate.y * DEFAULT_SPRITE_HEIGHT, + DEFAULT_SPRITE_WIDTH, + DEFAULT_SPRITE_HEIGHT }); +} + +void Canvas::renderSprite(Sprite sprite, SDL_Point point) const { + SDL_Rect target = { + LEFT_MARGIN + int((point.x * DEFAULT_SPRITE_WIDTH - sprite.rect.w / 2) * TEXTURE_SCALE_FACTOR), + TOP_MARGIN + int((point.y * DEFAULT_SPRITE_WIDTH - sprite.rect.h / 2) * TEXTURE_SCALE_FACTOR), + sprite.rect.w, + sprite.rect.h + }; + window.renderSprite(sprite, target); +} diff --git a/lib/Canvas.hpp b/lib/Canvas.hpp new file mode 100644 index 0000000..3cdac44 --- /dev/null +++ b/lib/Canvas.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "SDLWindow.hpp" + +class PacMan; +class Pellets; +class SuperPellets; + +class Canvas { +public: + Canvas(); + void update(const PacMan & pacMan, const Pellets & pellets, const SuperPellets & superPellets); + +private: + static constexpr int16_t LEFT_MARGIN = 40; + static constexpr int16_t TOP_MARGIN = 40; + static constexpr int16_t BOTTOM_MARGIN = 40; + static constexpr int16_t MAZE_WIDTH = 448; + static constexpr int16_t MAZE_HEIGHT = 496; + static constexpr int16_t SCORE_WIDTH = 200; + static constexpr int16_t DEFAULT_SPRITE_WIDTH = 32; + static constexpr int16_t DEFAULT_SPRITE_HEIGHT = 32; + static constexpr float TEXTURE_SCALE_FACTOR = 0.5; + + void renderMaze() const; + void renderPacMan(const PacMan & pac_man) const; + void renderPellets(const Pellets & pellets) const; + void renderSuperPellets(const SuperPellets & superPellets) const; + void renderSprite(Sprite sprite, SDL_Point point) const; + + SDL_Rect windowDimensions() const; + Sprite getSprite(SDL_Point rect) const; + SDLWindow window; +}; diff --git a/lib/Game.cpp b/lib/Game.cpp index 806f1e7..aae9f4a 100644 --- a/lib/Game.cpp +++ b/lib/Game.cpp @@ -20,7 +20,7 @@ void Game::run() { auto milli_delta = std::chrono::duration_cast(time_delta); pacMan.update(milli_delta, inputState, board); current_time += time_delta; - window.update(pacMan, pellets, superPellets); + canvas.update(pacMan, pellets, superPellets); } } diff --git a/lib/Game.hpp b/lib/Game.hpp index b184d4f..616b3ef 100644 --- a/lib/Game.hpp +++ b/lib/Game.hpp @@ -1,7 +1,7 @@ #pragma once #include "Board.hpp" -#include "GameWindow.hpp" +#include "Canvas.hpp" #include "PacMan.hpp" #include "Pellets.hpp" #include "SuperPellets.hpp" @@ -15,7 +15,7 @@ public: void run(); private: - GameWindow window; + Canvas canvas; Board board; PacMan pacMan; Pellets pellets; diff --git a/lib/GameWindow.cpp b/lib/GameWindow.cpp deleted file mode 100644 index 9209d32..0000000 --- a/lib/GameWindow.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include "GameWindow.hpp" - -#include -#include -#include - -#include "PacMan.hpp" -#include "Pellets.hpp" -#include "SuperPellets.hpp" - -GameWindow::GameWindow() { - initSDL(); - initSDLImage(); - - const auto window_dimension = windowDimensions(); - - auto sdl_window = createWindow(window_dimension.w, window_dimension.h); - auto sdl_renderer = createRenderer(sdl_window); - createWindowSurface(sdl_window); - setDrawColor(sdl_renderer); - maze_texture = loadTexture(sdl_renderer, "maze.png"); - sprite_texture = loadTexture(sdl_renderer, "sprites32.png"); -} - -void GameWindow::update(const PacMan & pacMan, const Pellets & pellets, const SuperPellets & superPellets) { - SDL_RenderClear(renderer.get()); - - renderMaze(); - renderPellets(pellets); - renderSuperPellets(superPellets); - renderPacMan(pacMan); - - SDL_RenderPresent(renderer.get()); -} - -void GameWindow::renderMaze() const { - SDL_Rect maze_rect = { 0, 0, MAZE_WIDTH, MAZE_HEIGHT }; - SDL_Rect maze_translated = { LEFT_MARGIN, TOP_MARGIN, MAZE_WIDTH, MAZE_HEIGHT }; - renderTexture(maze_texture.get(), maze_rect, maze_translated); -} - -void GameWindow::renderSuperPellets(const SuperPellets & superPellets) const { - SDL_Rect sprite_rect = textureGeometry(superPellets.currentSprite()); - std::vector superPelletPositions = superPellets.currentPositions(); - for (const auto & pos : superPelletPositions) { - renderTexture(sprite_texture.get(), sprite_rect, pos); - } -} - -void GameWindow::renderPellets(const Pellets & pellets) const { - SDL_Rect sprite_rect = textureGeometry(pellets.currentSprite()); - std::vector pelletPositions = pellets.currentPositions(); - for (const auto & pos : pelletPositions) { - renderTexture(sprite_texture.get(), sprite_rect, pos); - } -} - -void GameWindow::renderPacMan(const PacMan & pac_man) const { - SDL_Rect sprite_rect = textureGeometry(pac_man.currentSprite()); - Position pacman_pos = pac_man.position(); - renderTexture(sprite_texture.get(), sprite_rect, SDL_Point{ int(pacman_pos.x), int(pacman_pos.y) }); -} - -SDL_Rect GameWindow::textureGeometry(SDL_Point p) const { - return { p.x * 32, p.y * 32, 32, 32 }; -} - -SDL_Rect GameWindow::windowDimensions() const { - return { 0, 0, LEFT_MARGIN + MAZE_WIDTH + SCORE_WIDTH, TOP_MARGIN + MAZE_HEIGHT + BOTTOM_MARGIN }; -} - -void GameWindow::renderTexture(SDL_Texture * texture, const SDL_Rect & src, SDL_Point p) const { - SDL_Rect target = { - LEFT_MARGIN + int((p.x * DEFAULT_TEXTURE_WIDTH - src.w / 2) * TEXTURE_SCALE_FACTOR), - TOP_MARGIN + int((p.y * DEFAULT_TEXTURE_WIDTH - src.h / 2) * TEXTURE_SCALE_FACTOR), - src.w, - src.h - }; - renderTexture(texture, src, target); -} - -void GameWindow::renderTexture(SDL_Texture * texture, const SDL_Rect & src, const SDL_Rect & target) const { - - if (SDL_RenderCopy(renderer.get(), texture, &src, &target) < 0) - exitFailure("Failed to copy texture to renderer"); -} - -void GameWindow::initSDL() { - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) - exitFailure("Failed to initialize the SDL2 library"); -} - -void GameWindow::initSDLImage() { - int img_flags = IMG_INIT_PNG; - if (IMG_Init(img_flags) != img_flags) - exitImgFailure("Failed to init SDL_Image with png"); -} - -SDL_Window * GameWindow::createWindow(int width, int height) { - window = std::unique_ptr(SDL_CreateWindow( - "Pacman", - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - width, - height, - SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI)); - - if (!window) - exitFailure("Failed to create window"); - - return window.get(); -} - -SDL_Renderer * GameWindow::createRenderer(SDL_Window * sdl_window) { - renderer = std::unique_ptr(SDL_CreateRenderer( - sdl_window, - -1, - SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)); - - if (!renderer) - exitFailure("Failed to create renderer"); - - return renderer.get(); -} - -void GameWindow::createWindowSurface(SDL_Window * sdl_window) { - window_surface = std::unique_ptr(SDL_GetWindowSurface(sdl_window)); - if (!window_surface) - exitFailure("Failed to get the surface from the window"); -} - -void GameWindow::setDrawColor(SDL_Renderer * sdl_renderer) { - if (SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE) < 0) - exitFailure("Failed to set renderer color"); -} - -std::unique_ptr -GameWindow::loadTexture(SDL_Renderer * sdl_renderer, const std::string & path) { - auto surface = std::unique_ptr(IMG_Load(path.c_str())); - if (!surface) - exitImgFailure("Failed to load image"); - - auto texture = std::unique_ptr( - SDL_CreateTextureFromSurface(sdl_renderer, surface.get())); - if (!texture) - exitFailure("Failed to create texture from surface"); - return texture; -} - -void GameWindow::exitFailure(const std::string & message) { - std::cerr << message << "\n"; - std::cerr << "SDL2 Error: " << SDL_GetError() << "\n"; - exit(1); -} - -void GameWindow::exitImgFailure(const std::string & message) { - std::cerr << message << "\n"; - std::cerr << "SDL2_Image Error: " << IMG_GetError() << "\n"; - exit(1); -} diff --git a/lib/GameWindow.hpp b/lib/GameWindow.hpp deleted file mode 100644 index 332ef8d..0000000 --- a/lib/GameWindow.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include -#include - -struct SDL_Window_Deleter { - void operator()(SDL_Window * window) { - SDL_DestroyWindow(window); - } -}; - -struct SDL_Renderer_Deleter { - void operator()(SDL_Renderer * renderer) { - SDL_DestroyRenderer(renderer); - } -}; - -struct SDL_Surface_Deleter { - void operator()(SDL_Surface * surface) { - SDL_FreeSurface(surface); - } -}; - -struct SDL_Texture_Deleter { - void operator()(SDL_Texture * texture) { - SDL_DestroyTexture(texture); - } -}; - -struct TextureSize { - int width; - int height; -}; - -class PacMan; -class Pellets; -class SuperPellets; - -class GameWindow { -public: - explicit GameWindow(); - - void update(const PacMan & pacMan, const Pellets & pellets, const SuperPellets & superPellets); - -private: - static constexpr int16_t SCALE_FACTOR = 1; - static constexpr int16_t LEFT_MARGIN = 40; - static constexpr int16_t TOP_MARGIN = 40; - static constexpr int16_t BOTTOM_MARGIN = 40; - static constexpr int16_t MAZE_WIDTH = 448; - static constexpr int16_t MAZE_HEIGHT = 496; - static constexpr int16_t SCORE_WIDTH = 200; - static constexpr int16_t DEFAULT_TEXTURE_WIDTH = 32; - static constexpr int16_t DEFAULT_TEXTURE_HEIGHT = 32; - static constexpr float TEXTURE_SCALE_FACTOR = 0.5; - - std::unique_ptr window; - std::unique_ptr renderer; - std::unique_ptr window_surface; - std::unique_ptr maze_texture; - std::unique_ptr sprite_texture; - - SDL_Window * createWindow(int width, int height); - - SDL_Renderer * createRenderer(SDL_Window * window); - - void createWindowSurface(SDL_Window * sdl_window); - - static void initSDL(); - - static void initSDLImage(); - - static void setDrawColor(SDL_Renderer * sdl_renderer); - - static void exitFailure(const std::string & message); - - static void exitImgFailure(const std::string & message); - - static std::unique_ptr - loadTexture(SDL_Renderer * sdl_renderer, const std::string & path); - - void renderMaze() const; - - void renderPacMan(const PacMan & pac_man) const; - - void renderPellets(const Pellets & pellets) const; - - void renderSuperPellets(const SuperPellets & superPellets) const; - - SDL_Rect windowDimensions() const; - - // Given an x - y coordinate of a texture in the assets file, - // returns a rectangle for the whole texture. - // Assumes texture are laid out in a 32x32 grid - SDL_Rect textureGeometry(SDL_Point) const; - - void renderTexture(SDL_Texture * texture, const SDL_Rect & src, SDL_Point) const; - void renderTexture(SDL_Texture * texture, const SDL_Rect & src, const SDL_Rect & target) const; -}; diff --git a/lib/PacMan.cpp b/lib/PacMan.cpp index 24a52fa..9b394fd 100644 --- a/lib/PacMan.cpp +++ b/lib/PacMan.cpp @@ -1,7 +1,7 @@ #include "PacMan.hpp" -PacMan::PacMan(const Board & board) : - pos(board.initialPacManPosition()) {} +PacMan::PacMan(const Board & board) + : pos(board.initialPacManPosition()) {} SDL_Point PacMan::currentSprite() const { return pacManAnimation.animationFrame(direction); @@ -36,11 +36,10 @@ void PacMan::updateMazePosition(std::chrono::milliseconds time_delta, const Boar float position_delta = std::min(1.0, (time_delta.count() / 128.0)); // Handle teleport - if(pos.x >= COLUMNS-1 && direction == Direction::RIGHT) { - pos.x = -1; - } - else if(pos.x <= 0 && direction == Direction::LEFT) { - pos.x = COLUMNS; + if (pos.x >= COLUMNS - 1 && direction == Direction::RIGHT) { + pos.x = -1; + } else if (pos.x <= 0 && direction == Direction::LEFT) { + pos.x = COLUMNS; } else if (board.isWalkable(pos, position_delta, desired_direction)) { diff --git a/lib/PacMan.hpp b/lib/PacMan.hpp index fe1ff90..8d02b9e 100644 --- a/lib/PacMan.hpp +++ b/lib/PacMan.hpp @@ -1,8 +1,8 @@ #pragma once #include "Direction.hpp" -#include "Position.hpp" #include "PacManAnimation.hpp" +#include "Position.hpp" #include #include @@ -21,7 +21,6 @@ public: void update(std::chrono::milliseconds time_delta, InputState state, const Board & board); private: - Direction direction = Direction::NONE; Direction desired_direction = Direction::NONE; Position pos; diff --git a/lib/PacManAnimation.cpp b/lib/PacManAnimation.cpp index a0375c1..38606db 100644 --- a/lib/PacManAnimation.cpp +++ b/lib/PacManAnimation.cpp @@ -2,8 +2,6 @@ SDL_Point PacManAnimation::animationFrame(Direction direction) const { switch (direction) { - case Direction::NONE: - return closed; case Direction::LEFT: return left_animation[animation_position]; case Direction::RIGHT: @@ -12,6 +10,9 @@ SDL_Point PacManAnimation::animationFrame(Direction direction) const { return up_animation[animation_position]; case Direction::DOWN: return down_animation[animation_position]; + case Direction::NONE: + default: + return closed; } } diff --git a/lib/Pellets.hpp b/lib/Pellets.hpp index daca2df..5269cad 100644 --- a/lib/Pellets.hpp +++ b/lib/Pellets.hpp @@ -1,7 +1,7 @@ #pragma once -#include "Position.hpp" #include "Board.hpp" +#include "Position.hpp" #include diff --git a/lib/SDLWindow.cpp b/lib/SDLWindow.cpp new file mode 100644 index 0000000..9d81b1c --- /dev/null +++ b/lib/SDLWindow.cpp @@ -0,0 +1,113 @@ +#include "SDLWindow.hpp" + +#include +#include + +SDLWindow::SDLWindow(SDL_Rect windowGeometry) { + initSDL(); + initSDLImage(); + + createWindow(windowGeometry.w, windowGeometry.h); + createRenderer(); + createWindowSurface(); + setDrawColor(); + maze_texture = loadTexture("maze.png"); + sprite_texture = loadTexture("sprites32.png"); +} + +void SDLWindow::clear() { + SDL_RenderClear(renderer.get()); +} + +void SDLWindow::render() { + SDL_RenderPresent(renderer.get()); +} + +Sprite SDLWindow::getBackground() const { + int w, h; + if (SDL_QueryTexture(maze_texture.get(), nullptr, nullptr, &w, &h) != 0) { + exitFailure("Failed to get texture geometry"); + } + + SDL_Rect maze_rect = { 0, 0, w, h }; + return { maze_texture.get(), maze_rect }; +} + +Sprite SDLWindow::getSprite(SDL_Rect rect) const { + return { sprite_texture.get(), rect }; +} + +void SDLWindow::renderSprite(Sprite sprite, SDL_Rect target) const { + if (SDL_RenderCopy(renderer.get(), sprite.texture, &sprite.rect, &target) < 0) + exitFailure("Failed to copy texture to renderer"); +} + +void SDLWindow::initSDL() { + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + exitFailure("Failed to initialize the SDL2 library"); +} + +void SDLWindow::initSDLImage() { + int img_flags = IMG_INIT_PNG; + if (IMG_Init(img_flags) != img_flags) + exitImgFailure("Failed to init SDL_Image with png"); +} + +void SDLWindow::createWindow(int width, int height) { + window = std::unique_ptr(SDL_CreateWindow( + "Pacman", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + width, + height, + SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI)); + + if (!window) + exitFailure("Failed to create window"); +} + +void SDLWindow::createRenderer() { + renderer = std::unique_ptr(SDL_CreateRenderer( + window.get(), + -1, + SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)); + + if (!renderer) + exitFailure("Failed to create renderer"); +} + +void SDLWindow::createWindowSurface() { + window_surface = std::unique_ptr(SDL_GetWindowSurface(window.get())); + if (!window_surface) + exitFailure("Failed to get the surface from the window"); +} + +void SDLWindow::setDrawColor() { + if (SDL_SetRenderDrawColor(renderer.get(), 0, 0, 0, SDL_ALPHA_OPAQUE) < 0) + exitFailure("Failed to set renderer color"); +} + +std::unique_ptr +SDLWindow::loadTexture(const std::string & path) { + auto surface = std::unique_ptr(IMG_Load(path.c_str())); + if (!surface) + exitImgFailure("Failed to load image"); + + auto texture = std::unique_ptr( + SDL_CreateTextureFromSurface(renderer.get(), surface.get())); + if (!texture) + exitFailure("Failed to create texture from surface"); + return texture; +} + +void SDLWindow::exitFailure(const std::string & message) { + std::cerr << message << "\n"; + std::cerr << "SDL2 Error: " << SDL_GetError() << "\n"; + exit(1); +} + +void SDLWindow::exitImgFailure(const std::string & message) { + std::cerr << message << "\n"; + std::cerr << "SDL2_Image Error: " << IMG_GetError() << "\n"; + exit(1); +} diff --git a/lib/SDLWindow.hpp b/lib/SDLWindow.hpp new file mode 100644 index 0000000..d0c15e5 --- /dev/null +++ b/lib/SDLWindow.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include "Sprite.hpp" +#include +#include +#include + +struct SDL_Window_Deleter { + void operator()(SDL_Window * window) { + SDL_DestroyWindow(window); + } +}; + +struct SDL_Renderer_Deleter { + void operator()(SDL_Renderer * renderer) { + SDL_DestroyRenderer(renderer); + } +}; + +struct SDL_Surface_Deleter { + void operator()(SDL_Surface * surface) { + SDL_FreeSurface(surface); + } +}; + +struct SDL_Texture_Deleter { + void operator()(SDL_Texture * texture) { + SDL_DestroyTexture(texture); + } +}; + +struct TextureSize { + int width; + int height; +}; + +class PacMan; +class Pellets; +class SuperPellets; + +class SDLWindow { +public: + explicit SDLWindow(SDL_Rect windowGeometry); + + void clear(); + + void render(); + + Sprite getBackground() const; + Sprite getSprite(SDL_Rect rect) const; + void renderSprite(Sprite sprite, SDL_Rect target) const; + +private: + static constexpr int16_t SCALE_FACTOR = 1; + + std::unique_ptr window; + std::unique_ptr renderer; + std::unique_ptr window_surface; + std::unique_ptr maze_texture; + std::unique_ptr sprite_texture; + + void createWindow(int width, int height); + + void createRenderer(); + + void createWindowSurface(); + + static void initSDL(); + + static void initSDLImage(); + + void setDrawColor(); + + static void exitFailure(const std::string & message); + + static void exitImgFailure(const std::string & message); + + std::unique_ptr + loadTexture(const std::string & path); + + SDL_Rect windowDimensions() const; +}; diff --git a/lib/Sprite.cpp b/lib/Sprite.cpp new file mode 100644 index 0000000..86523c6 --- /dev/null +++ b/lib/Sprite.cpp @@ -0,0 +1 @@ +#include "Sprite.hpp" diff --git a/lib/Sprite.hpp b/lib/Sprite.hpp new file mode 100644 index 0000000..34e9373 --- /dev/null +++ b/lib/Sprite.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include +#include + +struct Sprite { + SDL_Texture * texture; + SDL_Rect rect; +}; diff --git a/lib/SuperPellets.cpp b/lib/SuperPellets.cpp index f1584e1..2c8595f 100644 --- a/lib/SuperPellets.cpp +++ b/lib/SuperPellets.cpp @@ -1,4 +1,4 @@ #include "SuperPellets.hpp" -SuperPellets::SuperPellets(const Board & board) : - positions(board.initialSuperPelletPositions()) {} +SuperPellets::SuperPellets(const Board & board) + : positions(board.initialSuperPelletPositions()) {} diff --git a/lib/SuperPellets.hpp b/lib/SuperPellets.hpp index fd8d07b..a2cfd60 100644 --- a/lib/SuperPellets.hpp +++ b/lib/SuperPellets.hpp @@ -1,7 +1,7 @@ #pragma once -#include "Position.hpp" #include "Board.hpp" +#include "Position.hpp" #include