ps5upload
Send games, apps and homebrew to a jailbroken PS5, and manage the console from your computer, phone or browser.
Geometry puzzle game: build conic-section mirrors so all 8 balls reach the hole. TypeScript, Canvas, PWA
Translation pending
GamesTypeScript · HTMLGitHub @placikkOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A minigolf puzzle where you don't aim. You build the geometry that makes every shot go in.
Built for phones first (touch controls, portrait layout) but it also runs on desktop. You can install it as a PWA, and it works offline after the first visit.
Most minigolf games are about aiming and luck. GeoGolf is closer to Euclidea: a construction puzzle.
You get a ball, a hole and a few mirrors shaped like conic sections (ellipses, arcs, parabolas, hyperbolas). You change their shape by dragging touch handles such as foci, vertices, size and arc ends. When you press Sprawdź ("Check"), the game fires 8 balls at once, each in a different direction (from stage 1 on; the warm-up stage uses a single ball). The level counts only if all eight reach the hole.
One lucky shot can't pass that test, but a correct construction always does. To solve a level you have to use the reflective properties of conics. An ellipse with one focus on the ball and the other on the hole sends every ball into the hole. A parabola turns a fan of shots into a parallel beam. A hyperbola redirects rays aimed at one focus toward the other. Later levels chain these into cascades, where one mirror's focus is the next mirror's source.
Every path from one focus of an ellipse to the other via the curve has the same length (2a), and balls move at a constant speed. So the eight balls also arrive at the same instant. Nothing is faked: the convergence in the animation is the geometry itself.
27 levels in 4 stages, each stage adding one mechanic:
| Stage | Levels | What you learn |
|---|---|---|
| 0 | 3 | Billiards with a flat mirror (one ball, one direction) |
| 1 | 8 | Ellipses: foci, size invariance, obstacles that narrow the valid sizes |
| 2 | 8 | Elliptical arcs and cascades: one mirror's focus feeds the next |
| 3 | 8 | Parabolas and hyperbolas in two-mirror "optical systems" |
The first level of each new mechanic opens with a one-sentence rule card. Its small diagrams are traced by the real engine. The card states the rule, and the levels make you work out how to apply it.
Open the menu, switch to Community („Społeczność") and tap + New level („+ Nowy poziom"). Place mirrors and obstacles, lock the handles the player must not grab, pick the shot direction, then tap Play („Zagraj") and solve your own level. Only then does Share („Udostępnij") appear: the whole level, including your winning setup as proof, is packed into the link itself (…/GeoGolf/#poziom=…), so no server is involved. Whoever opens the link gets the level only if that proof still holds — the solution must win and the starting position must not.
Adding a level to the community catalog (maintainers): paste the code after #poziom= into src/levels/community.ts together with the author's name and run npm test. The catalog test decodes every entry and replays the proof; CI runs the same tests before every deploy, so a broken entry never reaches the site.
The game is a small exact ray tracer for conic sections. There is no physics engine.
Ax² + Bxy + Cy² + Dx + Ey + F = 0. The type is never stored as a field. It is computed from the discriminant B² − 4AC, and a line is simply the case A = B = C = 0. So walls, mirrors and obstacles all go through the same code path: src/core/conic.ts.P + t·d into the form gives a quadratic in t. It is solved with the numerically stable form q = −½(b + sign(b)·√Δ), t₁ = q/a, t₂ = c/q, which avoids cancellation on very thin ellipses. There is a separate linear branch for a ≈ 0 (degenerate curves, or rays parallel to an asymptote), and an ε-threshold so a ball sitting on a mirror after a bounce doesn't hit it again at t ≈ 0: src/core/intersect.ts.(2Ax + By + D, Bx + 2Cy + E), and the reflection is d′ = d − 2(d·n̂)n̂. Three lines of code work for every curve type: src/core/reflect.ts.src/core/piece.ts, src/core/frame.ts.Why no game engine? A physics engine simulates rigid bodies within tolerances, but this game needs the exact intersection of a ray with a curve. A focus that is slightly off must make balls miss, or the puzzle teaches something false. Most of the work with an engine would go into fighting it. The entire geometric core is about 400 lines of TypeScript with no dependencies.
2a, and the reflected ray must aim at the other focus;src/core imports nothing outside itself, and another test bans shadowBlur, which is slow on phones (the glow is drawn as two strokes instead).core/ (pure geometry, runs in Node) → levels/ (levels are data, not code) → render/ → ui/. Beside them, share/ (the link format and its proof) and editor/ (the editor model, built on share/) sit on core/ and levels/ and also use the pure handle math from ui/handles.ts (the editor also reuses the pure curve polyline from render/shapes.ts); neither touches the DOM./ and at /GeoGolf/.master (.github/workflows/deploy.yml).I (Michał Plata) built GeoGolf with an AI-agent workflow in Claude Code. I designed the game, the progression and every level, and made the architecture calls: the single quadratic form, no engine, levels as data. For each stage I wrote or approved a design spec and an implementation plan. Agents then implemented them test-first and kept decision logs of every choice they made on their own, so I could review it and overrule it if needed. Those documents are all in docs/superpowers/ (in Polish): 8 specs, 8 plans and 5 decision logs.
Requires Node.js 20.19+ or 22.12+ (CI uses 22).
npm install
npm run dev # dev server with hot reload
npm test # full test suite (also builds the bundle for the size-budget test)
npm run build # type-check + production build into dist/
npx vite preview # serve the production build
To check one level's stored solution from the command line: npx vite-node scripts/sprawdz-poziom.ts <level-id>.
From the design spec, not yet implemented:
The game's interface is in Polish. Code comments and design documents are in Polish too.
src/core/trace.ts, src/core/verify.ts.