IMPLEMENTATION NOTES / C++ / SFML
Pac-Man (SFML Remake)
A Pac-Man remake in C++ and SFML, built to learn the game loop, collision, ghost AI, and sprite drawing.
IMPLEMENTATION / EQUATIONS & SOURCE
Follow the inputs through the code.
Read each section as purpose → equation → actual source. Snippets are excerpts of the working implementation, not standalone programs. Follow the source link for surrounding context.
01 / Ghosts select a next step, not an entire path
After excluding walls and reverse movement, compare each candidate’s squared distance to the target. No square root is needed for ranking. This chooses a local direction at junctions rather than computing an A* route. The <= test lets later candidates win ties. Distance takes integer arguments, so fractional coordinates are truncated before comparison.
D²(q,t) = (qx−tx)² + (qy−ty)²
nextDirection = arg min D²(candidate,target)float Distance(int x, int y, int x1, int y1)
{
return ((x - x1) * (x - x1)) + ((y - y1) * (y - y1));
}
// the original game didnt use a pathfinding algorithm
// simple distance comparisons are fine enough
Dir GetShortestDir(const std::vector<Dir>& squares, const Ghost& ghost, sf::Vector2f target)
{
int min_dist = 20000000;
Dir min_dir = NONE;
if (squares.size() == 0)
printf("EMPTY\n");
for (auto dir : squares) {
sf::Vector2f square = ghost.pos + dir_addition[dir];
float dir_dist = Distance(target.x, target.y, square.x, square.y);
if (dir_dist <= min_dist) {
min_dir = dir;
min_dist = dir_dist;
}
}
return min_dir;
}02 / Different target rules create different behavior
Red targets the player; pink targets four tiles ahead; blue reflects red’s position about the point two tiles ahead of the player. Orange switches to (0,31) when squared player distance is below 64. They share direction selection but use separate target rules.
tred = player
tpink = player + 4·direction
a = player + 2·direction, tblue = 2a − red
torange = corner if D² < 64, otherwise playerThese equations describe the public source, not every rule of the original arcade game or a claim of a newly invented algorithm.
sf::Vector2f BlinkyUpdate(Ghost& ghost)
{
return gState.player->pos;
}
sf::Vector2f PinkyUpdate(Ghost& ghost)
{
return gState.player->pos + dir_addition[gState.player->cur_dir] * 4;
}
sf::Vector2f InkyUpdate(Ghost& ghost)
{
sf::Vector2f target = gState.player->pos + dir_addition[gState.player->cur_dir] * 2;
sf::Vector2f offset = gState.ghosts[RED]->pos - target;
target = target + offset * -1;
return target;
}
sf::Vector2f ClydeUpdate(Ghost& ghost)
{
sf::Vector2f target = gState.player->pos;
// if clyde is 8 tiles away, target player, else target corner
if (Distance(ghost.pos.x, ghost.pos.y, gState.player->pos.x, gState.player->pos.y) < 64)
target = { 0,31 };
return target;
}SOURCE / SCOPE
Scope of the notes.
Each source excerpt comes from the linked fixed commit. Equations describe those operations. Apart from worked examples, no new performance or quality measurements are claimed. Refer to the repository for build steps and dependencies.
Open repository ↗