Quick answer: Float equality is unreliable. Use (vec - target).length_squared() < 1e-6 or math.isclose per component.

A platformer checks if the player reached a checkpoint at (100, 200). After moving via Vector2 arithmetic, position.xy looks like (100, 200) in debug print but the equality check fails. Float precision strikes again.

The Issue

pos = pygame.math.Vector2(0, 0)
for _ in range(100):
    pos += pygame.math.Vector2(1, 2)
print(pos)                          # Vector2(100, 200) ish
print(pos == (100, 200))            # sometimes False!

Repeated addition accumulates error. Result close to (100, 200) but not exactly.

Fix: Distance-Based Compare

def approx_equal(a, b, eps=1e-4):
    return (a - b).length_squared() < eps ** 2

if approx_equal(pos, pygame.math.Vector2(100, 200)):
    reached_checkpoint()

length_squared avoids the sqrt cost. Squaring eps gives the equivalent threshold.

Per-Component Tolerance

import math

def vec_isclose(a, b, rel_tol=1e-6):
    return (math.isclose(a.x, b[0], rel_tol=rel_tol) and
            math.isclose(a.y, b[1], rel_tol=rel_tol))

Uses math.isclose with relative + absolute tolerance. Robust around zero too.

Snap to Grid

For tile-based games, snap position to integer grid for comparison:

tile = (round(pos.x / TILE_SIZE), round(pos.y / TILE_SIZE))
if tile == checkpoint_tile:
    reached_checkpoint()

Eliminates float compare entirely by quantizing to discrete cells.

Verifying

Repeat the addition path; checkpoint triggers reliably. Spawn near-misses (off by 0.001) within tolerance to confirm.

“Float == is broken in general. Game code should compare positions with tolerance or snap to grid.”

A 1-pixel tolerance is usually safe for game checkpoints. Tighter tolerance only matters for physics solvers and constraint stability.