A browser-based multiplayer Pac-Man prototype that uses PubNub for the complete real-time path: secure player commands, authoritative lobby and game updates, presence, identity metadata, and persisted catch-up state.
- Players enter a name and join a shared lobby code.
- Each player can claim exactly one of Pac-Man, Blinky, Pinky, Inky, or Clyde.
- Claims are resolved by the server, so simultaneous claims have one winner and claimed cards immediately become unavailable everywhere.
- The match starts when all five characters are claimed or 30 seconds after the first player enters.
- Player movement is sent as compact, non-persisted PubNub signals. The Node authority publishes game snapshots, and Phaser smooths movement between them.
- Unclaimed characters are controlled by simple server-side bots.
- PubNub Presence drives the online roster. A disconnected player's claimed character freezes and flashes until that player returns.
- Recent lobby and game snapshots are stored by PubNub so late clients can catch up instead of relying on browser storage.
The maze, scoring, collisions, and bot routing are intentionally compact. They make the multiplayer loop playable without trying to reproduce the full arcade game.
Browser A ─┐ player-specific command channels ┌─ Node authority + token issuer
Browser B ─┼────────────────────────────────────►│ validates claims and inputs
Browser C ─┘ │ runs game + bots
▲ │
└──── lobby/game snapshots + presence ─────┘
PubNub
Channel names follow PubNub's descriptive prefix convention:
pacman.lobby.{lobbyId}
pacman.game.{lobbyId}
pacman.presence.{lobbyId}
pacman-command.{lobbyId}.{playerId}
Each Access Manager token is bound to one player ID. It grants read access to that lobby's shared state and Presence events, but write access only to that player's command channel. The browser never receives the secret key.
- Node.js 20 or newer
- A provisioned PubNub keyset with Access Manager, Presence, Message Persistence, and App Context enabled
- The keyset's publish, subscribe, and secret keys
Install dependencies:
npm installCreate the only environment file you need to fill manually:
cp .env.example server/.envPut all three PubNub keys in server/.env. Do not paste them into chat, do not
commit this file, and never put PUBNUB_SECRET_KEY in any client file.
The browser needs only the safe publish and subscribe keys. During the guided
setup, those two values are copied into the git-ignored client/.env.local
without reading or copying the secret key. You should not edit the client file
yourself.
Start the authority/token server in one terminal:
npm run dev:serverStart the browser client in another:
npm run dev:clientOpen http://localhost:5173.
- Open the app in two separate browser profiles or one normal and one private window. Tabs in the same profile are still distinct players in this prototype, but separate profiles make the disconnect test clearer.
- Enter different names and the same lobby code.
- Confirm both names show online in both windows.
- Claim Pac-Man in one window and a ghost in the other. Confirm the two cards become unavailable everywhere and that neither player can claim a second card.
- Wait for the 30-second countdown. The remaining characters should become bots.
- Move with the arrow keys or WASD and compare the two windows side by side.
- Close one window. A clean leave is usually immediate; an abrupt connection loss is detected within roughly 10 seconds. The remaining window should mark that player offline and flash their character.
Run the deterministic lobby, access-scope, credential, maze, and game tests:
npm testBuild the production browser bundle:
npm run buildWith the server running and the safe client environment populated, run the live token, Presence, claim round-trip, and denied cross-player write check:
npm run smokeThese checks validate local logic and the browser build. A real PubNub round trip still requires your keyset and must be exercised through the running prototype.
- The server grants 60-minute, player-bound tokens. The client refreshes five
minutes before expiry and retries after a PubNub
403. - Name entry is deliberately standing in for authentication. Replace the open session endpoint with your real login/session before production.
- The session credential is server-signed and kept only in page memory. Reloading creates a new prototype player identity; production identity should come from your account system.
- The single Node authority is appropriate for this evaluation build. A production game service should add leader election or lobby partitioning, idempotent command handling, metrics, and deployment health checks.