Make files for ghosts

This commit is contained in:
Patricia Aas 2021-07-28 15:28:36 +02:00
parent fe04e7d03a
commit 5b2b0d8e73
13 changed files with 191 additions and 75 deletions

27
lib/Blinky.cpp Normal file
View file

@ -0,0 +1,27 @@
#include "Blinky.hpp"
namespace pacman {
Blinky::Blinky()
: Ghost(Atlas::Ghost::blinky, pacman::initialBlinkyPosition(), pacman::blinkyScatterTarget()) {
}
double Blinky::speed(const GameState & gameState) const {
if (state == State::Eyes)
return 2;
if (state == State::Frightened)
return 0.5;
return 0.75;
}
Position Blinky::target(const GameState & gameState) const {
if (state == State::Eyes)
return startingPosition;
if (isInPen())
return pacman::penDoorPosition();
return blinkyScatterTarget();
}
}

27
lib/Clyde.cpp Normal file
View file

@ -0,0 +1,27 @@
#include "Clyde.hpp"
namespace pacman {
Clyde::Clyde()
: Ghost(Atlas::Ghost::clyde, initialClydePosition(), clydeScatterTarget()) {
}
double Clyde::speed(const GameState & gameState) const {
if (state == State::Eyes)
return 2;
if (state == State::Frightened)
return 0.5;
return 0.75;
}
Position Clyde::target(const GameState & gameState) const {
if (state == State::Eyes)
return startingPosition;
if (isInPen())
return penDoorPosition();
return clydeScatterTarget();
}
}

View file

@ -73,10 +73,10 @@ void Game::step(std::chrono::milliseconds delta, InputState inputState) {
if (!gameState.pacMan.hasDirection()) if (!gameState.pacMan.hasDirection())
return; return;
gameState.blinky.update(delta); gameState.blinky.update(delta, gameState);
gameState.pinky.update(delta); gameState.pinky.update(delta, gameState);
gameState.inky.update(delta); gameState.inky.update(delta, gameState);
gameState.clyde.update(delta); gameState.clyde.update(delta, gameState);
checkCollision(gameState.blinky); checkCollision(gameState.blinky);
checkCollision(gameState.pinky); checkCollision(gameState.pinky);
@ -87,7 +87,7 @@ void Game::step(std::chrono::milliseconds delta, InputState inputState) {
eatPellets(); eatPellets();
} }
void Game::checkCollision(Ghost ghost) { void Game::checkCollision(Ghost & ghost) {
if (pacManDying() || ghost.isEyes()) if (pacManDying() || ghost.isEyes())
return; return;

View file

@ -7,8 +7,7 @@ namespace pacman {
Ghost::Ghost(Atlas::Ghost spritesSet, Position startingPosition, Position scatterTarget) Ghost::Ghost(Atlas::Ghost spritesSet, Position startingPosition, Position scatterTarget)
: spritesSet(spritesSet), : spritesSet(spritesSet),
pos(startingPosition), pos(startingPosition),
startingPosition(startingPosition), startingPosition(startingPosition) {
scatterTarget(scatterTarget) {
} }
void Ghost::frighten() { void Ghost::frighten() {
@ -62,7 +61,7 @@ GridPosition Ghost::positionInGrid() const {
return positionToGridPosition(pos); return positionToGridPosition(pos);
} }
void Ghost::update(std::chrono::milliseconds time_delta) { void Ghost::update(std::chrono::milliseconds time_delta, const GameState & gameState) {
if (state == State::Eyes && isInPen()) if (state == State::Eyes && isInPen())
state = State::Scatter; state = State::Scatter;
@ -73,17 +72,17 @@ void Ghost::update(std::chrono::milliseconds time_delta) {
} }
updateAnimation(time_delta); updateAnimation(time_delta);
updatePosition(time_delta); updatePosition(time_delta, gameState);
} }
bool Ghost::isInPen() const { bool Ghost::isInPen() const {
return pacman::isInPen(positionInGrid()); return pacman::isInPen(positionInGrid());
} }
void Ghost::updatePosition(std::chrono::milliseconds time_delta) { void Ghost::updatePosition(std::chrono::milliseconds time_delta, const GameState & gameState) {
updateDirection(); updateDirection(gameState);
double position_delta = (0.004 * time_delta.count()) * speed(); double position_delta = (0.004 * time_delta.count()) * speed(gameState);
switch (direction) { switch (direction) {
case Direction::NONE: case Direction::NONE:
@ -107,14 +106,6 @@ void Ghost::updatePosition(std::chrono::milliseconds time_delta) {
} }
} }
double Ghost::speed() const {
if (state == State::Eyes)
return 2;
if (state == State::Frightened)
return 0.5;
return 0.75;
}
/* /*
* Each time a ghost finds itself at an intersection, * Each time a ghost finds itself at an intersection,
* it picks a target position - the specific target depends on the state * it picks a target position - the specific target depends on the state
@ -131,7 +122,7 @@ double Ghost::speed() const {
* In the scatter state, each ghost tries to reach an unreachable position outside of the map. * In the scatter state, each ghost tries to reach an unreachable position outside of the map.
* This makes ghosts run in circle around the island at each of the 4 map corner. * This makes ghosts run in circle around the island at each of the 4 map corner.
*/ */
void Ghost::updateDirection() { void Ghost::updateDirection(const GameState & gameState) {
const auto current_grid_position = positionInGrid(); const auto current_grid_position = positionInGrid();
if (current_grid_position == last_grid_position) if (current_grid_position == last_grid_position)
return; return;
@ -149,7 +140,7 @@ void Ghost::updateDirection() {
Move{ Direction::DOWN, { x, y + 1 } }, Move{ Direction::DOWN, { x, y + 1 } },
Move{ Direction::RIGHT, { x + 1, y } } } }; Move{ Direction::RIGHT, { x + 1, y } } } };
const Position target_position = target(); const Position target_position = target(gameState);
for (auto & move : possible_moves) { for (auto & move : possible_moves) {
const bool invalid_position = (move.position.x < 0 || move.position.y < 0); const bool invalid_position = (move.position.x < 0 || move.position.y < 0);
@ -177,16 +168,6 @@ void Ghost::updateDirection() {
last_grid_position = current_grid_position; last_grid_position = current_grid_position;
} }
Position Ghost::target() const {
if (state == State::Eyes)
return startingPosition;
if (pacman::isInPen(positionInGrid()))
return pacman::penDoorPosition();
return scatterTarget;
}
void Ghost::updateAnimation(std::chrono::milliseconds time_delta) { void Ghost::updateAnimation(std::chrono::milliseconds time_delta) {
timeForAnimation += time_delta.count(); timeForAnimation += time_delta.count();
if (timeForAnimation >= 250) { if (timeForAnimation >= 250) {
@ -195,20 +176,4 @@ void Ghost::updateAnimation(std::chrono::milliseconds time_delta) {
} }
} }
Blinky::Blinky()
: Ghost(Atlas::Ghost::blinky, pacman::initialBlinkyPosition(), pacman::blinkyScatterTarget()) {
}
Pinky::Pinky()
: Ghost(Atlas::Ghost::speedy, pacman::initialSpeedyPosition(), pacman::speedyScatterTarget()) {
}
Inky::Inky()
: Ghost(Atlas::Ghost::inky, pacman::initialInkyPosition(), pacman::inkyScatterTarget()) {
}
Clyde::Clyde()
: Ghost(Atlas::Ghost::clyde, pacman::initialClydePosition(), pacman::clydeScatterTarget()) {
}
} // namespace pacman } // namespace pacman

27
lib/Inky.cpp Normal file
View file

@ -0,0 +1,27 @@
#include "Inky.hpp"
namespace pacman {
Inky::Inky()
: Ghost(Atlas::Ghost::inky, pacman::initialInkyPosition(), pacman::inkyScatterTarget()) {
}
double Inky::speed(const GameState & gameState) const {
if (state == State::Eyes)
return 2;
if (state == State::Frightened)
return 0.5;
return 0.75;
}
Position Inky::target(const GameState & gameState) const {
if (state == State::Eyes)
return startingPosition;
if (isInPen())
return pacman::penDoorPosition();
return inkyScatterTarget();
}
}

27
lib/Pinky.cpp Normal file
View file

@ -0,0 +1,27 @@
#include "Pinky.hpp"
namespace pacman {
Pinky::Pinky()
: Ghost(Atlas::Ghost::speedy, pacman::initialSpeedyPosition(), pacman::speedyScatterTarget()) {
}
double Pinky::speed(const GameState & gameState) const {
if (state == State::Eyes)
return 2;
if (state == State::Frightened)
return 0.5;
return 0.75;
}
Position Pinky::target(const GameState & gameState) const {
if (state == State::Eyes)
return startingPosition;
if (isInPen())
return pacman::penDoorPosition();
return speedyScatterTarget();
}
}

14
lib/include/Blinky.hpp Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "Ghost.hpp"
namespace pacman {
class Blinky : public Ghost {
public:
explicit Blinky();
[[nodiscard]] double speed(const GameState & gameState) const override;
[[nodiscard]] Position target(const GameState & gameState) const override;
};
} // namespace pacman

14
lib/include/Clyde.hpp Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "Ghost.hpp"
namespace pacman {
class Clyde : public Ghost {
public:
explicit Clyde();
[[nodiscard]] double speed(const GameState & gameState) const override;
[[nodiscard]] Position target(const GameState & gameState) const override;
};
} // namespace pacman

View file

@ -20,7 +20,7 @@ private:
void step(std::chrono::milliseconds delta, InputState inputState); void step(std::chrono::milliseconds delta, InputState inputState);
void eatPellets(); void eatPellets();
void processEvents(InputState & inputState); void processEvents(InputState & inputState);
void checkCollision(Ghost ghost); void checkCollision(Ghost & ghost);
void killPacMan(); void killPacMan();
bool pacManDying() const; bool pacManDying() const;
void handleDeathAnimation(std::chrono::milliseconds delta); void handleDeathAnimation(std::chrono::milliseconds delta);

View file

@ -1,8 +1,12 @@
#pragma once #pragma once
#include "Blinky.hpp"
#include "Clyde.hpp"
#include "Ghost.hpp" #include "Ghost.hpp"
#include "Inky.hpp"
#include "PacMan.hpp" #include "PacMan.hpp"
#include "Pellets.hpp" #include "Pellets.hpp"
#include "Pinky.hpp"
#include "Score.hpp" #include "Score.hpp"
#include "SuperPellets.hpp" #include "SuperPellets.hpp"

View file

@ -8,6 +8,8 @@
namespace pacman { namespace pacman {
class GameState;
class Ghost { class Ghost {
public: public:
enum class State { enum class State {
@ -25,7 +27,7 @@ public:
[[nodiscard]] GridPosition positionInGrid() const; [[nodiscard]] GridPosition positionInGrid() const;
void update(std::chrono::milliseconds time_delta); void update(std::chrono::milliseconds time_delta, const GameState & gameState);
void frighten(); void frighten();
void die(); void die();
[[nodiscard]] bool isFrightened() const; [[nodiscard]] bool isFrightened() const;
@ -33,13 +35,15 @@ public:
void reset(); void reset();
private: private:
[[nodiscard]] double speed() const;
void updateAnimation(std::chrono::milliseconds time_delta); void updateAnimation(std::chrono::milliseconds time_delta);
void updatePosition(std::chrono::milliseconds time_delta); void updatePosition(std::chrono::milliseconds time_delta, const GameState & gameState);
void updateDirection(); void updateDirection(const GameState & gameState);
[[nodiscard]] Position target() const;
protected: protected:
[[nodiscard]] virtual double speed(const GameState & gameState) const = 0;
[[nodiscard]] virtual Position target(const GameState & gameState) const = 0;
Atlas::Ghost spritesSet; Atlas::Ghost spritesSet;
Direction direction = Direction::NONE; Direction direction = Direction::NONE;
double timeForAnimation = 0; double timeForAnimation = 0;
@ -49,29 +53,8 @@ protected:
int timeChase = 0; int timeChase = 0;
Position pos; Position pos;
Position startingPosition; Position startingPosition;
Position scatterTarget;
GridPosition last_grid_position = { 0, 0 }; GridPosition last_grid_position = { 0, 0 };
[[nodiscard]] bool isInPen() const; [[nodiscard]] bool isInPen() const;
}; };
class Blinky : public Ghost {
public:
explicit Blinky();
};
class Pinky : public Ghost {
public:
explicit Pinky();
};
class Inky : public Ghost {
public:
explicit Inky();
};
class Clyde : public Ghost {
public:
explicit Clyde();
};
} // namespace pacman } // namespace pacman

14
lib/include/Inky.hpp Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "Ghost.hpp"
namespace pacman {
class Inky : public Ghost {
public:
explicit Inky();
[[nodiscard]] double speed(const GameState & gameState) const override;
[[nodiscard]] Position target(const GameState & gameState) const override;
};
} // namespace pacman

14
lib/include/Pinky.hpp Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "Ghost.hpp"
namespace pacman {
class Pinky : public Ghost {
public:
explicit Pinky();
[[nodiscard]] double speed(const GameState & gameState) const override;
[[nodiscard]] Position target(const GameState & gameState) const override;
};
} // namespace pacman