Create GameState
This commit is contained in:
parent
8082c69aff
commit
e5e46a0e65
10 changed files with 80 additions and 85 deletions
|
@ -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);
|
||||
}
|
||||
|
|
39
lib/Game.cpp
39
lib/Game.cpp
|
@ -1,4 +1,5 @@
|
|||
#include "Game.hpp"
|
||||
#include "GameState.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,31 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "GameState.hpp"
|
||||
#include "Position.hpp"
|
||||
#include "Score.hpp"
|
||||
#include <optional>
|
||||
|
||||
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<sf::Event> 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
|
||||
|
|
|
@ -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<Blinky, Speedy, Inky, Clyde> 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();
|
||||
};
|
||||
|
|
18
lib/include/GameState.hpp
Normal file
18
lib/include/GameState.hpp
Normal file
|
@ -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<Blinky, Speedy, Inky, Clyde> ghosts;
|
||||
PacMan pacMan;
|
||||
Pellets pellets;
|
||||
SuperPellets superPellets;
|
||||
};
|
||||
|
||||
} // namespace pacman
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "Atlas.hpp"
|
||||
#include "Board.hpp"
|
||||
#include "Direction.hpp"
|
||||
#include "InputState.hpp"
|
||||
#include "Position.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace pacman {
|
||||
|
||||
|
|
Loading…
Reference in a new issue