breakout-game
Breakout
Breakout is the arcade game where you slide a paddle, bounce a ball, and knock out a wall of blocks. This one is built from scratch in Python, no game engine, so everything is hand-made: spotting when the ball touches a block, losing one of three lives, speeding up as you rally, saving the high score. That touch test is a crude distance check; the drawing library offers nothing better.
Solo work by Salman Adnan.
Overview
A classic Breakout clone built with Python's turtle module: a paddle, a bouncing ball, a wall of blocks colored by row, a lives system, a start and end screen, an increasing difficulty ramp, and a persistent high score.
A game-loop exercise: object motion, collision detection against multiple kinds of surfaces (walls, paddle, blocks), a small state machine for start/playing/game-over/win, and score state that survives between runs, all without a game engine, just turtle and a manual while-loop.
Key features
- A block wall generated procedurally: random widths, packed row by row until there's no more vertical room, each row colored from a fixed palette.
- Breaking a block flashes it white for a few frames and fires a small outward burst of particle turtles before both disappear.
- Three lives; missing the ball costs one and re-centers it, keeping current difficulty, until all lives are gone.
- The ball speeds up slightly every 4 paddle returns, capped at a maximum speed.
- A start screen gates the game until the player is ready, and a game-over or win screen offers a restart that rebuilds the wall and resets ball and lives.
- High score persists across runs in `highestScore.txt`, read on startup and saved whenever a game ends.
Verification
Since `main.py` never returns until the window is closed, verification ran the same modules through a headless-safe frame loop capped at 200 iterations, operating on private copies of the modules so the real `highestScore.txt` was untouched. It drove the ball onto the paddle 10 times to trigger the difficulty ramp, then forced a miss and a restart. Result: 52 blocks created, 200 frames run without exception, 10 paddle hits recorded, a life loss and a difficulty increase both observed, and the restart path rebuilding 46 blocks with lives and ball speed reset correctly.
Tech stack
A challenge worth noting
Turtle gives no rectangle collision out of the box, so ball-to-block collision uses a fixed-radius distance check, an approximation that treats a wide block and a narrow block as the same size. Packing the block wall has a similar manual-geometry problem: `place_block()` tracks the previous block's position and width to decide whether the next one fits on the current row, wrapping to a new row or stopping entirely once vertical space runs out. `main.py` also runs the ball-to-block collision check twice per frame (once before moving the ball, once after) to catch a fast ball tunneling past a block between checks, which works but costs double the checks most frames need.