Fixes for ghost movement where they would occationally exit the stage when cornered. Closes #25
This commit is contained in:
parent
60b3cdeb40
commit
613831f1c0
9 changed files with 29 additions and 26 deletions
|
@ -54,7 +54,7 @@ constexpr std::array<std::array<int, COLUMNS>, ROWS> board = {{
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
static Cell cellAtPosition(GridPosition point) {
|
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::wall;
|
||||||
return Cell(board[point.y][point.x]);
|
return Cell(board[point.y][point.x]);
|
||||||
}
|
}
|
||||||
|
@ -64,10 +64,10 @@ bool isWalkableForPacMan(GridPosition point) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWalkableForGhost(GridPosition point, GridPosition origin, bool isEyes) {
|
bool isWalkableForGhost(GridPosition point, GridPosition origin, bool isEyes) {
|
||||||
Cell cell = cellAtPosition(point);
|
const Cell cell = cellAtPosition(point);
|
||||||
if (cell == Cell::wall)
|
if (cell == Cell::wall)
|
||||||
return false;
|
return false;
|
||||||
return isEyes || (isInPen(origin) || !isInPen(point));
|
return isEyes || isInPen(origin) || !isInPen(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInPen(GridPosition point) {
|
bool isInPen(GridPosition point) {
|
||||||
|
|
|
@ -95,6 +95,9 @@ void Ghost::updatePosition(std::chrono::milliseconds time_delta, const GameState
|
||||||
|
|
||||||
double position_delta = (0.004 * time_delta.count()) * speed(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) {
|
switch (direction) {
|
||||||
case Direction::NONE:
|
case Direction::NONE:
|
||||||
break;
|
break;
|
||||||
|
@ -119,6 +122,10 @@ void Ghost::updatePosition(std::chrono::milliseconds time_delta, const GameState
|
||||||
if (isPortal(positionInGrid(), direction)) {
|
if (isPortal(positionInGrid(), direction)) {
|
||||||
pos = gridPositionToPosition(teleport(positionInGrid()));
|
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);
|
const Position target_position = target(gameState);
|
||||||
|
|
||||||
for (auto & move : possible_moves) {
|
for (auto & move : possible_moves) {
|
||||||
|
|
||||||
if (isPortal(current_grid_position, move.direction))
|
if (isPortal(current_grid_position, move.direction))
|
||||||
move.position = gridPositionToPosition(teleport(current_grid_position));
|
move.position = gridPositionToPosition(teleport(current_grid_position));
|
||||||
|
|
||||||
|
@ -172,7 +178,7 @@ void Ghost::updateDirection(const GameState & gameState) {
|
||||||
if (opposite_direction)
|
if (opposite_direction)
|
||||||
continue;
|
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());
|
const bool can_walk = isWalkableForGhost(grid_position, current_grid_position, isEyes());
|
||||||
if (!can_walk)
|
if (!can_walk)
|
||||||
continue;
|
continue;
|
||||||
|
@ -184,7 +190,7 @@ void Ghost::updateDirection(const GameState & gameState) {
|
||||||
return a.distance_to_target < b.distance_to_target;
|
return a.distance_to_target < b.distance_to_target;
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto& move = *optimal_move;
|
const auto & move = *optimal_move;
|
||||||
direction = move.direction;
|
direction = move.direction;
|
||||||
last_grid_position = current_grid_position;
|
last_grid_position = current_grid_position;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// And selects a point on the line crossing blinky and this position that is at twice that distance
|
||||||
// away from blinky
|
// away from blinky
|
||||||
targetPosition.x += size_t((targetPosition.x - blinkyPosition.x) / distanceBetweenBlinkyAndTarget) * 2;
|
targetPosition.x += int64_t((targetPosition.x - blinkyPosition.x) / distanceBetweenBlinkyAndTarget) * 2;
|
||||||
targetPosition.y += size_t((targetPosition.y - blinkyPosition.y) / distanceBetweenBlinkyAndTarget) * 2;
|
targetPosition.y += int64_t((targetPosition.y - blinkyPosition.y) / distanceBetweenBlinkyAndTarget) * 2;
|
||||||
|
|
||||||
return gridPositionToPosition(targetPosition);
|
return gridPositionToPosition(targetPosition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,13 +64,13 @@ void PacMan::updateMazePosition(std::chrono::milliseconds time_delta) {
|
||||||
auto moveToPosition = [position_delta](Position point, Direction move_direction) {
|
auto moveToPosition = [position_delta](Position point, Direction move_direction) {
|
||||||
switch (move_direction) {
|
switch (move_direction) {
|
||||||
case Direction::LEFT:
|
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:
|
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:
|
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:
|
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:
|
case Direction::NONE:
|
||||||
default:
|
default:
|
||||||
return positionToGridPosition(point);
|
return positionToGridPosition(point);
|
||||||
|
|
|
@ -32,15 +32,13 @@ void PacManAnimation::updateAnimationPosition(std::chrono::milliseconds time_del
|
||||||
return;
|
return;
|
||||||
|
|
||||||
animation_position_delta += (0.02) * double(time_delta.count());
|
animation_position_delta += (0.02) * double(time_delta.count());
|
||||||
|
animation_position = int64_t(animation_position + animation_position_delta);
|
||||||
animation_position = int(animation_position + animation_position_delta);
|
|
||||||
|
|
||||||
if (!dead)
|
if (!dead)
|
||||||
animation_position = animation_position % 4;
|
animation_position = animation_position % 4;
|
||||||
|
|
||||||
if(animation_position_delta > 1)
|
if(animation_position_delta > 1)
|
||||||
animation_position_delta = animation_position_delta - 1;
|
animation_position_delta = animation_position_delta - 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacManAnimation::pause() {
|
void PacManAnimation::pause() {
|
||||||
|
|
|
@ -47,8 +47,8 @@ constexpr GridPosition eyeSprite(Direction direction) {
|
||||||
|
|
||||||
constexpr GridPosition ghostSprite(Ghost ghost, Direction direction, bool alternative) {
|
constexpr GridPosition ghostSprite(Ghost ghost, Direction direction, bool alternative) {
|
||||||
assert(ghost >= Ghost::blinky && ghost <= Ghost::clyde && "Invalid Ghost");
|
assert(ghost >= Ghost::blinky && ghost <= Ghost::clyde && "Invalid Ghost");
|
||||||
auto y = static_cast<size_t>(ghost);
|
auto y = static_cast<int64_t>(ghost);
|
||||||
size_t x = 0;
|
int64_t x = 0;
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case Direction::RIGHT:
|
case Direction::RIGHT:
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
|
@ -18,8 +18,7 @@ std::vector<GridPosition> initialPelletPositions();
|
||||||
|
|
||||||
std::vector<GridPosition> initialSuperPelletPositions();
|
std::vector<GridPosition> initialSuperPelletPositions();
|
||||||
|
|
||||||
inline Position penDoorPosition() {
|
inline Position penDoorPosition() { return { 13, 11 }; }
|
||||||
return { 13, 11 }; }
|
inline Position initialPacManPosition() { return { 13.5, 23 }; }
|
||||||
inline Position initialPacManPosition() { return { 13.5, 23 }; }
|
|
||||||
|
|
||||||
} // namespace pacman
|
} // namespace pacman
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
void pause();
|
void pause();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t animation_position = 0;
|
int64_t animation_position = 0;
|
||||||
double animation_position_delta = 0.0;
|
double animation_position_delta = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,13 @@ struct Position {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GridPosition {
|
struct GridPosition {
|
||||||
size_t x;
|
int64_t x;
|
||||||
size_t y;
|
int64_t y;
|
||||||
constexpr GridPosition(size_t x, size_t y) : x(x), y(y) {}
|
constexpr GridPosition(int64_t x, int64_t y) : x(x), y(y) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline GridPosition positionToGridPosition(Position pos) {
|
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) {
|
inline Position gridPositionToPosition(GridPosition pos) {
|
||||||
|
|
Loading…
Reference in a new issue