Fixes for ghost movement where they would occationally exit the stage when cornered. Closes #25

This commit is contained in:
Ólafur Waage 2021-09-09 10:56:29 +02:00
parent 60b3cdeb40
commit 613831f1c0
9 changed files with 29 additions and 26 deletions

View File

@ -54,7 +54,7 @@ constexpr std::array<std::array<int, COLUMNS>, ROWS> board = {{
// clang-format on
static Cell cellAtPosition(GridPosition point) {
if (point.x >= COLUMNS || point.y >= ROWS)
if (point.x < 0 || point.x >= COLUMNS || point.y < 0 || point.y >= ROWS)
return Cell::wall;
return Cell(board[point.y][point.x]);
}
@ -64,10 +64,10 @@ bool isWalkableForPacMan(GridPosition point) {
}
bool isWalkableForGhost(GridPosition point, GridPosition origin, bool isEyes) {
Cell cell = cellAtPosition(point);
const Cell cell = cellAtPosition(point);
if (cell == Cell::wall)
return false;
return isEyes || (isInPen(origin) || !isInPen(point));
return isEyes || isInPen(origin) || !isInPen(point);
}
bool isInPen(GridPosition point) {

View File

@ -95,6 +95,9 @@ void Ghost::updatePosition(std::chrono::milliseconds time_delta, const GameState
double position_delta = (0.004 * time_delta.count()) * speed(gameState);
const auto old_position = pos;
const GridPosition old_grid_position = positionToGridPosition(old_position);
switch (direction) {
case Direction::NONE:
break;
@ -119,6 +122,10 @@ void Ghost::updatePosition(std::chrono::milliseconds time_delta, const GameState
if (isPortal(positionInGrid(), direction)) {
pos = gridPositionToPosition(teleport(positionInGrid()));
}
else if (!isWalkableForGhost(positionInGrid(), old_grid_position, isEyes())) {
pos = old_position;
direction = oppositeDirection(direction);
}
}
/*
@ -160,7 +167,6 @@ void Ghost::updateDirection(const GameState & gameState) {
const Position target_position = target(gameState);
for (auto & move : possible_moves) {
if (isPortal(current_grid_position, move.direction))
move.position = gridPositionToPosition(teleport(current_grid_position));
@ -172,7 +178,7 @@ void Ghost::updateDirection(const GameState & gameState) {
if (opposite_direction)
continue;
const GridPosition grid_position = { size_t(move.position.x), size_t(move.position.y) };
const GridPosition grid_position = { int64_t(move.position.x), int64_t(move.position.y) };
const bool can_walk = isWalkableForGhost(grid_position, current_grid_position, isEyes());
if (!can_walk)
continue;
@ -184,7 +190,7 @@ void Ghost::updateDirection(const GameState & gameState) {
return a.distance_to_target < b.distance_to_target;
});
const auto& move = *optimal_move;
const auto & move = *optimal_move;
direction = move.direction;
last_grid_position = current_grid_position;
}

View File

@ -53,8 +53,8 @@ Position Inky::target(const GameState & gameState) const {
// And selects a point on the line crossing blinky and this position that is at twice that distance
// away from blinky
targetPosition.x += size_t((targetPosition.x - blinkyPosition.x) / distanceBetweenBlinkyAndTarget) * 2;
targetPosition.y += size_t((targetPosition.y - blinkyPosition.y) / distanceBetweenBlinkyAndTarget) * 2;
targetPosition.x += int64_t((targetPosition.x - blinkyPosition.x) / distanceBetweenBlinkyAndTarget) * 2;
targetPosition.y += int64_t((targetPosition.y - blinkyPosition.y) / distanceBetweenBlinkyAndTarget) * 2;
return gridPositionToPosition(targetPosition);
}

View File

@ -64,13 +64,13 @@ void PacMan::updateMazePosition(std::chrono::milliseconds time_delta) {
auto moveToPosition = [position_delta](Position point, Direction move_direction) {
switch (move_direction) {
case Direction::LEFT:
return GridPosition{ std::size_t(point.x - position_delta), std::size_t(point.y) };
return GridPosition{ int64_t(point.x - position_delta), int64_t(point.y) };
case Direction::RIGHT:
return GridPosition{ std::size_t(point.x + pacman_size), std::size_t(point.y) };
return GridPosition{ int64_t(point.x + pacman_size), int64_t(point.y) };
case Direction::UP:
return GridPosition{ std::size_t(point.x), std::size_t(point.y - position_delta) };
return GridPosition{ int64_t(point.x), int64_t(point.y - position_delta) };
case Direction::DOWN:
return GridPosition{ std::size_t(point.x), std::size_t(point.y + pacman_size) };
return GridPosition{ int64_t(point.x), int64_t(point.y + pacman_size) };
case Direction::NONE:
default:
return positionToGridPosition(point);

View File

@ -32,15 +32,13 @@ void PacManAnimation::updateAnimationPosition(std::chrono::milliseconds time_del
return;
animation_position_delta += (0.02) * double(time_delta.count());
animation_position = int(animation_position + animation_position_delta);
animation_position = int64_t(animation_position + animation_position_delta);
if (!dead)
animation_position = animation_position % 4;
if(animation_position_delta > 1)
animation_position_delta = animation_position_delta - 1;
}
void PacManAnimation::pause() {

View File

@ -47,8 +47,8 @@ constexpr GridPosition eyeSprite(Direction direction) {
constexpr GridPosition ghostSprite(Ghost ghost, Direction direction, bool alternative) {
assert(ghost >= Ghost::blinky && ghost <= Ghost::clyde && "Invalid Ghost");
auto y = static_cast<size_t>(ghost);
size_t x = 0;
auto y = static_cast<int64_t>(ghost);
int64_t x = 0;
switch (direction) {
case Direction::RIGHT:
x = 0;

View File

@ -18,8 +18,7 @@ std::vector<GridPosition> initialPelletPositions();
std::vector<GridPosition> initialSuperPelletPositions();
inline Position penDoorPosition() {
return { 13, 11 }; }
inline Position initialPacManPosition() { return { 13.5, 23 }; }
inline Position penDoorPosition() { return { 13, 11 }; }
inline Position initialPacManPosition() { return { 13.5, 23 }; }
} // namespace pacman
} // namespace pacman

View File

@ -18,7 +18,7 @@ public:
void pause();
private:
size_t animation_position = 0;
int64_t animation_position = 0;
double animation_position_delta = 0.0;
};

View File

@ -10,13 +10,13 @@ struct Position {
};
struct GridPosition {
size_t x;
size_t y;
constexpr GridPosition(size_t x, size_t y) : x(x), y(y) {}
int64_t x;
int64_t y;
constexpr GridPosition(int64_t x, int64_t y) : x(x), y(y) {}
};
inline GridPosition positionToGridPosition(Position pos) {
return { size_t(std::round(pos.x)), size_t(std::round(pos.y)) };
return { int64_t(std::round(pos.x)), int64_t(std::round(pos.y)) };
}
inline Position gridPositionToPosition(GridPosition pos) {