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) {
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(board[point.y][point.x]);
}

View file

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

View file

@ -59,7 +59,7 @@ Position Ghost::position() 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) {
@ -116,34 +116,48 @@ double Ghost::speed() const {
}
void Ghost::updateDirection(const Board & board) {
auto cell = positionInGrid();
if (cell == lastIntersection)
const auto current_grid_position = positionInGrid();
if (current_grid_position == last_grid_position)
return;
struct NewDirection {
struct Move {
Direction direction;
GridPosition position;
double distance;
Position position;
double distance = std::numeric_limits<double>::infinity();
};
auto [x, y] = cell;
std::array<NewDirection, 4> directions = { { NewDirection{ Direction::UP, { x, y - 1 }, 0 },
NewDirection{ Direction::LEFT, { x - 1, y }, 0 },
NewDirection{ Direction::DOWN, { x, y + 1 }, 0 },
NewDirection{ Direction::RIGHT, { x + 1, y }, 0 } } };
const Position target = this->target(board);
const Position current_position = { double(current_grid_position.x), double(current_grid_position.y) };
const auto [x, y] = current_position;
std::array<Move, 4> possible_moves = { { Move{ Direction::UP, { x, y - 1 } },
Move{ Direction::LEFT, { x - 1, y } },
Move{ Direction::DOWN, { x, y + 1 } },
Move{ Direction::RIGHT, { x + 1, y } } } };
for (auto && d : directions) {
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();
const Position target_position = target(board);
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;
});
lastIntersection = cell;
direction = it->direction;
last_grid_position = current_grid_position;
direction = optimal_move->direction;
}
Position Ghost::target(const Board & board) const {

View file

@ -15,7 +15,7 @@ Position PacMan::position() const {
}
GridPosition PacMan::positionInGrid() const {
return { int(std::round(pos.x)), int(std::round(pos.y)) };
return positionToGridPosition(pos);
}
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) {
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) {
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:
return GridPosition{ int(point.x) + 1, int(point.y) };
return Position{ std::floor(point.x + 1), std::floor(point.y) };
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:
return GridPosition{ int(point.x), int(point.y) + 1 };
return Position{ std::floor(point.x), std::floor(point.y + 1) };
case Direction::NONE:
default:
return positionInGrid();
return point;
}
};
auto canGo = [&](Direction desired_direction) {
return board.isWalkableForPacMan(positionToGridPosition(moveToPosition(pos, position_delta, desired_direction)));
};
// Handle teleport
if (pos.x >= COLUMNS - 1 && direction == Direction::RIGHT) {
pos.x = -1;
} else if (pos.x <= 0 && direction == Direction::LEFT) {
pos.x = COLUMNS;
} else if (board.isWalkableForPacMan(cellAtPosition(pos, position_delta, desired_direction))) {
} else if (canGo(desired_direction)) {
direction = desired_direction;
}
if (board.isWalkableForPacMan(cellAtPosition(pos, position_delta, direction))) {
if (canGo(direction)) {
switch (direction) {
case Direction::NONE:
break;

View file

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

View file

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

View file

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

View file

@ -10,31 +10,35 @@ struct Position {
};
struct GridPosition {
int x;
int y;
size_t x;
size_t y;
};
using Rect = sf::Rect<int>;
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;
}
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;
}
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;
}
inline bool operator!=(const Position & a, const Position & b) {
constexpr bool operator!=(const Position & a, const Position & 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);
}