- Bump @valknar/vpinball-wasm to 0.3.2 (PinMAME ROM support, MsgBox fix) - Add optional PinMAME ROM .zip upload alongside .vpx tables - Persist uploaded tables/ROMs in IndexedDB so users don't have to re-upload on later visits, with a library list on the landing page - Fix Insert Coin key mismatch with the engine's real coin-door gating (now bound to 4, matching the shared table scripts) and surface it in the controls legend and "Tap to Start" hint - Make the landing page, staging panel, and in-game HUD responsive for portrait phone widths; drop the landscape hint since portrait plays fine - Replace the separate STATS HUD toggle with an FPS row in the info panel Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N9JmzRBZenapVkFWjw9jmG
131 lines
5.2 KiB
Markdown
131 lines
5.2 KiB
Markdown
# vpinball
|
|
|
|
Play real `.vpx` pinball tables in your browser. Drop in your own table or try the bundled demo —
|
|
no plugins, no native install. Powered by [`@valknar/vpinball-wasm`](https://dev.pivoine.art/valknar/vpinball-wasm),
|
|
a WebAssembly build of the real [Visual Pinball](https://github.com/vpinball/vpinball) engine
|
|
(real physics, real VBScript table scripting, real WebGL2 rendering).
|
|
|
|
## Features
|
|
|
|
- **Play any self-contained `.vpx` table** — drag a file onto the landing page, or click to browse.
|
|
- **ROM support for real-hardware ("SS") tables** — attach the table's PinMAME ROM `.zip` alongside
|
|
the `.vpx` upload; most tables don't need this.
|
|
- **A local table library** — uploads are saved in the browser (IndexedDB) so you don't have to
|
|
re-upload the same table (and its ROM) on your next visit. Nothing leaves your browser; there's
|
|
no server-side storage.
|
|
- **Demo mode** — a bundled table plays instantly with no upload required.
|
|
- **Fullscreen**, a live **FPS/stats** readout, and a **game info** panel (table name, size, load
|
|
time) in an in-game HUD styled after a pinball cabinet's coin door.
|
|
- **Installable as a PWA** — add it to your home screen or desktop; the engine is cached after
|
|
your first game so it's available offline afterward.
|
|
- **Deployable as a static site** via Docker Compose — no Node server at runtime, just nginx
|
|
serving prebuilt files.
|
|
|
|
## Prerequisites
|
|
|
|
- Node.js ≥ 20, [pnpm](https://pnpm.io) ≥ 11
|
|
- Docker + Docker Compose, for the containerized deploy
|
|
|
|
## Install
|
|
|
|
```bash
|
|
pnpm install --frozen-lockfile --trust-lockfile
|
|
```
|
|
|
|
`vpinball-wasm` is published to a private Gitea npm registry
|
|
(`https://dev.pivoine.art/api/packages/valknar/npm/`) under the `@valknar` scope. `.npmrc` maps
|
|
that scope to the registry; the package is publicly readable, so no auth token is needed to
|
|
install it.
|
|
|
|
To bump the engine to a newer published version:
|
|
|
|
```bash
|
|
pnpm add @valknar/vpinball-wasm@<version>
|
|
```
|
|
|
|
## Development
|
|
|
|
```bash
|
|
pnpm dev
|
|
```
|
|
|
|
`pnpm dev` copies the engine's build output into `public/vendor/vpinball-wasm/` first (via the
|
|
`predev` script) — it's gitignored and regenerated from `node_modules`, so this only needs
|
|
`pnpm install` to have completed. Re-run `pnpm run copy-engine-assets` by hand if you update the
|
|
dependency without restarting the dev server.
|
|
|
|
The dev server runs at `http://localhost:3000`.
|
|
|
|
## Build
|
|
|
|
```bash
|
|
pnpm build
|
|
```
|
|
|
|
Produces a fully static export in `out/` (`next.config.ts` sets `output: "export"`) — no Node
|
|
server needed to serve it.
|
|
|
|
## Docker deploy
|
|
|
|
```bash
|
|
docker compose build
|
|
docker compose up -d
|
|
```
|
|
|
|
Serves the static build via nginx on `http://localhost:8080`. No secrets or registry
|
|
authentication are required to build the image.
|
|
|
|
## PWA
|
|
|
|
The app can be installed from the browser's install prompt. A hand-rolled service worker
|
|
(`public/sw.js`) precaches the app shell; the engine's `.wasm`/`.data` files (~34 MB) are cached
|
|
on first visit to `/play`, not upfront, so installing the app doesn't force a large download
|
|
before anyone has actually played. After that first visit, offline reloads work.
|
|
|
|
When you ship a release that changes the app shell or updates the vendored engine build, bump the
|
|
cache version so returning visitors actually get the update:
|
|
|
|
```bash
|
|
pnpm run sw:bump
|
|
```
|
|
|
|
## Controls
|
|
|
|
| Key | Action |
|
|
| -------------- | ------------- |
|
|
| 4 | Insert coin |
|
|
| 1 | Start game |
|
|
| Enter | Launch ball |
|
|
| Left Shift | Left flipper |
|
|
| Right Shift | Right flipper |
|
|
|
|
On touch devices, an on-screen control overlay appears automatically once a table is running.
|
|
|
|
## Limitations
|
|
|
|
Inherited from the underlying engine:
|
|
|
|
- Only self-contained `.vpx` tables are supported — tables that reference an external `.vbs`
|
|
script override or a `Music/` folder won't load correctly.
|
|
- PinMAME (`VPinMAME.Controller`) ROM-driven emulation runs, but on-screen DMD/backglass output
|
|
and hands-on switch/solenoid/scoring behavior aren't yet confirmed end-to-end — see the engine's
|
|
own README for the current state. No DOF, FlexDMD, or backglass (`.directb2s`) plugin support.
|
|
ROM files are copyrighted; only supply ones you're legally entitled to use.
|
|
- The ROM `gameName` PinMAME needs is derived from the uploaded zip's filename (e.g.
|
|
`hvymetal.zip` → `hvymetal`) — rename the zip to match if a table doesn't recognize its ROM.
|
|
- Single-threaded (no `SharedArrayBuffer`) — performance depends on your device's single-core
|
|
WebGL2 throughput.
|
|
- Initial engine download is ~34 MB (cached after the first visit).
|
|
- Gamepad input and DMD rendering are implemented but not yet confirmed on real hardware/tables.
|
|
- Raw cabinet hardware input (real nudge/plunger boards) has no browser equivalent.
|
|
- The table library lives in the browser's IndexedDB storage — clearing site data removes it, and
|
|
it doesn't sync across browsers/devices.
|
|
|
|
## License
|
|
|
|
This app's own source has no license file yet — add one before distributing it. Separately, the
|
|
built output bundles the `@valknar/vpinball-wasm` engine and its default table, which redistribute
|
|
Visual Pinball source under a **mixed legacy/GPLv3+ license** (migrating file-by-file to GPLv3+
|
|
since October 2020) — see that package's own `LICENSE` for the authoritative terms before
|
|
distributing a build.
|