main
🍬 Cosmic Candy Pinball
A cute, 8-bit, pixel-art pinball game, written from scratch in Python with pygame-ce. 100% procedural — there are no image or audio asset files: every sprite, texture, particle, chiptune and sound effect is generated by code at runtime.
Not web-based: it opens its own native window and renders on a low-res
portrait 360×480 virtual canvas — like a proper pinball machine —
upscaled with crisp nearest-neighbour scaling for an authentic retro look.
Running it
Fastest (uv, already used in this project):
uv venv .venv --python 3.12 # once
uv pip install --python .venv/bin/python -r requirements.txt # once
.venv/bin/python main.py
Or with plain venv + pip (Python 3.10+):
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python main.py
Note: the dependency is
pygame-ce, notpygame(the community edition supports newer Python versions and is what this was built against).
Controls
| Key | Action |
|---|---|
← → (or Z / /) |
Flippers |
hold Space / ↑ |
Charge the Candy Cannon — release to fire |
M |
Mute |
P |
Pause |
R |
Restart game |
Esc |
Quit |
Enter |
Start / play again |
How to play
- Light the 3 star lanes up top → CANDY FEVER! (double points for 20s — keep hitting stars to extend it).
- Bounce off the three kawaii candy bumpers and the two slingshots. Every hit inside 2.5s builds your combo multiplier (up to ×9).
- Watch the bottom-centre drain and the two outlanes… or lose the ball.
- Every 50,000 points earns an extra ball.
- The kawaii cat helper reacts to your shots from the corner.
Project layout
| file | purpose |
|---|---|
main.py |
entry point / main loop |
game.py |
game states, scoring, juice, all rendering (pixel art) |
physics.py |
pure pinball physics (flippers, bumpers, slingshots, drains) — no rendering |
font.py |
hand-made 5×5 pixel bitmap font |
sfx.py |
procedural chiptune + music synthesis (pure code, no samples) |
highscore.json |
best score (written at game over) |
Dev / test tools (run headless, no window needed):
.venv/bin/python autotest.py 40000 # auto-playing bot, prints game-health stats
.venv/bin/python runtest.py 900 # simulated session incl. rendering
.venv/bin/python shots.py shots # dumps screenshots of every state
.venv/bin/python probe.py # pixel-probes the rendered layout
Design notes
- Portrait table: a
360×480playfield like a real pinball machine, with regular-sized flippers (about a quarter of the playfield width each) at the bottom and a wide centre drain between them. - Physics: fixed 60 Hz logic with up to 6 collision substeps so the ball never tunnels; kinematic flippers whose angular velocity is transferred to the ball (real "scoop" feel); inward-tilting floor funnels; centre drain + guarded outlanes; a softlock rescue nudge if a ball ever parks too long.
- Fun tuning was data-driven: an
autotest.pybot plays thousands of frames and reports hit/drain rates per table element, so bumper, slingshot and flipper geometry was tuned against measured behaviour, not guesswork. - Audio: soft triangle/sine voices -> PCM at startup; pitched bumper pops that climb with your combo, plus two real melodies (a slow Twinkle Twinkle lullaby on the title, a bouncier version during play — no square-wave or noise percussion in the music).
Licence: MIT — go wild.
Languages
Python
100%
