Crappy-Wheels

Like Happy-Wheels, but crappier

Crappy-Wheels logo

Crappy-Wheels is a little physics driving game I made in Godot 4, because I was bored and wanted to make something like Happy-Wheels. You drive a wobbly hand-drawn car from start to finish, try not to land on your roof, and race other people’s times on the leaderboard.

It runs right in the browser: play it at toemmsen.ch/crappy-wheels.


Controls

KeyAction
W / ↑Accelerate
S / ↓Brake, then reverse
A / ←Tilt back (nose up)
D / →Tilt forward (nose down)
SpaceBoost
FReset to the start
EscPause

The car is a rigid body with two wheels on pin joints, so everything you do is actual physics: the throttle puts torque on the wheels, tilting puts torque on the body, and boost just shoves the whole car to the right. Hit something hard enough and it goes crash, land on the roof and it goes dong.


Level Builder

The main menu has a Level Builder where you can make your own levels: draw floors, place balls and boost pads, and move the start and finish around. Test plays the level straight away, Save stores it locally, and your levels show up under Your Levels in the level selector, where you can play, edit or delete them.

Levels are plain JSON instead of Godot scenes, since loading a scene or resource can run scripts inside it, which is not something you want when downloading levels from strangers. Every level goes through the same loader, which rejects malformed files and clamps out-of-range values.


Sharing Levels & Leaderboards

Community levels live in crappy-wheels-levels. Press Share next to one of your levels and it gets added to the Community/ folder right away. You can also Export the .json and open a pull request yourself. Browse Online Levels lists everything in Base/ and Community/ and downloads it into the game.

Level 1 and every downloaded level have a leaderboard. When you finish, the finish screen shows the ten fastest times and submits yours under the name you entered. Only your best time per level is kept. There are no accounts, so yes, you could cheat, but please don’t.


The Backend (on a phone)

Leaderboards and level sharing are handled by the crappy-wheels-backend, a small Go server with an SQLite database. When someone shares a level, it validates the file with the same rules as the game, commits it to the level repository and pushes it to GitHub over SSH with a deploy key.

The fun part: it runs on my old Samsung J5, which has Linux running on it. So it is a single static arm64 binary (SQLite and git are compiled in as pure Go), runs as a sandboxed systemd service, and is careful not to write more than it has to, to spare the phone’s flash storage. Tailscale Funnel gives it a public HTTPS address so the browser build can talk to it. Rate limits and size caps are there so nobody can fill up the phone.


Stack

  • Game: Godot 4.7, GDScript, exported to the web and deployed to GitHub Pages via GitHub Actions
  • Backend: Go, SQLite, go-git, running on a Samsung J5
  • Levels: JSON files in a public GitHub repository
  • Art: hand drawn by me (obviously), text in Gochi Hand

Play → · Game on GitHub → · Levels →