Games /shoot-the-apple
Shoot The Apple
A phone-first physics puzzler. Aim the cannon, bounce off walls, ice, bouncers and teleporters, and hit the apple in as few shots as you can. Hand-made worlds, a level editor, generated daily and random levels, and online leaderboards with server-verified replays.

A cannon, an apple, and a handful of shots. Drag to aim, let go to fire, and use walls, ice, bouncers, movers, switches and teleporters to reach the apple in as few shots as possible. Built for a phone held sideways: one finger, big targets, and nothing that needs a keyboard, though a keyboard works too.
What's inside:
- Deterministic physics. The simulation runs on a fixed 60 Hz step with a deterministic build of Rapier 2D, completely separate from the renderer. The same shots give the same result on every device, which is what makes replays and online verification possible.
- Levels as data. Every level is a small JSON file in metres and degrees. A solver sweeps the aim space to prove each level can be won and to rate its difficulty, and that gate runs in CI, so a level that stops being winnable fails the build.
- Generated play. A seeded generator builds pools of levels from recipes, settles them, rates them and keeps the ones in a target band. Those pools feed a daily level (the same for everyone, scheduled years ahead) and random play by difficulty band.
- A level editor in the game itself, with undo, snapping, a "check" that runs the solver, and share links that carry the whole level in the URL.
- Online, optional. Turn it on and you get an anonymous account with a generated handle, cloud saves that merge across devices, and leaderboards. The server replays every submitted shot before it ranks it, so a board entry is a play that actually happened. Everything works offline first; results queue and sync later.
- Installable. A progressive web app with the whole game precached, so it loads and plays with no connection.
The stack is a TypeScript monorepo: a pure simulation package, a Phaser 4 client, the solver and generator, a small API on Azure Functions behind Azure Static Web Apps, and Table Storage for the online data. Art is drawn in code from a shared palette; there are no image assets.