Zentris
A Tetris game inspired by Tetris Effect, but playing any playlist you like: your own music folder or a YouTube playlist. Each song is analysed ahead of time (tempo, key, structure: intro, verse, build, chorus, drop...) and the game stages it: pieces fall on the beat, the pace follows the song's energy, and a procedurally generated 3D scene evolves with every section. Built in C++ / OpenGL 3.3.
Nine scenes generated by the game. Every song, and every run, gets its own scene.
Install
Prebuilt packages for Linux, macOS and Windows are published on PyPI:
pipx install zentris # then: zentris, zenscope
uvx zentris # or run it without installing
zentris "https://www.youtube.com/playlist?list=PLWHPu2N_Gb2lbZ8-7sYKSEbDlb3UiAVye"
zentris ~/Music # with no argument it plays ./audio or ~/Music
The package brings yt-dlp and an ffmpeg build for YouTube playlists; YouTube also needs a JavaScript runtime (Deno or Node.js) on your system.
Build from source
Dependencies (Debian/Ubuntu): sudo apt install cmake g++ libglfw3-dev libglew-dev
(miniaudio and stb are vendored in third_party/).
cmake -S . -B build && cmake --build build -j
./build/zentris # plays every .mp3/.wav/.flac in ./audio, in order (--shuffle for random)
./build/zentris song.mp3 ~/Music --fullscreen
YouTube playlists (or single videos) work too, through yt-dlp
(install it with pipx install "yt-dlp[default]"; YouTube also needs a JavaScript runtime such as Deno or
Node.js, and Node.js is picked up automatically). Songs are downloaded when queued and cached as MP3 in
~/.cache/zentris/youtube/. Downloading from YouTube is against its terms of service: personal use only.
./build/zentris "https://www.youtube.com/playlist?list=PLWHPu2N_Gb2lbZ8-7sYKSEbDlb3UiAVye" # quote it: & is special in the shell
./build/zenscope "https://www.youtube.com/watch?v=..."
Other options: --shuffle (random song order; default is in order: folders alphabetically, playlists in their order), --seed N (repeat a scene), --autoplay, --mute, --size WxH,
--shots PREFIX N (renders N screenshots of different scenes and exits), --phase-shots PREFIX (one screenshot per scene level of a song).
zenscope: see what the game hears
./build/zenscope [songs or folders...] plays a song and shows the analysis that drives the game:
- a phase timebar with the scene levels (calm / mid / peak) and where the scene changes happen
- the detected structure: intro, verse, build, chorus, drop, break, outro, with similar parts grouped
- pulse zones, a 16-band spectrum, loudness, intensity and onsets, and bar lines
- a live readout of the current section and the game's density/speed/glow profile, with the beat in the bar
- a zoomed detail view with the beat grid
Space plays/pauses, Left/Right seek 5 s, Up/Down zoom the detail view, N/P change song, click to seek.
The game and zenscope share the same analysis and song plan code (src/songplan.*), so what you see is what the game uses.
Controls
Keyboard and gamepad both work at the same time. A gamepad is detected at startup and on hot-plug,
and the on-screen hints follow whichever device you used last.
Controllers are recognised through the bundled SDL_GameControllerDB
(third_party/gamecontrollerdb.txt; extra mappings can be given in SDL_GAMECONTROLLERCONFIG). A controller
missing from it still works with a generic layout.
| Action | Keyboard | Gamepad |
|---|---|---|
| Move | ← → | D-pad / left stick |
| Soft / hard drop | ↓ / Space | Down / Up |
| Rotate | ↑ or X (Z or J to rotate left) | A (B/X to rotate left) |
| Hold | C / Shift (tap) | LB / RB / triggers |
| New scene | T | Y |
| Next song | N / Tab / Enter / PageDown | Back |
| Seek ±10 s in the song (testing) | Ctrl+Shift+Left/Right | |
| Next level (debugging) | L | |
| Pause | Esc / P (Q quits while paused) | Start |
| Fullscreen | F / F11 |
How the music shapes the game
Each song is decoded and analyzed in the background (under 1 s):
- Tempo and beat grid: gravity steps land on the beat, at 1 row every 2 beats, every beat, or every half beat, depending on the song's energy at that moment.
- Levels: one level per 20 lines, up to a plateau at level 20. Each level speeds up the beat-locked gravity (at the plateau: 5, 10 or 16 rows per beat for calm, mid and peak parts, on musical subdivisions, capped at 28 rows/s) and shortens the lock delay (0.55 s → 0.35 s). Game over resets the level.
- Key: the base hue follows the circle of fifths.
- Brightness, bass/air balance, dynamics, density: choose the mood (night, dusk or pale), the particle layouts, bloom, how strongly things react, and the camera's motion.
- Song structure: the song is split at bar lines into labelled segments (intro, verse, build, chorus, drop, break, outro), and segments that sound alike are grouped. Each segment eases the scene's density, speed, glow and saturation (builds ramp up, breaks thin out).
- One identity per song: background, main particles, blocks, frame and mood stay the same for the whole song. At most three intensity levels (calm, mid, peak) shift the hue slightly and add color, glow or an extra particle layer. Changes happen only when the level changes, crossfading over 8 s, and never interrupt each other.
- Calm by design: visuals follow slow (~1 s) envelopes of the music and there is no camera shake or flashing. Beat pulses appear only during peak sections (choruses, drops), stronger for faster songs; songs above ~110 BPM also get soft hits on strong transients there.
- Live bands and loudness, heavily smoothed, drive particle motion and glow.
The scene seed combines the song's fingerprint with a random seed for each run, so the same song looks different every time. The combinatorial space covers 8 palette schemes × 3 moods, 24 backgrounds, 38 particle layouts × 20 particle shapes (none, one or two layers), 12 continuous surface layers (smoke, silk, lava, caustics, ink, geometry, aurora, fog, beams, flowing rings, liquid, cloud shades), 22 block materials × a continuous family of block shapes (cube → rounded → sphere → gem), 18 board frames, a rare audio equalizer (3 layouts × 6 renderings × 4 resolutions × 3 colorings) and light rays, 22 line-clear effects, 25 transition shapes, and a post-processing grade (bloom, vignette, chromatic aberration, grain, split-toning). The scene name is shown in the bottom-left corner.
Releasing
.github/workflows/wheels.yml builds wheels for Linux (x86_64, aarch64), macOS (x86_64, arm64) and
Windows (x86_64) plus a source distribution on every push, and publishes them to PyPI when a v* tag is
pushed (git tag v0.1.0 && git push --tags). Publishing uses PyPI trusted publishing: on pypi.org, add a
publisher for project zentris, repository Gregwar/zentris, workflow wheels.yml, environment pypi.
Metadata
Release files for zentris 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| zentris-1.0.0.tar.gz | 825.3 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| zentris-1.0.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| zentris-1.0.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl | Python 3 | none | Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 | Details |
| zentris-1.0.0-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.27+ ARM64, Linux glibc 2.28+ ARM64 | Details |
| zentris-1.0.0-py3-none-macosx_11_0_x86_64.whl | Python 3 | none | macOS 11.0+ x86-64 | Details |
| zentris-1.0.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
Total release size: 6.7 MB
Release files / zentris-1.0.0.tar.gz
| Download URL | zentris-1.0.0.tar.gz |
|---|---|
| Size | 825.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a399f593425aafa3677b1afd7f0a393751e30be0e11bbf5b54417b28b9edb6bf
|
|
BLAKE2b-256 checksum How to use checksums |
837ffa4690fd8a2efc01d47e6961cf5b3017070a1b86c164d784be3ec2413c01
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / zentris-1.0.0-py3-none-win_amd64.whl
| Download URL | zentris-1.0.0-py3-none-win_amd64.whl |
|---|---|
| Size | 928.0 kB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
52f31fdbe21ba03049ab521b63c01ab30d44a9b6c1a7f52913daf31b24f74824
|
|
BLAKE2b-256 checksum How to use checksums |
853866a0d4d93392fc7754ed00255124bcdb81ae350c0842c9b89ac8de65e701
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / zentris-1.0.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | zentris-1.0.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
c5a746f6c4d09c5a0de59e805d359d1cf1ad2721c590b6881fb7507d956e6865
|
|
BLAKE2b-256 checksum How to use checksums |
e4aa49986f132412ea06a1e9061bdb845ff60405694f01742c208526eb37c309
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / zentris-1.0.0-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
| Download URL | zentris-1.0.0-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
91ce209d7196c4c8e08c84278db8e13f89279f0787496c0d2222a77dbfd459bb
|
|
BLAKE2b-256 checksum How to use checksums |
ed63200af8d25a5647ebfa0ad654c14fe8198f5bb289f4b8c16331204678ba0e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / zentris-1.0.0-py3-none-macosx_11_0_x86_64.whl
| Download URL | zentris-1.0.0-py3-none-macosx_11_0_x86_64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | Python 3 macOS 11.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
717517ba734f6a18beda9c11c66e8f437e48ee789bb8d253ca8689862881790d
|
|
BLAKE2b-256 checksum How to use checksums |
0e9f97a6e0aad7c9cdf5bf59e8203729c4a831a63c9c9341d8930868a17efa82
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / zentris-1.0.0-py3-none-macosx_11_0_arm64.whl
| Download URL | zentris-1.0.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 963.5 kB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
b6402ee418f6eddb4b3524ac1dd53239048605f29b72056d07c25918fd61f14d
|
|
BLAKE2b-256 checksum How to use checksums |
10c48060fa04cdacafa9c85d4d5dd10c47a1f0cf2a31257224725cdfd638bcea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency log