From caeb26e90ef09fdad85af72f460644e09d3b2c7c Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 21 Mar 2020 16:12:16 +0100 Subject: Player sprite direction, read map file --- README.md | 3 ++ include/game.hpp | 7 +++ include/graphics.hpp | 5 +- map/cosomopoly01.sokoban | 9 ++++ map/square.sokoban | 7 +++ screenshot.png | Bin 0 -> 46284 bytes src/game.cpp | 134 +++++++++++++++++++++++++++++++---------------- src/graphics.cpp | 26 +++++++-- src/main.cpp | 28 +++++----- 9 files changed, 157 insertions(+), 62 deletions(-) create mode 100644 map/cosomopoly01.sokoban create mode 100644 map/square.sokoban create mode 100644 screenshot.png diff --git a/README.md b/README.md index 99861a7..2bbf9af 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,14 @@ Mario sokoban project of [openclassrooms](https://openclassrooms.com/fr/courses/19980-apprenez-a-programmer-en-c/18709-tp-mario-sokoban) (in C++ instead of C because I can't be bothered). +![screenshot](./screenshot.png) + # Usage ``` make all ./mario_sokoban +./mario_sokoban [mapfile] ``` # Dependencies diff --git a/include/game.hpp b/include/game.hpp index 647a12d..946f07c 100644 --- a/include/game.hpp +++ b/include/game.hpp @@ -1,6 +1,8 @@ #ifndef GAME_HPP # define GAME_HPP +#include +#include #include #include #include @@ -9,6 +11,7 @@ class Game { public: Game(std::string fmt); + Game(std::ifstream &file); ~Game(); enum Direction @@ -40,6 +43,7 @@ public: size_t getHeight() const; size_t getWidth() const; Position const &getPlayer() const; + Direction getPlayerDirection() const; private: @@ -51,8 +55,11 @@ private: std::vector m_cratePos; std::vector m_payloadPos; + void construct(std::string fmt); + void findWidth(std::string fmt); bool tryMoveCrate(Position &pos, Direction direction); bool validPosition(Position pos); + static Position makePos(int y, int x); }; diff --git a/include/graphics.hpp b/include/graphics.hpp index ea5d70e..5f274a3 100644 --- a/include/graphics.hpp +++ b/include/graphics.hpp @@ -28,7 +28,10 @@ private: SDL_Texture *m_crateTex; SDL_Texture *m_crateSolvedTex; SDL_Texture *m_payloadTex; - SDL_Texture *m_playerTex; + SDL_Texture *m_playerUpTex; + SDL_Texture *m_playerDownTex; + SDL_Texture *m_playerLeftTex; + SDL_Texture *m_playerRightTex; void drawGame(); void drawCell(Game::Cell cell, int y, int x); diff --git a/map/cosomopoly01.sokoban b/map/cosomopoly01.sokoban new file mode 100644 index 0000000..7dc5f4e --- /dev/null +++ b/map/cosomopoly01.sokoban @@ -0,0 +1,9 @@ + #### + # #### + # # +## #. # +# * #*## +# $ * # +# # @ # +# #### +##### diff --git a/map/square.sokoban b/map/square.sokoban new file mode 100644 index 0000000..23d637c --- /dev/null +++ b/map/square.sokoban @@ -0,0 +1,7 @@ +####### +# m # +#* # +# U # +# U # +# * # +####### diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..2e042fd Binary files /dev/null and b/screenshot.png differ diff --git a/src/game.cpp b/src/game.cpp index 1ab4ab8..cdc8937 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,52 +1,29 @@ #include "game.hpp" -#define EMPTY_CHAR ' ' -#define WALL_CHAR '#' -#define CRATE_CHAR 'U' -#define PAYLOAD_CHAR '*' -#define MARIO_CHAR 'm' +#define EMPTY_CHAR ' ' +#define WALL_CHAR '#' +#define CRATE_CHAR '$' +#define CRATE_SOLVED_CHAR '*' +#define PAYLOAD_CHAR '.' +#define MARIO_CHAR '@' Game::Game(std::string fmt) : m_playerDirection(DirectionDown) { - size_t p; + construct(fmt); +} - m_height = std::count(fmt.begin(), fmt.end(), '\n'); - m_grid = new Cell*[m_height]; - m_width = fmt.find("\n"); - for (int i = 0; (p = fmt.find("\n")) != std::string::npos; i++) - { - std::string token = fmt.substr(0, p); - m_grid[i] = new Cell[m_width]; - for (size_t j = 0; j < token.size(); j++) - { - switch (token[j]) - { - case EMPTY_CHAR: - m_grid[i][j] = CellEmpty; - break; - case WALL_CHAR: - m_grid[i][j] = CellWall; - break; - case CRATE_CHAR: - m_grid[i][j] = CellEmpty; - m_cratePos.push_back(makePos(i, j)); - break; - case PAYLOAD_CHAR: - m_grid[i][j] = CellEmpty; - m_payloadPos.push_back(makePos(i, j)); - break; - case MARIO_CHAR: - m_grid[i][j] = CellEmpty; - m_playerPos.y = i; - m_playerPos.x = j; - break; - default: - exit(1); - } - } - fmt.erase(0, p + 1); - } +Game::Game(std::ifstream &file) + : m_playerDirection(DirectionDown) +{ + std::string fmt; + std::string line; + + if (!file) + exit(1); + while (getline(file, line)) + fmt += line + "\n"; + construct(fmt); } Game::~Game() @@ -131,7 +108,73 @@ Game::Position const &Game::getPlayer() const return m_playerPos; } -#include +Game::Direction Game::getPlayerDirection() const +{ + return m_playerDirection; +} + +void Game::construct(std::string fmt) +{ + size_t p; + + m_height = std::count(fmt.begin(), fmt.end(), '\n'); + m_grid = new Cell*[m_height]; + findWidth(fmt); + for (int i = 0; (p = fmt.find("\n")) != std::string::npos; i++) + { + std::string token = fmt.substr(0, p); + m_grid[i] = new Cell[m_width]; + for (size_t j = 0; j < m_width; j++) + m_grid[i][j] = CellEmpty; + for (size_t j = 0; j < token.size(); j++) + { + switch (token[j]) + { + case EMPTY_CHAR: + m_grid[i][j] = CellEmpty; + break; + case WALL_CHAR: + m_grid[i][j] = CellWall; + break; + case CRATE_CHAR: + m_grid[i][j] = CellEmpty; + m_cratePos.push_back(makePos(i, j)); + break; + case CRATE_SOLVED_CHAR: + m_grid[i][j] = CellEmpty; + m_cratePos.push_back(makePos(i, j)); + m_payloadPos.push_back(makePos(i, j)); + break; + case PAYLOAD_CHAR: + m_grid[i][j] = CellEmpty; + m_payloadPos.push_back(makePos(i, j)); + break; + case MARIO_CHAR: + m_grid[i][j] = CellEmpty; + m_playerPos.y = i; + m_playerPos.x = j; + break; + default: + std::cerr << "Cannot parse map" << std::endl; + exit(1); + } + } + fmt.erase(0, p + 1); + } +} + +void Game::findWidth(std::string fmt) +{ + size_t p; + m_width = 0; + + for (int i = 0; (p = fmt.find("\n")) != std::string::npos; i++) + { + m_width = std::max(m_width, p); + fmt.erase(0, p + 1); + } +} + bool Game::tryMoveCrate(Position &pos, Direction direction) { Position clone = pos; @@ -150,9 +193,8 @@ bool Game::tryMoveCrate(Position &pos, Direction direction) case DirectionRight: clone.x++; } - // std::cout << pos.y << ", " << pos.x << "\n"; - // std::cout << get(pos) << std::endl; - if (!validPosition(clone) || get(clone) == CellCrate || get(clone) == CellWall) + if (!validPosition(clone) || get(clone) == CellCrate + || get(clone) == CellCrateSolved || get(clone) == CellWall) return false; pos = clone; return true; diff --git a/src/graphics.cpp b/src/graphics.cpp index b773827..298fc43 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -15,12 +15,18 @@ Graphics::Graphics(Game &game, std::string title, int width, int height): m_crateTex = loadImage("sprite/crate.jpg"); m_crateSolvedTex = loadImage("sprite/crate_solved.jpg"); m_payloadTex = loadImage("sprite/payload.png"); - m_playerTex = loadImage("sprite/mario_down.gif"); + m_playerUpTex = loadImage("sprite/mario_up.gif"); + m_playerDownTex = loadImage("sprite/mario_down.gif"); + m_playerLeftTex = loadImage("sprite/mario_left.gif"); + m_playerRightTex = loadImage("sprite/mario_right.gif"); } Graphics::~Graphics() { - SDL_DestroyTexture(m_playerTex); + SDL_DestroyTexture(m_playerRightTex); + SDL_DestroyTexture(m_playerLeftTex); + SDL_DestroyTexture(m_playerDownTex); + SDL_DestroyTexture(m_playerUpTex); SDL_DestroyTexture(m_payloadTex); SDL_DestroyTexture(m_crateSolvedTex); SDL_DestroyTexture(m_crateTex); @@ -97,7 +103,21 @@ void Graphics::drawPlayer() r.y = pos.y * (m_height / m_game.getHeight()); r.w = m_width / m_game.getWidth(); r.h = m_height / m_game.getHeight(); - putImage(m_playerTex, &r); + switch (m_game.getPlayerDirection()) + { + case Game::DirectionUp: + putImage(m_playerUpTex, &r); + break; + case Game::DirectionDown: + putImage(m_playerDownTex, &r); + break; + case Game::DirectionLeft: + putImage(m_playerLeftTex, &r); + break; + case Game::DirectionRight: + putImage(m_playerRightTex, &r); + break; + } } void Graphics::handleEvent() diff --git a/src/main.cpp b/src/main.cpp index 3f79ca7..b7168d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,24 @@ +#include +#include #include "game.hpp" #include "graphics.hpp" -int main() -{ - Game game( - "#######\n" - "# m #\n" - "#* #\n" - "# #\n" - "# U #\n" - "# U #\n" - "#######\n" - ); +#define DEFAULT_MAP_FILENAME "map/square.sokoban" +int main(int argc, char **argv) +{ + std::ifstream file; + if (argc == 1) + file.open(DEFAULT_MAP_FILENAME); + else if (argc == 2) + file.open(argv[1]); + else + { + std::cout << "Usage: " << argv[0] << " [mapfile]" << std::endl; + return 0; + } + Game game(file); Graphics graphics(game, "mario sokoban", 500, 500); - while (graphics.isRunning()) graphics.update(); return 0; -- cgit