Add ghosts
No movement for now!
This commit is contained in:
parent
79506d218e
commit
93186dc8b9
13 changed files with 295 additions and 101 deletions
50
lib/Atlas.hpp
Normal file
50
lib/Atlas.hpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Direction.hpp"
|
||||||
|
#include "Position.hpp"
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
namespace Atlas {
|
||||||
|
|
||||||
|
enum class Ghost {
|
||||||
|
blinky = 2,
|
||||||
|
speedy = 3,
|
||||||
|
inky = 4,
|
||||||
|
clyde = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr PositionInt pacman_right_wide = { 0, 0 };
|
||||||
|
constexpr PositionInt pacman_right_narrow = { 1, 0 };
|
||||||
|
constexpr PositionInt pacman_closed = { 2, 0 };
|
||||||
|
constexpr PositionInt pacman_left_narrow = { 3, 0 };
|
||||||
|
constexpr PositionInt pacman_left_wide = { 4, 0 };
|
||||||
|
constexpr PositionInt pacman_up_wide = { 5, 0 };
|
||||||
|
constexpr PositionInt pacman_up_narrow = { 6, 0 };
|
||||||
|
constexpr PositionInt pacman_down_wide = { 7, 0 };
|
||||||
|
constexpr PositionInt pacman_down_narrow = { 8, 0 };
|
||||||
|
|
||||||
|
constexpr PositionInt ghostSprite(Ghost ghost, Direction direction, bool alternative) {
|
||||||
|
assert(ghost >= Ghost::blinky && ghost <= Ghost::clyde && "Invalid Ghost");
|
||||||
|
int y = static_cast<int>(ghost);
|
||||||
|
int x = 0;
|
||||||
|
switch (direction) {
|
||||||
|
case Direction::RIGHT:
|
||||||
|
x = 0;
|
||||||
|
break;
|
||||||
|
case Direction::DOWN:
|
||||||
|
x = 2;
|
||||||
|
break;
|
||||||
|
case Direction::LEFT:
|
||||||
|
x = 4;
|
||||||
|
break;
|
||||||
|
case Direction::UP:
|
||||||
|
x = 6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
x = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (alternative)
|
||||||
|
x++;
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@
|
||||||
// 5 - pen doors
|
// 5 - pen doors
|
||||||
|
|
||||||
static const uint8_t board[ROWS][COLUMNS] = {
|
static const uint8_t board[ROWS][COLUMNS] = {
|
||||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
|
||||||
{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, // 1
|
{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, // 1
|
||||||
{ 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 }, // 2
|
{ 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 }, // 2
|
||||||
|
@ -50,11 +50,11 @@ Board::Board() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::isWalkableForPacMan(Position point, float d, Direction direction) const {
|
bool Board::isWalkableForPacMan(Position point, float d, Direction direction) const {
|
||||||
return isWalkable(point, d, direction, true);
|
return isWalkable(point, d, direction, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::isWalkableForGhost(Position point, float d, Direction direction) const {
|
bool Board::isWalkableForGhost(Position point, float d, Direction direction) const {
|
||||||
return isWalkable(point, d, direction, false);
|
return isWalkable(point, d, direction, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::isWalkable(Position point, float position_delta, Direction direction, bool pacman) const {
|
bool Board::isWalkable(Position point, float position_delta, Direction direction, bool pacman) const {
|
||||||
|
@ -62,29 +62,29 @@ bool Board::isWalkable(Position point, float position_delta, Direction direction
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto cellAtPosition = [&](Position point, float position_delta, Direction direction) {
|
auto cellAtPosition = [&](Position point, float position_delta, Direction direction) {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case Direction::LEFT:
|
case Direction::LEFT:
|
||||||
return board_state[int(point.y)][int(point.x - position_delta)];
|
return board_state[int(point.y)][int(point.x - position_delta)];
|
||||||
case Direction::RIGHT:
|
case Direction::RIGHT:
|
||||||
return board_state[int(point.y)][int(point.x) + 1];
|
return board_state[int(point.y)][int(point.x) + 1];
|
||||||
case Direction::UP:
|
case Direction::UP:
|
||||||
return board_state[int(point.y - position_delta)][int(point.x)];
|
return board_state[int(point.y - position_delta)][int(point.x)];
|
||||||
case Direction::DOWN:
|
case Direction::DOWN:
|
||||||
return board_state[int(point.y) + 1][int(point.x)];
|
return board_state[int(point.y) + 1][int(point.x)];
|
||||||
case Direction::NONE:
|
case Direction::NONE:
|
||||||
default:
|
default:
|
||||||
return uint8_t(0);
|
return uint8_t(Cell::wall);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto cell = cellAtPosition(point, position_delta, direction);
|
Cell cell = Cell(cellAtPosition(point, position_delta, direction));
|
||||||
return pacman ? cell != 0 : cell != 0 && cell != 5;
|
return pacman ? cell != Cell::wall : cell != Cell::wall && cell != Cell::pen_door;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PositionInt> Board::initialPelletPositions() const {
|
std::vector<PositionInt> Board::initialPelletPositions() const {
|
||||||
std::vector<PositionInt> positions;
|
std::vector<PositionInt> positions;
|
||||||
for (uint8_t row = 0; row < ROWS; row++) {
|
for (uint8_t row = 0; row < ROWS; row++) {
|
||||||
for (uint8_t column = 0; column < COLUMNS; column++) {
|
for (uint8_t column = 0; column < COLUMNS; column++) {
|
||||||
if (board_state[row][column] == 1)
|
if (board_state[row][column] == uint8_t(Cell::pellet))
|
||||||
positions.push_back({ column, row });
|
positions.push_back({ column, row });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ std::vector<PositionInt> Board::initialSuperPelletPositions() const {
|
||||||
std::vector<PositionInt> positions;
|
std::vector<PositionInt> positions;
|
||||||
for (uint8_t row = 0; row < ROWS; row++) {
|
for (uint8_t row = 0; row < ROWS; row++) {
|
||||||
for (uint8_t column = 0; column < COLUMNS; column++) {
|
for (uint8_t column = 0; column < COLUMNS; column++) {
|
||||||
if (board_state[row][column] == 4)
|
if (board_state[row][column] == uint8_t(Cell::power_pellet))
|
||||||
positions.push_back({ column, row });
|
positions.push_back({ column, row });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,15 @@ const uint8_t COLUMNS = 28;
|
||||||
|
|
||||||
class Board {
|
class Board {
|
||||||
public:
|
public:
|
||||||
|
enum class Cell {
|
||||||
|
wall = 0,
|
||||||
|
pellet = 1,
|
||||||
|
nothing = 2,
|
||||||
|
door = 3,
|
||||||
|
power_pellet = 4,
|
||||||
|
pen_door = 5,
|
||||||
|
};
|
||||||
|
|
||||||
Board();
|
Board();
|
||||||
|
|
||||||
[[nodiscard]] bool isWalkableForPacMan(Position point, float d, Direction direction) const;
|
[[nodiscard]] bool isWalkableForPacMan(Position point, float d, Direction direction) const;
|
||||||
|
@ -21,7 +30,19 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] std::vector<PositionInt> initialSuperPelletPositions() const;
|
[[nodiscard]] std::vector<PositionInt> initialSuperPelletPositions() const;
|
||||||
|
|
||||||
static Position initialPacManPosition() { return { 14, 23 }; }
|
static Position initialPacManPosition() { return { 13.5, 23 }; }
|
||||||
|
|
||||||
|
static Position initialBlinkyPosition() { return { 13.5, 11 }; }
|
||||||
|
static Position blinkyScatterTarget() { return { 25, -2 }; }
|
||||||
|
|
||||||
|
static Position initialSpeedyPosition() { return { 11.5, 14 }; }
|
||||||
|
static Position speedyScatterTarget() { return { 3, -2 }; }
|
||||||
|
|
||||||
|
static Position initialInkyPosition() { return { 13.5, 14 }; }
|
||||||
|
static Position inkyScatterTarget() { return { 27, 30 }; }
|
||||||
|
|
||||||
|
static Position initialClydePosition() { return { 15.5, 14 }; }
|
||||||
|
static Position clydeScatterTarget() { return { 0, 30 }; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] bool isWalkable(Position point, float d, Direction direction, bool pacman) const;
|
[[nodiscard]] bool isWalkable(Position point, float d, Direction direction, bool pacman) const;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "Canvas.hpp"
|
#include "Canvas.hpp"
|
||||||
|
#include "Game.hpp"
|
||||||
|
#include "Ghost.hpp"
|
||||||
#include "PacMan.hpp"
|
#include "PacMan.hpp"
|
||||||
#include "Pellets.hpp"
|
#include "Pellets.hpp"
|
||||||
#include "SuperPellets.hpp"
|
#include "SuperPellets.hpp"
|
||||||
|
@ -17,15 +18,21 @@ Canvas::Canvas()
|
||||||
game_font = loadFont("joystix.ttf");
|
game_font = loadFont("joystix.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::update(const PacMan & pacMan, const Pellets & pellets, const SuperPellets & superPellets, const Score & score) {
|
void Canvas::update(const Game & game) {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
renderMaze();
|
renderMaze();
|
||||||
renderPellets(pellets);
|
renderPellets(game.pellets);
|
||||||
renderSuperPellets(superPellets);
|
renderSuperPellets(game.superPellets);
|
||||||
renderPacMan(pacMan);
|
renderPacMan(game.pacMan);
|
||||||
renderScore(score.points);
|
|
||||||
renderLives(score.lives);
|
renderGhost(game.blinky);
|
||||||
|
renderGhost(game.speedy);
|
||||||
|
renderGhost(game.inky);
|
||||||
|
renderGhost(game.clyde);
|
||||||
|
|
||||||
|
renderScore(game.score.points);
|
||||||
|
renderLives(game.score.lives);
|
||||||
|
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
|
@ -73,6 +80,12 @@ void Canvas::renderPacMan(const PacMan & pac_man) {
|
||||||
renderSprite(pacmanSprite, pos);
|
renderSprite(pacmanSprite, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::renderGhost(const Ghost & ghost) {
|
||||||
|
Sprite sprite = getSprite(ghost.currentSprite());
|
||||||
|
const auto & pos = ghost.position();
|
||||||
|
renderSprite(sprite, pos);
|
||||||
|
}
|
||||||
|
|
||||||
void Canvas::renderScore(int score) {
|
void Canvas::renderScore(int score) {
|
||||||
const int x = LEFT_MARGIN + MAZE_WIDTH + LEFT_MARGIN;
|
const int x = LEFT_MARGIN + MAZE_WIDTH + LEFT_MARGIN;
|
||||||
const int y = TOP_MARGIN * 2;
|
const int y = TOP_MARGIN * 2;
|
||||||
|
@ -87,16 +100,16 @@ void Canvas::renderScore(int score) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::renderLives(int lives) {
|
void Canvas::renderLives(int lives) {
|
||||||
constexpr PositionInt liveSprite{3, 0};
|
constexpr PositionInt liveSprite = Atlas::pacman_left_narrow;
|
||||||
const int x = LEFT_MARGIN + MAZE_WIDTH + LEFT_MARGIN;
|
const int x = LEFT_MARGIN + MAZE_WIDTH + LEFT_MARGIN;
|
||||||
const int y = maze_texture.getSize().y;
|
const int y = maze_texture.getSize().y;
|
||||||
|
|
||||||
Sprite pacmanSprite = getSprite(liveSprite);
|
Sprite pacmanSprite = getSprite(liveSprite);
|
||||||
for(int i = 0; i < lives - 1; i++) {
|
for (int i = 0; i < lives - 1; i++) {
|
||||||
PositionInt pos{x + i * pacmanSprite.getTextureRect().width, y};
|
PositionInt pos{ x + i * pacmanSprite.getTextureRect().width, y };
|
||||||
pacmanSprite.setPosition(pos.x, pos.y);
|
pacmanSprite.setPosition(pos.x, pos.y);
|
||||||
window.draw(pacmanSprite);
|
window.draw(pacmanSprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect Canvas::windowDimensions() {
|
Rect Canvas::windowDimensions() {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Score.hpp"
|
#include "Score.hpp"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
class Game;
|
||||||
|
class Ghost;
|
||||||
class PacMan;
|
class PacMan;
|
||||||
class Pellets;
|
class Pellets;
|
||||||
class SuperPellets;
|
class SuperPellets;
|
||||||
|
@ -11,7 +13,7 @@ class SuperPellets;
|
||||||
class Canvas {
|
class Canvas {
|
||||||
public:
|
public:
|
||||||
Canvas();
|
Canvas();
|
||||||
void update(const PacMan & pacMan, const Pellets & pellets, const SuperPellets & superPellets, const Score &);
|
void update(const Game & game);
|
||||||
std::optional<sf::Event> pollEvent();
|
std::optional<sf::Event> pollEvent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -28,6 +30,7 @@ private:
|
||||||
void render();
|
void render();
|
||||||
void renderMaze();
|
void renderMaze();
|
||||||
void renderPacMan(const PacMan & pac_man);
|
void renderPacMan(const PacMan & pac_man);
|
||||||
|
void renderGhost(const Ghost & ghost);
|
||||||
void renderPellets(const Pellets & pellets);
|
void renderPellets(const Pellets & pellets);
|
||||||
void renderSuperPellets(const SuperPellets & superPellets);
|
void renderSuperPellets(const SuperPellets & superPellets);
|
||||||
void renderSprite(Sprite sprite, Position pos);
|
void renderSprite(Sprite sprite, Position pos);
|
||||||
|
|
77
lib/Game.cpp
77
lib/Game.cpp
|
@ -4,18 +4,18 @@
|
||||||
|
|
||||||
constexpr int DEFAULT_LIVES = 3;
|
constexpr int DEFAULT_LIVES = 3;
|
||||||
constexpr int NORMAL_PELLET_POINTS = 10;
|
constexpr int NORMAL_PELLET_POINTS = 10;
|
||||||
constexpr int POWER_PELLET_POINTS = 50;
|
constexpr int POWER_PELLET_POINTS = 50;
|
||||||
//constexpr int GHOST_POINTS[] = {200, 400, 800, 1600};
|
//constexpr int GHOST_POINTS[] = {200, 400, 800, 1600};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Game::Game()
|
Game::Game()
|
||||||
: pacMan(board),
|
: pacMan(board),
|
||||||
pellets(board),
|
pellets(board),
|
||||||
superPellets(board)
|
superPellets(board),
|
||||||
{
|
blinky(board),
|
||||||
score.lives = DEFAULT_LIVES;
|
speedy(board),
|
||||||
|
inky(board),
|
||||||
|
clyde(board) {
|
||||||
|
score.lives = DEFAULT_LIVES;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Game::now() {
|
auto Game::now() {
|
||||||
|
@ -24,44 +24,53 @@ auto Game::now() {
|
||||||
|
|
||||||
void Game::run() {
|
void Game::run() {
|
||||||
|
|
||||||
const std::chrono::milliseconds delta_time (1000/60);
|
const std::chrono::milliseconds delta_time(1000 / 60);
|
||||||
|
|
||||||
std::chrono::milliseconds t(0);
|
std::chrono::milliseconds t(0);
|
||||||
std::chrono::milliseconds accumulator(0);
|
std::chrono::milliseconds accumulator(0);
|
||||||
auto current_time = now();
|
auto current_time = now();
|
||||||
|
|
||||||
InputState inputState;
|
InputState inputState;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto newTime = now();
|
auto newTime = now();
|
||||||
auto frameTime = std::chrono::duration_cast<std::chrono::milliseconds>(newTime - current_time);
|
auto frameTime = std::chrono::duration_cast<std::chrono::milliseconds>(newTime - current_time);
|
||||||
current_time = newTime;
|
current_time = newTime;
|
||||||
accumulator += frameTime;
|
accumulator += frameTime;
|
||||||
processEvents(inputState);
|
processEvents(inputState);
|
||||||
if(inputState.close)
|
if (inputState.close)
|
||||||
return;
|
return;
|
||||||
while ( accumulator >= delta_time ) {
|
while (accumulator >= delta_time) {
|
||||||
pacMan.update(delta_time, inputState, board);
|
step(delta_time, inputState);
|
||||||
eatPellets();
|
accumulator -= delta_time;
|
||||||
accumulator -= delta_time;
|
t += delta_time;
|
||||||
t += delta_time;
|
|
||||||
}
|
|
||||||
canvas.update(pacMan, pellets, superPellets, score);
|
|
||||||
}
|
}
|
||||||
|
canvas.update(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::step(std::chrono::milliseconds delta, InputState inputState) {
|
||||||
|
pacMan.update(delta, inputState, board);
|
||||||
|
|
||||||
|
blinky.update(delta, board);
|
||||||
|
speedy.update(delta, board);
|
||||||
|
inky.update(delta, board);
|
||||||
|
clyde.update(delta, board);
|
||||||
|
|
||||||
|
eatPellets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::eatPellets() {
|
void Game::eatPellets() {
|
||||||
const auto pos = pacMan.positionInGrid();
|
const auto pos = pacMan.positionInGrid();
|
||||||
if(pellets.eatPelletAtPosition(pos)) {
|
if (pellets.eatPelletAtPosition(pos)) {
|
||||||
score.eatenPellets++;
|
score.eatenPellets++;
|
||||||
score.points += NORMAL_PELLET_POINTS;
|
score.points += NORMAL_PELLET_POINTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(superPellets.eatPelletAtPosition(pos)) {
|
if (superPellets.eatPelletAtPosition(pos)) {
|
||||||
score.eatenPellets++;
|
score.eatenPellets++;
|
||||||
score.points += POWER_PELLET_POINTS;
|
score.points += POWER_PELLET_POINTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processEvents(InputState & inputState) {
|
void Game::processEvents(InputState & inputState) {
|
||||||
|
|
12
lib/Game.hpp
12
lib/Game.hpp
|
@ -1,10 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Score.hpp"
|
|
||||||
#include "Board.hpp"
|
#include "Board.hpp"
|
||||||
#include "Canvas.hpp"
|
#include "Canvas.hpp"
|
||||||
|
#include "Ghost.hpp"
|
||||||
#include "PacMan.hpp"
|
#include "PacMan.hpp"
|
||||||
#include "Pellets.hpp"
|
#include "Pellets.hpp"
|
||||||
|
#include "Score.hpp"
|
||||||
#include "SuperPellets.hpp"
|
#include "SuperPellets.hpp"
|
||||||
|
|
||||||
class InputState;
|
class InputState;
|
||||||
|
@ -12,19 +13,24 @@ class InputState;
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class Canvas;
|
||||||
|
|
||||||
Canvas canvas;
|
Canvas canvas;
|
||||||
Board board;
|
Board board;
|
||||||
PacMan pacMan;
|
PacMan pacMan;
|
||||||
Pellets pellets;
|
Pellets pellets;
|
||||||
SuperPellets superPellets;
|
SuperPellets superPellets;
|
||||||
|
Blinky blinky;
|
||||||
|
Speedy speedy;
|
||||||
|
Inky inky;
|
||||||
|
Clyde clyde;
|
||||||
Score score;
|
Score score;
|
||||||
|
|
||||||
|
void step(std::chrono::milliseconds delta, InputState inputState);
|
||||||
void eatPellets();
|
void eatPellets();
|
||||||
|
|
||||||
void processEvents(InputState & inputState);
|
void processEvents(InputState & inputState);
|
||||||
|
|
||||||
[[nodiscard]] static auto now();
|
[[nodiscard]] static auto now();
|
||||||
|
|
45
lib/Ghost.cpp
Normal file
45
lib/Ghost.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "Ghost.hpp"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
Ghost::Ghost(Atlas::Ghost spritesSet, Position startingPosition, Position scatterTarget)
|
||||||
|
: spritesSet(spritesSet),
|
||||||
|
pos(startingPosition),
|
||||||
|
startingPosition(startingPosition),
|
||||||
|
scatterTarget(scatterTarget) {
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] PositionInt Ghost::currentSprite() const {
|
||||||
|
return Atlas::ghostSprite(spritesSet, direction, alternate_animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
Position Ghost::position() const {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
Position Ghost::positionInGrid() const {
|
||||||
|
return { std::round(pos.x), std::round(pos.y) };
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ghost::update(std::chrono::milliseconds time_delta, const Board & board) {
|
||||||
|
time += time_delta.count();
|
||||||
|
if (time >= 250) {
|
||||||
|
time = 0;
|
||||||
|
alternate_animation = !alternate_animation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Blinky::Blinky(const Board & board)
|
||||||
|
: Ghost(Atlas::Ghost::blinky, board.initialBlinkyPosition(), board.blinkyScatterTarget()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Speedy::Speedy(const Board & board)
|
||||||
|
: Ghost(Atlas::Ghost::speedy, board.initialSpeedyPosition(), board.speedyScatterTarget()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Inky::Inky(const Board & board)
|
||||||
|
: Ghost(Atlas::Ghost::inky, board.initialInkyPosition(), board.inkyScatterTarget()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Clyde::Clyde(const Board & board)
|
||||||
|
: Ghost(Atlas::Ghost::clyde, board.initialClydePosition(), board.clydeScatterTarget()) {
|
||||||
|
}
|
57
lib/Ghost.hpp
Normal file
57
lib/Ghost.hpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "Atlas.hpp"
|
||||||
|
#include "Board.hpp"
|
||||||
|
#include "Position.hpp"
|
||||||
|
|
||||||
|
class Ghost {
|
||||||
|
public:
|
||||||
|
enum class State {
|
||||||
|
Chase,
|
||||||
|
Scatter,
|
||||||
|
Freightened,
|
||||||
|
Eyes,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit Ghost(Atlas::Ghost spritesSet, Position startingPosition, Position scatterTarget);
|
||||||
|
|
||||||
|
[[nodiscard]] PositionInt currentSprite() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Position position() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Position positionInGrid() const;
|
||||||
|
|
||||||
|
void update(std::chrono::milliseconds time_delta, const Board & board);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Atlas::Ghost spritesSet;
|
||||||
|
Direction direction = Direction::NONE;
|
||||||
|
double time = 0;
|
||||||
|
bool alternate_animation = false;
|
||||||
|
State state = State::Chase;
|
||||||
|
Position pos;
|
||||||
|
Position startingPosition;
|
||||||
|
Position scatterTarget;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Blinky : public Ghost {
|
||||||
|
public:
|
||||||
|
explicit Blinky(const Board & board);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Speedy : public Ghost {
|
||||||
|
public:
|
||||||
|
explicit Speedy(const Board & board);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Inky : public Ghost {
|
||||||
|
public:
|
||||||
|
explicit Inky(const Board & board);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Clyde : public Ghost {
|
||||||
|
public:
|
||||||
|
explicit Clyde(const Board & board);
|
||||||
|
};
|
|
@ -37,12 +37,11 @@ void PacMan::setDirection(const InputState & state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacMan::updateAnimationPosition(std::chrono::milliseconds time_delta, bool paused) {
|
void PacMan::updateAnimationPosition(std::chrono::milliseconds time_delta, bool paused) {
|
||||||
if(paused) {
|
if (paused) {
|
||||||
pacManAnimation.pause();
|
pacManAnimation.pause();
|
||||||
}
|
} else {
|
||||||
else {
|
pacManAnimation.updateAnimationPosition(time_delta);
|
||||||
pacManAnimation.updateAnimationPosition(time_delta);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacMan::updateMazePosition(std::chrono::milliseconds time_delta, const Board & board) {
|
void PacMan::updateMazePosition(std::chrono::milliseconds time_delta, const Board & board) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ PositionInt PacManAnimation::animationFrame(Direction direction) const {
|
||||||
return down_animation[animation_position];
|
return down_animation[animation_position];
|
||||||
case Direction::NONE:
|
case Direction::NONE:
|
||||||
default:
|
default:
|
||||||
return closed;
|
return Atlas::pacman_closed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,6 @@ void PacManAnimation::updateAnimationPosition(std::chrono::milliseconds time_del
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacManAnimation::pause() {
|
void PacManAnimation::pause() {
|
||||||
animation_position = 0;
|
animation_position = 0;
|
||||||
animation_position_delta = 0;
|
animation_position_delta = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Atlas.hpp"
|
||||||
#include "Board.hpp"
|
#include "Board.hpp"
|
||||||
#include "Direction.hpp"
|
#include "Direction.hpp"
|
||||||
#include "InputState.hpp"
|
#include "InputState.hpp"
|
||||||
|
@ -14,21 +15,11 @@ public:
|
||||||
void updateAnimationPosition(std::chrono::milliseconds time_delta);
|
void updateAnimationPosition(std::chrono::milliseconds time_delta);
|
||||||
void pause();
|
void pause();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t animation_position = 0;
|
uint8_t animation_position = 0;
|
||||||
float animation_position_delta = 0.0;
|
float animation_position_delta = 0.0;
|
||||||
const PositionInt right_wide = { 0, 0 };
|
const PositionInt down_animation[4]{ Atlas::pacman_down_wide, Atlas::pacman_down_narrow, Atlas::pacman_closed, Atlas::pacman_down_narrow };
|
||||||
const PositionInt right_narrow = { 1, 0 };
|
const PositionInt left_animation[4]{ Atlas::pacman_left_wide, Atlas::pacman_left_narrow, Atlas::pacman_closed, Atlas::pacman_left_narrow };
|
||||||
const PositionInt closed = { 2, 0 };
|
const PositionInt right_animation[4]{ Atlas::pacman_right_wide, Atlas::pacman_right_narrow, Atlas::pacman_closed, Atlas::pacman_right_narrow };
|
||||||
const PositionInt left_narrow = { 3, 0 };
|
const PositionInt up_animation[4]{ Atlas::pacman_up_wide, Atlas::pacman_up_narrow, Atlas::pacman_closed, Atlas::pacman_up_narrow };
|
||||||
const PositionInt left_wide = { 4, 0 };
|
|
||||||
const PositionInt up_wide = { 5, 0 };
|
|
||||||
const PositionInt up_narrow = { 6, 0 };
|
|
||||||
const PositionInt down_wide = { 7, 0 };
|
|
||||||
const PositionInt down_narrow = { 8, 0 };
|
|
||||||
const PositionInt down_animation[4]{ down_wide, down_narrow, closed, down_narrow };
|
|
||||||
const PositionInt left_animation[4]{ left_wide, left_narrow, closed, left_narrow };
|
|
||||||
const PositionInt right_animation[4]{ right_wide, right_narrow, closed, right_narrow };
|
|
||||||
const PositionInt up_animation[4]{ up_wide, up_narrow, closed, up_narrow };
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct Score {
|
struct Score {
|
||||||
int lives = 0;
|
int lives = 0;
|
||||||
int points = 0;
|
int points = 0;
|
||||||
int eatenPellets = 0;
|
int eatenPellets = 0;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue