It's tubes, okay?

tl;dr

Play it yourself: https://langa.pl/downthedrain/
Playthrough video: https://www.youtube.com/watch?v=IiaM_c-nWL4

The backstory

I got really excited when Glyph pinged me to team up for PyWeek. I always admired PyWeek and people who managed to accomplish something in seven days when regular life can be a bit much on its own.

I made the theme for the game, and we had a funny little Zoom meeting where Glyph's daughter shared ideas with us that could easily turn into a few games. However, later in the week, life caught up to each one of us, and the ambitious plans went down the drain.

And now for something completely different

But I'm a stubborn guy, and I already had the music. I also gave a talk at EuroPython about generative graphics where the most well-received part was about 3D animation with PyScript. So, to salvage PyWeek #36, I decided to spend my Saturday hacking up something that's not much more than a tech demo to demonstrate this cool technology. I managed to complete just that, so this becomes our team's entry for this edition of PyWeek! Did I finish on Saturday or did I cheat a bit and only managed to get collision detection working on Sunday? Well, friends don't ask friends such questions.
A winning game of "Down The Drain"
OK, but is it at least on topic?

Well, you're flying in a dark tube, the title's got somewhat negative connotations... you could say it fits the "Dark Matter" theme! If you squint right 😎

Python in the browser is all I wanted for Christmas

Let's talk about the tech, that's definitely a more pleasant topic!
  • this is written in PyScript, which packages Pyodide in a way that is very easy to use for new projects;
  • graphics and audio bind to THREE.js, a wonderful library that makes using WebGL pretty easy;
  • but there is no JavaScript in this project, it's all Python 3.11!
There are some fantastic things about this that you might notice:
  • it runs everywhere without installation, including my iPhone;
  • it easily runs at 60FPS in Firefox and at a whopping 120FPS in Chrome -- remember that all logic here is written in Python;
  • it looks really nice, even if I only used the most primitive pieces of THREE.js this time.
Did you at least learn anything interesting?

Sure, sure! This entire ordeal of making a game in 24 hours or so taught me many things, but in no particular order, these are some highlights:
  • collision detection is a complex beast, and no algorithm is perfect;
  • in space no one can hear you scream that there's actually not three but six attributes needed to position and orient an object in three dimensions;
  • there are many clock domains: if you want to make your game synchronize to audio, you can't naively increment calculations in an animation frame callback, because some systems will run 60 of them per second, some 120, and some will struggle with even 30;
  • JavaScript is an FFI language in Pyodide, so there are some surprises like the fact that you need to call create_proxy() when passing callbacks so that Python's memory management doesn't destroy the function before it's called by JavaScript;
  • THREE.js is very powerful but still easy to use, even though many examples available online for it no longer work because it moves very quickly in terms of API changes;
  • more importantly, you can successfully write Python in the browser while reading JavaScript API docs and survive to tell the tale!