Cloudhop is an arcade game about flying a paper plane through gaps. You flap to rise, wait to fall and steer towards the next opening. Then you can retry the same course and try to improve your score.
I built it with AI assistance, using JavaScript for the game rules and Three.js for the 3D world. The public browser demo has ten destinations, a daily course and a gentler Beginner mode.

Simple controls, with room to practise
Space or the up arrow makes the plane flap. Left and right steer it, and P pauses the flight. Touch controls and controller support are included too. The score rewards how accurately you enter an opening, so getting through is only the start of improving a run.
Beginner gives you a two-minute flight without crashes. Arcade is a one-life score chase. Adventure takes you through all ten worlds with a supply of lives, while Daily Departure is a 90-second route that changes at midnight UTC.
For two to four people, Party mode uses three short heats on the same device. Players take turns on the same course. It gives you a way to compare flights without setting up accounts or a multiplayer server.
How I built the game
The rules live in a JavaScript model, separate from the Three.js scene and the interface. That lets the same rules be tested without drawing the world. Vite bundles the browser release, and the finished demo is served as static files.
The courses use a seed. A course code remembers the route, world and pace, so you can return to a particular challenge or copy a link for someone else. Your best attempt can leave a faint ghost plane and trail to chase on a later flight.
I used Codex to help with the implementation and checks. Automated tests cover the game rules, saved records, course codes and invalid inputs. Browser checks exercise the controls, menus and release files. Those checks matter because a working score calculation doesn't prove that a button is reachable on a phone.
Ten worlds with their own scenery
The destinations include a forest, an orbital route, a tabletop world, a reef, a canyon, ice, volcanic islands, a neon city, clockwork scenery and gardens above the clouds. The low-poly geometry and illustrated destination cards give each one a different look.
The visual assets are original project work. Audio combines original synthesised tracks with licensed CC0 music and effects. The in-game Credits button lists the creators and sources, including the Bungee typeface and Three.js.
Scores and shared challenges
The demo saves scores and progress in your browser. Completed flights can also enter a global leaderboard, so you can compare your score with people playing on other devices. Use a nickname: the name you submit appears beside your score.
Assisted flights have separate standings. A change to the rules also has its own records, so an older score doesn't quietly become the target for a different version of the game.
The server checks a flight by replaying its controls through the game rules and calculating the score itself. It doesn't accept a high-score number from the browser. That checks whether the flight follows the rules; it doesn't prove who played it.
I put the shared leaderboard in a separate Cloudflare Free account, using a SQLite-backed Durable Object. It stops when its free allowance is used rather than moving to paid usage. If shared scoring is unavailable, the game shows a notice and keeps your local scores working. Daily allowances reset at midnight UTC.
Local progress still belongs to the browser you're using. Clearing browser data removes it, and the global board doesn't sync your coins, medals or saved settings.
Trying it in your browser
The demo is free, with no account, payments or game telemetry. The flight shop uses coins earned in the game, with no cash value. It needs a browser and graphics hardware that support WebGL 2. The Detail control reduces the graphics load, and the game pauses when it loses focus.
If the 3D world can't open, the game shows a message with a retry button. Your saved records are kept. Keyboard and touch both work, although a larger screen gives you more room to see the next opening.