diff --git a/lib/Canvas.cpp b/lib/Canvas.cpp index 92b52f0..69cacfd 100644 --- a/lib/Canvas.cpp +++ b/lib/Canvas.cpp @@ -8,11 +8,10 @@ namespace pacman { Canvas::Canvas() - : window(sf::VideoMode((viewDimensions().width/2.0), (viewDimensions().height/2.0)), + : window(sf::VideoMode((viewDimensions().width / 2.0), (viewDimensions().height / 2.0)), "Pacman", - sf::Style::Titlebar | sf::Style::Close) - , view(sf::FloatRect(0, 0, viewDimensions().width, viewDimensions().height)) -{ + sf::Style::Titlebar | sf::Style::Close), + view(sf::FloatRect(0, 0, viewDimensions().width, viewDimensions().height)) { window.setView(view); window.setFramerateLimit(60); @@ -21,30 +20,29 @@ Canvas::Canvas() // We render the game in view at twice the native resolution, // Then project it on a scaled window - on some mac we get the // scaling factor of the window to adjust the resolution - const auto scale = scaling_factor_for_window(window.getSystemHandle()); - const auto width = viewDimensions().width/2.0 * scale; - const auto height = viewDimensions().height/2.0 * scale; + const auto scale = scaling_factor_for_window(window.getSystemHandle()); + const auto width = viewDimensions().width / 2.0 * scale; + const auto height = viewDimensions().height / 2.0 * scale; window.setSize(sf::Vector2u(width, height)); - maze_texture = loadTexture("maze.png"); sprites_texture = loadTexture("sprites32.png"); game_font = loadFont("retro_font.ttf"); } -void Canvas::update(const Game & game) { +void Canvas::update(const GameState & gameState, const Score & score) { clear(); renderMaze(); - renderPellets(game.pellets); - renderSuperPellets(game.superPellets); + renderPellets(gameState.pellets); + renderSuperPellets(gameState.superPellets); - std::apply([&](const auto &... ghost) { (renderGhost(ghost), ...); }, game.ghosts); + std::apply([&](const auto &... ghost) { (renderGhost(ghost), ...); }, gameState.ghosts); - renderScore(game.score.points); - renderLives(game.score.lives); + renderScore(score.points); + renderLives(score.lives); - renderPacMan(game.pacMan); + renderPacMan(gameState.pacMan); render(); } @@ -107,7 +105,7 @@ void Canvas::renderGhost(const Ghost & ghost) { void Canvas::renderScore(int score) { const int x = (LEFT_MARGIN + TARGET_MAZE_WIDTH + LEFT_MARGIN); - const int y = (TOP_MARGIN * 2) ; + const int y = (TOP_MARGIN * 2); sf::Text text; text.setPosition(x, y); @@ -133,8 +131,8 @@ void Canvas::renderLives(int lives) { } Rect Canvas::viewDimensions() { - const double width = (LEFT_MARGIN + TARGET_MAZE_WIDTH + SCORE_WIDTH); - const double height = (TOP_MARGIN + TARGET_MAZE_HEIGHT + BOTTOM_MARGIN); + const double width = (LEFT_MARGIN + TARGET_MAZE_WIDTH + SCORE_WIDTH); + const double height = (TOP_MARGIN + TARGET_MAZE_HEIGHT + BOTTOM_MARGIN); return { 0, 0, int(width), int(height) }; } @@ -150,7 +148,7 @@ Sprite Canvas::getSprite(GridPosition coordinate) const { void Canvas::renderSprite(Sprite sprite, Position pos) { pos.x = LEFT_MARGIN + (pos.x * SPRITE_WIDTH); - pos.y = TOP_MARGIN + (pos.y * SPRITE_HEIGHT); + pos.y = TOP_MARGIN + (pos.y * SPRITE_HEIGHT); sprite.setPosition(pos.x, pos.y); window.draw(sprite); } diff --git a/lib/Game.cpp b/lib/Game.cpp index 02412e1..4e08400 100644 --- a/lib/Game.cpp +++ b/lib/Game.cpp @@ -1,4 +1,5 @@ #include "Game.hpp" +#include "GameState.hpp" #include @@ -9,11 +10,7 @@ constexpr int NORMAL_PELLET_POINTS = 10; constexpr int POWER_PELLET_POINTS = 50; constexpr int GHOST_POINTS = 200; -Game::Game() - : pacMan(), - pellets(), - superPellets(), - ghosts(Blinky(), Speedy(), Inky(), Clyde()) { +Game::Game() { score.lives = DEFAULT_LIVES; } @@ -44,13 +41,13 @@ void Game::run() { accumulator -= delta_time; t += delta_time; } - canvas.update(*this); + canvas.update(gameState, score); } } void Game::step(std::chrono::milliseconds delta, InputState inputState) { - pacMan.update(delta, inputState); + gameState.pacMan.update(delta, inputState.direction()); if (timeSinceDeath.count() != 0) { timeSinceDeath += delta; @@ -60,57 +57,57 @@ void Game::step(std::chrono::milliseconds delta, InputState inputState) { std::apply([&](auto &... ghost) { (ghost.reset(), ...); }, - ghosts); - pacMan.reset(); + gameState.ghosts); + gameState.pacMan.reset(); timeSinceDeath = std::chrono::milliseconds(0); } if (timeSinceDeath.count()) return; - if (!pacMan.onTheMove()) + if (!gameState.pacMan.hasDirection()) return; std::apply([&](auto &... ghost) { (ghost.update(delta), ...); (checkCollision(ghost), ...); }, - ghosts); + gameState.ghosts); eatPellets(); } -void Game::checkCollision(Ghost & g) { - if (timeSinceDeath.count() || g.isEyes()) +void Game::checkCollision(Ghost & ghost) { + if (timeSinceDeath.count() || ghost.isEyes()) return; - if (g.positionInGrid() != pacMan.positionInGrid()) + if (ghost.positionInGrid() != gameState.pacMan.positionInGrid()) return; - if (g.isFrightened()) { - g.eat(); + if (ghost.isFrightened()) { + ghost.eat(); score.points += GHOST_POINTS; } else { - pacMan.eat(); + gameState.pacMan.eat(); score.lives--; timeSinceDeath = std::chrono::milliseconds(1); } } void Game::eatPellets() { - const auto pos = pacMan.positionInGrid(); - if (pellets.eatPelletAtPosition(pos)) { + const auto pos = gameState.pacMan.positionInGrid(); + if (gameState.pellets.eatPelletAtPosition(pos)) { score.eatenPellets++; score.points += NORMAL_PELLET_POINTS; } - if (superPellets.eatPelletAtPosition(pos)) { + if (gameState.superPellets.eatPelletAtPosition(pos)) { score.eatenPellets++; score.points += POWER_PELLET_POINTS; std::apply([&](auto &... ghost) { (ghost.frighten(), ...); }, - ghosts); + gameState.ghosts); } } diff --git a/lib/PacMan.cpp b/lib/PacMan.cpp index 05b841b..4060250 100644 --- a/lib/PacMan.cpp +++ b/lib/PacMan.cpp @@ -31,29 +31,19 @@ void PacMan::reset() { pos = pacman::Board::initialPacManPosition(); } -void PacMan::update(std::chrono::milliseconds time_delta, InputState state) { +void PacMan::update(std::chrono::milliseconds time_delta, Direction input_direction) { if (eaten) { updateAnimationPosition(time_delta, false); return; } + if (input_direction != Direction::NONE) + desired_direction = input_direction; const auto old = pos; - setDirection(state); updateMazePosition(time_delta); const bool paused = pos == old; updateAnimationPosition(time_delta, paused); } -void PacMan::setDirection(const InputState & state) { - if (state.left) - desired_direction = Direction::LEFT; - else if (state.right) - desired_direction = Direction::RIGHT; - else if (state.up) - desired_direction = Direction::UP; - else if (state.down) - desired_direction = Direction::DOWN; -} - void PacMan::updateAnimationPosition(std::chrono::milliseconds time_delta, bool paused) { if (paused) { pacManAnimation.pause(); diff --git a/lib/include/Canvas.hpp b/lib/include/Canvas.hpp index 91c1eff..04231c7 100644 --- a/lib/include/Canvas.hpp +++ b/lib/include/Canvas.hpp @@ -1,31 +1,26 @@ #pragma once +#include "GameState.hpp" #include "Position.hpp" #include "Score.hpp" #include namespace pacman { -class Game; -class Ghost; -class PacMan; -class Pellets; -class SuperPellets; - class Canvas { public: Canvas(); - void update(const Game & game); + void update(const GameState & gameState, const Score & score); std::optional pollEvent(); private: static constexpr uint16_t LEFT_MARGIN = 40 * 2; - static constexpr uint16_t TOP_MARGIN = 40 * 2; + static constexpr uint16_t TOP_MARGIN = 40 * 2; static constexpr uint16_t BOTTOM_MARGIN = 40 * 2; static constexpr uint16_t MAZE_WIDTH = 448; static constexpr uint16_t MAZE_HEIGHT = 496; static constexpr uint16_t MAZE_SCALE_UP = 2; - static constexpr uint16_t TARGET_MAZE_WIDTH = 448 * MAZE_SCALE_UP; + static constexpr uint16_t TARGET_MAZE_WIDTH = 448 * MAZE_SCALE_UP; static constexpr uint16_t TARGET_MAZE_HEIGHT = 496 * MAZE_SCALE_UP; static constexpr uint16_t SCORE_WIDTH = 200 * 2; static constexpr uint16_t SPRITE_WIDTH = 32; @@ -54,7 +49,6 @@ private: sf::Texture maze_texture; sf::Texture sprites_texture; sf::Font game_font; - }; } // namespace pacman diff --git a/lib/include/Game.hpp b/lib/include/Game.hpp index 2a2d46b..a580b59 100644 --- a/lib/include/Game.hpp +++ b/lib/include/Game.hpp @@ -1,38 +1,26 @@ #pragma once -#include "Board.hpp" #include "Canvas.hpp" -#include "Ghost.hpp" -#include "PacMan.hpp" -#include "Pellets.hpp" -#include "Score.hpp" -#include "SuperPellets.hpp" +#include "GameState.hpp" +#include "InputState.hpp" namespace pacman { -class InputState; - class Game { public: Game(); void run(); private: - friend class Canvas; - Canvas canvas; - Board board; - PacMan pacMan; - Pellets pellets; - SuperPellets superPellets; - std::tuple ghosts; + GameState gameState; Score score; std::chrono::milliseconds timeSinceDeath{}; void step(std::chrono::milliseconds delta, InputState inputState); void eatPellets(); void processEvents(InputState & inputState); - void checkCollision(Ghost & g); + void checkCollision(Ghost & ghost); [[nodiscard]] static auto now(); }; diff --git a/lib/include/GameState.hpp b/lib/include/GameState.hpp new file mode 100644 index 0000000..aad923e --- /dev/null +++ b/lib/include/GameState.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Ghost.hpp" +#include "PacMan.hpp" +#include "Pellets.hpp" +#include "Score.hpp" +#include "SuperPellets.hpp" + +namespace pacman { + +struct GameState { + std::tuple ghosts; + PacMan pacMan; + Pellets pellets; + SuperPellets superPellets; +}; + +} // namespace pacman diff --git a/lib/include/InputState.hpp b/lib/include/InputState.hpp index ce36138..cdefacb 100644 --- a/lib/include/InputState.hpp +++ b/lib/include/InputState.hpp @@ -9,6 +9,19 @@ public: bool down = false; bool left = false; bool right = false; + + [[nodiscard]] Direction direction() const { + if (left) + return Direction::LEFT; + else if (right) + return Direction::RIGHT; + else if (up) + return Direction::UP; + else if (down) + return Direction::DOWN; + else + return Direction::NONE; + } }; } // namespace pacman diff --git a/lib/include/PacMan.hpp b/lib/include/PacMan.hpp index bc4a538..292980f 100644 --- a/lib/include/PacMan.hpp +++ b/lib/include/PacMan.hpp @@ -21,11 +21,11 @@ public: [[nodiscard]] GridPosition positionInGrid() const; - void update(std::chrono::milliseconds time_delta, InputState state); + void update(std::chrono::milliseconds time_delta, Direction input_direction); void eat(); void reset(); - [[nodiscard]] bool onTheMove() const { + [[nodiscard]] bool hasDirection() const { return direction != Direction::NONE; } @@ -36,8 +36,6 @@ private: PacManAnimation pacManAnimation; bool eaten = false; - void setDirection(const InputState & state); - void updateAnimationPosition(std::chrono::milliseconds time_delta, bool paused); void updateMazePosition(std::chrono::milliseconds time_delta); }; diff --git a/lib/include/PacManAnimation.hpp b/lib/include/PacManAnimation.hpp index b49c0d9..fab5eae 100644 --- a/lib/include/PacManAnimation.hpp +++ b/lib/include/PacManAnimation.hpp @@ -3,7 +3,6 @@ #include "Atlas.hpp" #include "Board.hpp" #include "Direction.hpp" -#include "InputState.hpp" #include "Position.hpp" #include diff --git a/lib/include/Position.hpp b/lib/include/Position.hpp index ecd93a7..da5e6ae 100644 --- a/lib/include/Position.hpp +++ b/lib/include/Position.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include namespace pacman {