Move over to size_t

This commit is contained in:
Patricia Aas 2021-07-06 12:35:23 +02:00
parent 510e12a921
commit 30f69464dd
8 changed files with 77 additions and 54 deletions

View file

@ -63,7 +63,7 @@ bool Board::isInPen(GridPosition point) {
} }
Board::Cell Board::cellAtPosition(GridPosition point) { Board::Cell Board::cellAtPosition(GridPosition point) {
if (point.x < 0 || point.x >= int(COLUMNS) || point.y < 0 || point.y >= int(ROWS)) if (point.x >= COLUMNS || point.y >= ROWS)
return Cell::wall; return Cell::wall;
return Cell(board[point.y][point.x]); return Cell(board[point.y][point.x]);
} }

View file

@ -101,12 +101,13 @@ void Canvas::renderScore(int score) {
void Canvas::renderLives(int lives) { void Canvas::renderLives(int lives) {
constexpr GridPosition liveSprite = Atlas::pacman_left_narrow; constexpr GridPosition liveSprite = Atlas::pacman_left_narrow;
const int x = LEFT_MARGIN + MAZE_WIDTH + LEFT_MARGIN; const size_t x = LEFT_MARGIN + MAZE_WIDTH + LEFT_MARGIN;
const int y = maze_texture.getSize().y; const size_t 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++) {
GridPosition pos{ x + i * pacmanSprite.getTextureRect().width, y }; size_t life_position = i * pacmanSprite.getTextureRect().width;
GridPosition pos{ x + life_position, y };
pacmanSprite.setPosition(pos.x, pos.y); pacmanSprite.setPosition(pos.x, pos.y);
window.draw(pacmanSprite); window.draw(pacmanSprite);
} }
@ -119,8 +120,8 @@ Rect Canvas::windowDimensions() {
Sprite Canvas::getSprite(GridPosition coordinate) const { Sprite Canvas::getSprite(GridPosition coordinate) const {
sf::Sprite sprite; sf::Sprite sprite;
sprite.setTexture(sprites_texture); sprite.setTexture(sprites_texture);
sprite.setTextureRect(sf::IntRect{ coordinate.x * DEFAULT_SPRITE_WIDTH, sprite.setTextureRect(sf::IntRect{ int(coordinate.x * DEFAULT_SPRITE_WIDTH),
coordinate.y * DEFAULT_SPRITE_HEIGHT, int(coordinate.y * DEFAULT_SPRITE_HEIGHT),
DEFAULT_SPRITE_WIDTH, DEFAULT_SPRITE_WIDTH,
DEFAULT_SPRITE_HEIGHT }); DEFAULT_SPRITE_HEIGHT });
sprite.scale(0.5, 0.5); sprite.scale(0.5, 0.5);

View file

@ -59,7 +59,7 @@ Position Ghost::position() const {
} }
GridPosition Ghost::positionInGrid() const { GridPosition Ghost::positionInGrid() const {
return { int(std::round(pos.x)), int(std::round(pos.y)) }; return positionToGridPosition(pos);
} }
void Ghost::update(std::chrono::milliseconds time_delta, const Board & board) { void Ghost::update(std::chrono::milliseconds time_delta, const Board & board) {
@ -116,34 +116,48 @@ double Ghost::speed() const {
} }
void Ghost::updateDirection(const Board & board) { void Ghost::updateDirection(const Board & board) {
auto cell = positionInGrid(); const auto current_grid_position = positionInGrid();
if (cell == lastIntersection) if (current_grid_position == last_grid_position)
return; return;
struct NewDirection { struct Move {
Direction direction; Direction direction;
GridPosition position; Position position;
double distance; double distance = std::numeric_limits<double>::infinity();
}; };
auto [x, y] = cell; const Position current_position = { double(current_grid_position.x), double(current_grid_position.y) };
std::array<NewDirection, 4> directions = { { NewDirection{ Direction::UP, { x, y - 1 }, 0 }, const auto [x, y] = current_position;
NewDirection{ Direction::LEFT, { x - 1, y }, 0 }, std::array<Move, 4> possible_moves = { { Move{ Direction::UP, { x, y - 1 } },
NewDirection{ Direction::DOWN, { x, y + 1 }, 0 }, Move{ Direction::LEFT, { x - 1, y } },
NewDirection{ Direction::RIGHT, { x + 1, y }, 0 } } }; Move{ Direction::DOWN, { x, y + 1 } },
const Position target = this->target(board); Move{ Direction::RIGHT, { x + 1, y } } } };
for (auto && d : directions) { const Position target_position = target(board);
d.distance = (d.direction != oppositeDirection(direction) && board.isWalkableForGost(d.position, cell, state == State::Eyes)) ? std::hypot(d.position.x - target.x, d.position.y - target.y)
: std::numeric_limits<double>::infinity(); for (auto & move : possible_moves) {
const bool invalid_position = (move.position.x < 0 || move.position.y < 0);
if (invalid_position)
continue;
const bool opposite_direction = (move.direction == oppositeDirection(direction));
if (opposite_direction)
continue;
const GridPosition grid_position = {size_t(move.position.x), size_t(move.position.y)};
const bool can_walk = board.isWalkableForGost(grid_position, current_grid_position, isEyes());
if (!can_walk)
continue;
move.distance = std::hypot(move.position.x - target_position.x, move.position.y - target_position.y);
} }
auto it = std::min_element(directions.begin(), directions.end(), [](const auto & a, const auto & b) { const auto optimal_move = std::min_element(possible_moves.begin(), possible_moves.end(), [](const auto & a, const auto & b) {
return a.distance < b.distance; return a.distance < b.distance;
}); });
lastIntersection = cell; last_grid_position = current_grid_position;
direction = it->direction; direction = optimal_move->direction;
} }
Position Ghost::target(const Board & board) const { Position Ghost::target(const Board & board) const {

View file

@ -15,7 +15,7 @@ Position PacMan::position() const {
} }
GridPosition PacMan::positionInGrid() const { GridPosition PacMan::positionInGrid() const {
return { int(std::round(pos.x)), int(std::round(pos.y)) }; return positionToGridPosition(pos);
} }
void PacMan::eat() { void PacMan::eat() {
@ -63,34 +63,38 @@ void PacMan::updateAnimationPosition(std::chrono::milliseconds time_delta, bool
} }
void PacMan::updateMazePosition(std::chrono::milliseconds time_delta, const Board & board) { void PacMan::updateMazePosition(std::chrono::milliseconds time_delta, const Board & board) {
double position_delta = 0.004 * time_delta.count(); const double position_delta = 0.004 * time_delta.count();
auto cellAtPosition = [&](Position point, double position_delta, Direction direction) { auto moveToPosition = [&](Position point, double position_delta, Direction direction) {
switch (direction) { switch (direction) {
case Direction::LEFT: case Direction::LEFT:
return GridPosition{ int(point.x - position_delta), int(point.y) }; return Position{ std::floor(point.x - position_delta), std::floor(point.y) };
case Direction::RIGHT: case Direction::RIGHT:
return GridPosition{ int(point.x) + 1, int(point.y) }; return Position{ std::floor(point.x + 1), std::floor(point.y) };
case Direction::UP: case Direction::UP:
return GridPosition{ int(point.x), int(point.y - position_delta) }; return Position{ std::floor(point.x), std::floor(point.y - position_delta) };
case Direction::DOWN: case Direction::DOWN:
return GridPosition{ int(point.x), int(point.y) + 1 }; return Position{ std::floor(point.x), std::floor(point.y + 1) };
case Direction::NONE: case Direction::NONE:
default: default:
return positionInGrid(); return point;
} }
}; };
auto canGo = [&](Direction desired_direction) {
return board.isWalkableForPacMan(positionToGridPosition(moveToPosition(pos, position_delta, desired_direction)));
};
// Handle teleport // Handle teleport
if (pos.x >= COLUMNS - 1 && direction == Direction::RIGHT) { if (pos.x >= COLUMNS - 1 && direction == Direction::RIGHT) {
pos.x = -1; pos.x = -1;
} else if (pos.x <= 0 && direction == Direction::LEFT) { } else if (pos.x <= 0 && direction == Direction::LEFT) {
pos.x = COLUMNS; pos.x = COLUMNS;
} else if (board.isWalkableForPacMan(cellAtPosition(pos, position_delta, desired_direction))) { } else if (canGo(desired_direction)) {
direction = desired_direction; direction = desired_direction;
} }
if (board.isWalkableForPacMan(cellAtPosition(pos, position_delta, direction))) { if (canGo(direction)) {
switch (direction) { switch (direction) {
case Direction::NONE: case Direction::NONE:
break; break;

View file

@ -8,7 +8,7 @@
namespace pacman::Atlas { namespace pacman::Atlas {
enum class Ghost { enum class Ghost : unsigned int {
blinky = 2, blinky = 2,
speedy = 3, speedy = 3,
inky = 4, inky = 4,
@ -31,7 +31,7 @@ constexpr GridPosition ghost_white_frightened = { 2, 7 };
constexpr GridPosition ghost_white_frightened2 = { 3, 7 }; constexpr GridPosition ghost_white_frightened2 = { 3, 7 };
constexpr GridPosition eyeSprite(Direction direction) { constexpr GridPosition eyeSprite(Direction direction) {
int x = 0; size_t x = 0;
switch (direction) { switch (direction) {
case Direction::RIGHT: case Direction::RIGHT:
x = 0; x = 0;
@ -54,8 +54,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");
int y = static_cast<int>(ghost); size_t y = static_cast<size_t>(ghost);
int x = 0; size_t x = 0;
switch (direction) { switch (direction) {
case Direction::RIGHT: case Direction::RIGHT:
x = 0; x = 0;

View file

@ -19,14 +19,14 @@ public:
std::optional<sf::Event> pollEvent(); std::optional<sf::Event> pollEvent();
private: private:
static constexpr int16_t LEFT_MARGIN = 40; static constexpr uint16_t LEFT_MARGIN = 40;
static constexpr int16_t TOP_MARGIN = 40; static constexpr uint16_t TOP_MARGIN = 40;
static constexpr int16_t BOTTOM_MARGIN = 40; static constexpr uint16_t BOTTOM_MARGIN = 40;
static constexpr int16_t MAZE_WIDTH = 448; static constexpr uint16_t MAZE_WIDTH = 448;
static constexpr int16_t MAZE_HEIGHT = 496; static constexpr uint16_t MAZE_HEIGHT = 496;
static constexpr int16_t SCORE_WIDTH = 200; static constexpr uint16_t SCORE_WIDTH = 200;
static constexpr int16_t DEFAULT_SPRITE_WIDTH = 32; static constexpr uint16_t DEFAULT_SPRITE_WIDTH = 32;
static constexpr int16_t DEFAULT_SPRITE_HEIGHT = 32; static constexpr uint16_t DEFAULT_SPRITE_HEIGHT = 32;
void clear(); void clear();
void render(); void render();

View file

@ -50,7 +50,7 @@ protected:
Position pos; Position pos;
Position startingPosition; Position startingPosition;
Position scatterTarget; Position scatterTarget;
GridPosition lastIntersection = { -1, -1 }; GridPosition last_grid_position = { 0, 0 };
bool isInPen(const Board & board) const; bool isInPen(const Board & board) const;
}; };

View file

@ -10,31 +10,35 @@ struct Position {
}; };
struct GridPosition { struct GridPosition {
int x; size_t x;
int y; size_t y;
}; };
using Rect = sf::Rect<int>; using Rect = sf::Rect<int>;
using Sprite = sf::Sprite; using Sprite = sf::Sprite;
inline bool operator==(const GridPosition & a, const GridPosition & b) { inline GridPosition positionToGridPosition(Position pos) {
return { size_t(std::round(pos.x)), size_t(std::round(pos.y)) };
}
constexpr bool operator==(const GridPosition & a, const GridPosition & b) {
return a.x == b.x && a.y == b.y; return a.x == b.x && a.y == b.y;
} }
inline bool operator==(const GridPosition & a, const Position & b) { constexpr bool operator==(const GridPosition & a, const Position & b) {
return a.x == b.x && a.y == b.y; return a.x == b.x && a.y == b.y;
} }
inline bool operator==(const Position & a, const Position & b) { constexpr bool operator==(const Position & a, const Position & b) {
return a.x == b.x && a.y == b.y; return a.x == b.x && a.y == b.y;
} }
inline bool operator!=(const Position & a, const Position & b) { constexpr bool operator!=(const Position & a, const Position & b) {
return !(a == b); return !(a == b);
} }
inline bool operator!=(const GridPosition & a, const GridPosition & b) { constexpr bool operator!=(const GridPosition & a, const GridPosition & b) {
return !(a == b); return !(a == b);
} }