Heads up: I'm not a game developer, so there are probably things done wrong or clumsy in here. Be gentle, ha ha — always open to learning!
This is the part I like. There are just two dots:
- the head, which runs at the word you're typing
- the tail, which runs at the head, just slower
The head is quick so it races ahead. The tail can't keep up, so it trails
behind. The gap between them is what you see as the long stretchy bit. Move
fast and it stretches, stop and it catches up again. That's the whole trick,
and it's about ten lines in logic.go.
Two small things worth knowing:
- It looks the same on any monitor. Both dots ease toward their target
with
1 - exp(-speed * dt). The simplerdt * speedstep (which I first tested in blob-physics) drifts: on high refresh screens the blob moves at different speeds, and on a dropped frame it can jump past its target. The exponential form never overshoots. - The stretch is capped. The dome can only get so long, because the blob's resting spot teleports to whatever word it just ate, so uncapped it would smear the whole screen. It stays as wide as the blob the whole stretch, so it reads as one fat blob being pulled rather than a rubber band.
yay -S tez-binnix run github:vyrx-dev/tezDownload the latest version for your platform from Releases:
- Linux:
.tar.gz,.deb(Debian/Ubuntu), or.rpm(Fedora/RHEL) - macOS:
tez_*_darwin_all.tar.gz(Universal) - Windows:
tez_*_windows_amd64.zip(Standalonetez.exe)
You just need Go 1.24+. No C compiler or raylib setup required:
CGO_ENABLED=0 go run .To build a binary:
CGO_ENABLED=0 go build -o tez .nix run .
# or in the dev shell:
nix-shell --run "go run ."The blob maths doesn't need raylib or a window, so it's tested on its own:
go test -tags test ./...raylib picks its audio backend at runtime. If it cannot find PulseAudio or ALSA, it silently falls back to Null (plays nothing, with no error). Check your startup terminal log:
INFO: > Backend: miniaudio | PulseAudio <- sound works
INFO: > Backend: miniaudio | Null <- silent fallback
If you see Null:
- Standard Linux: Make sure
alsa-lib(Arch/Fedora) orlibasound2(Ubuntu/Debian) is installed. - NixOS: Run with
steam-run ./tez,nix-shell --run "./tez", ornix run ..
| File | What it does |
|---|---|
main.go |
Opens the window, audio and the frame loop. Nothing else. |
game.go |
Game state, restarting, the boot and game over screens. |
update.go |
What happens each frame: keys, spawning, the blob. |
render.go |
Everything that gets drawn. |
logic.go |
The blob maths. No raylib in here at all. |
logic_test.go |
Tests for the maths. |
audio.go |
Loads the sound effects, which are embedded in the binary. |
Want more words? They all live in one list, wordList in types.go, split by
difficulty. Add or take away whatever you like there and the game picks it up
next build.
The sound effects are embedded in the binary from assets/audio, so the game
never writes anything to disk and makes no noise about it if it cannot.
- Death mode: one wrong letter and it's over, no hearts and no second chances
- more words
- difficulty that isn't just "everything got faster"
- a combo score for typing words without a slip
The stretchy blob is inspired by Tsoding's blob (Rust + SDL3). I first prototyped and verified the mechanics in Go as blob-physics before building this game on top of it.