metro
Python project · featured · pixel art, simulation
Lisbon metro sim in pixel art: watch the four lines run, step into any station, board a train and ride it.




- 50stations
- 4lines
- 202tests
- 0audio files
The problem
I wanted a transit sim you could actually stand inside: not just coloured lines on a map, but platforms with people on them, trains you can board, and a city whose rush hour you can feel.
What I built
- The four real Lisbon lines and all 50 stations, with passengers who plan their own journeys and change at interchanges (routing over a graph of station + line states, so changing lines has a cost).
- A 24-minute day with morning and evening peaks, different kinds of rider (commuters, visitors, night workers), fares, running costs and people who give up and walk out.
- Three scenes: the network map, a walkable platform where every station is tiled differently, and a ride view with the tunnel scrolling past the windows.
- A control room to move trains between lines before the rush, and faults you clear from the driver's seat.
- Every sound synthesized from arithmetic at startup, so there are no audio files to ship.
The hard part
Keeping the pixel art crisp at every zoom: the camera only zooms in whole-pixel steps and station names are drawn live on top at screen resolution. The nastier bug was colour: drawing onto a surface with an alpha channel picked up stray alpha from sprite blits and turned into coloured blocks on real display drivers, but never in the headless tests. Everything now draws onto a 24-bit surface.
Built with
- Python 3.12
- pygame
- pytest (202 tests)
- GitHub Actions
- pygbag / WebAssembly
More projects
- call_me_maybe · Turns a sentence into a JSON function call with a 0.6B model using constrained decoding — parseable by construction, not by luck.
- codexion · Multithreaded twist on the Dining Philosophers: coders compete for shared dongles, with FIFO/EDF scheduling.
- fly-in · Drone fleet routing: Dijkstra pathfinding, turn-based scheduling and a pygame replay.
- a-maze-ing · Maze generator with multiple algorithms, pathfinding solvers and terminal visualization.
- push_swap · Highly optimized sorting with two stacks and a tiny set of allowed operations.
- ft_printf · printf rebuilt from scratch: chars, strings, pointers, decimals, unsigned and hex.
- get_next_line · Reads a file descriptor one line at a time with careful dynamic memory handling.
- Libft · My own C standard library — the foundation every later 42 project is built on.