A retro Snake-inspired arcade game built with a browser/JavaScript runtime (with a preserved Python/Pygame reference implementation). Local-first by default — no email, real-name account, telemetry, ads, or backend required for normal play. A local anonymous player ID and username support the global personal-best leaderboard.
Production-ready arcade game (v1.0.0). Playable in any modern browser, installable as a PWA, and packaged as a native Android app via Capacitor.
The browser runtime under web/ is the primary runtime. The Python/Pygame version is preserved as a canonical reference implementation.
- Snake movement with grid-based alignment (portrait and landscape)
- Rodent collection with quadratic scoring
- Obstacles with collision detection
- 4 power-up types: Immunity, Speed Boost, Shield, Score Multiplier
- Each with unique color, audio cue, and game effect
- 4 visual themes: Classic (green), Midnight (dark), Desert (warm), Ocean (teal)
- Title screen with difficulty selection (Easy / Normal / Hard)
- Pause/resume with on-screen pause button
- Procedural audio with sound effects
- Looping background music with toggle and credit link
- Haptic feedback on mobile (vibration)
- Deterministic replay recording, playback, and verification
- First-run username setup with whimsical random name generator
- Global leaderboard via Supabase for each player's personal best
- Local score history and personal-best tracking
- Gameplay stats tracking (games played, food, averages)
- Portrait and landscape game modes (360×560 portrait grid)
- Responsive canvas with DPR support (crisp on high-DPI screens)
- PWA installability and offline cache behavior
- Capacitor Android APK (6.6MB, signed)
- Graceful degradation: game never crashes on missing audio or assets
- Animated decorative snake field background (canvas-based)
- Local-first: no real-name accounts, telemetry, ads, or multiplayer; Supabase leaderboard calls store username, anonymous player ID, and personal best only
See ARCHITECTURE.md for the full module structure and data flow.
hisstastic/ # Python/Pygame package (canonical)
main.py — Entry point
game.py — Game class, state machine
config.py — CONFIG dict, difficulty presets
entities.py — Snake, Food, Obstacle, PowerUp
audio.py — Procedural sound effects with graceful fallback
assets.py — Asset loading with placeholder fallbacks
input.py — Event-to-action mapping
rendering.py — All Pygame draw functions
scoring.py — Quadratic scoring and legacy messages
spawns.py — Safe grid-aligned entity placement
states.py — Game state constants
replay.py — Deterministic replay recording and validation
replay_cli.py — Command-line replay tools
ghost.py — Local ghost replay sync and visualization
web/ # Browser/PWA runtime (primary)
index.html
js/ — Game engine, audio, renderer, input, replay, supabase, snake field, snake facts
css/style.css
assets/ — Background music, images
sw.js — Service worker (offline caching)
manifest.webmanifest
identity.js — Local anonymous player identity, score history, personal best, pending sync
supabase.js — Global leaderboard REST client
HissTastic has two runtimes. Neither requires Vercel, a backend, or any external service for normal local play. The global leaderboard uses Supabase only to sync player profile and personal-best rows.
- Python 3.9+ (python.org)
- Git (git-scm.com)
- A modern browser (Chrome, Firefox, Edge, Safari)
- pygame (for the Python runtime only)
# Clone the repo
git clone https://github.com/sparshsam/hisstastic.git
cd hisstastic
# Or use the dev server script
bash scripts/serve.sh
# Opens at http://localhost:8080 — the browser game, no build step requiredThe Python/Pygame version is the canonical runtime.
# Create and activate a virtual environment
python -m venv .venv
# macOS / Linux:
source .venv/bin/activate
# Windows (PowerShell):
.venv\Scripts\activate
# Install pygame
pip install pygame
# Run the game
python main.pyLegacy entry point (preserved, unchanged):
python hisstastic.pyTroubleshooting:
| Problem | Fix |
|---|---|
ModuleNotFoundError: No module named 'pygame' |
Run pip install pygame |
pygame.error: video system not initialized |
Ensure you have a display (no DISPLAY in SSH) |
pygame.error: No available video device |
Install X server or use headless mode (see below) |
Headless/WSL (no display):
On WSL or headless servers, the Python runtime won't produce a window. This is expected. Use the browser runtime instead — it's the primary local dev workflow.
The browser runtime is a zero-config static site. No build step, no framework, no Node.js required.
bash scripts/serve.sh
# Opens at http://localhost:8080Or with a custom port:
bash scripts/serve.sh 3000
# Opens at http://localhost:3000python -m http.server 8080 --directory web/
# Opens at http://localhost:8080# Node (if installed)
npx serve web/ -p 8080
# PHP
php -S localhost:8080 -t web/To preview the game as it would appear in production, serve from the web/ directory:
# Start server
python -m http.server 8080 --directory web/
# Open in a browser
open http://localhost:8080Important: On plain HTTP localhost, the service worker is intentionally skipped to
avoid stale-cache confusion during local development. You can play and test everything on
localhost without issues — this is the recommended local workflow.
To test full PWA offline caching and service worker behavior, deploy to a secure context (HTTPS) such as:
- Vercel preview deployment (
vercel --preview) - GitHub Pages
- Any HTTPS-enabled hosting
- A local HTTPS server (e.g.
mkcertfor a trusted local cert)
When deployed to HTTPS, the service worker caches all assets and the game remains playable offline.
# Validation suite (checks assets, schema, imports, etc.)
python validation.py
# Unit tests
python -m unittest discover -v
# Replay system
python -m hisstastic.replay_cli record
python -m hisstastic.replay_cli verify replays/replay_*.json
python -m hisstastic.replay_cli play replays/replay_*.json# Local health check — verifies all files, assets, and dependencies
bash scripts/check-local.sh
# Start the server and open http://localhost:8080
bash scripts/serve.sh
# Manual smoke tests:
# 1. Game loads without JS console errors
# 2. Title screen displays with difficulty selection
# 3. Gameplay: snake moves, eats food, collides with obstacles
# 4. Sound effects play on eat/power-up/game-over
# 5. Background music toggle works (🎵 Music button)
# 6. Music credit link opens YouTube source
# 7. PWA manifest loads (check DevTools → Application → Manifest)
# 8. Service worker state (check DevTools → Application → Service Workers;
# on localhost it won't register — expected. Verify on HTTPS/preview.)
# 9. Import/Export replay buttons work
# 10. Mobile D-pad controls respond on touch devices| Asset | Path | How to Verify |
|---|---|---|
| Browser HTML | web/index.html |
Load http://localhost:8080 |
| CSS | web/css/style.css |
DevTools → Network → style.css |
| JS files | web/js/*.js |
DevTools → Sources → js/ |
| Background music | web/assets/background-music.mp3 |
Click 🎵 Music button; should play at low volume |
| PWA manifest | web/manifest.webmanifest |
DevTools → Application → Manifest |
| Service worker | web/sw.js |
DevTools → Application → Service Workers |
| PWA icons | web/icons/icon-{192,512}.png |
DevTools → Application → Manifest |
| Python assets | assets/snake.png, rodent.png, danger.png, power_up.png, icon.png |
ls assets/ or python validation.py |
Graceful degradation: If the background music file is missing or fails to load, the Music button becomes disabled and the game continues without crashing.
During development, the service worker caches aggressively. If you see stale content:
- Open DevTools → Application → Service Workers
- Click "Unregister"
- Hard-reload (
Ctrl+Shift+RorCmd+Shift+R)
Or, run an incognito/private window where no service worker is registered.
- Browser autoplay policy: The music only starts after your first click/tap on the page. Click anywhere on the game first.
- File not found: Check that
web/assets/background-music.mp3exists. If missing, the Music button will be disabled. - Volume too low: Default volume is 0.15. Ensure your system volume is turned up.
WSL doesn't have a native display. The Python/Pygame runtime requires a window server.
Use the browser runtime instead (bash scripts/serve.sh then open in Windows browser).
Make sure you're accessing the game through an HTTP server, not by opening the HTML file directly
(file:/// path). Browsers block many features (service workers, audio, fetch) on file:// URLs.
# Correct:
python -m http.server 8080 --directory web/
# Then open http://localhost:8080
# Incorrect: double-clicking web/index.html (file:///path/to/index.html)Record a game session:
python -m hisstastic.replay_cli recordVerify a replay file:
python -m hisstastic.replay_cli verify replays/replay_12345_20260604.jsonPlay back a replay:
python -m hisstastic.replay_cli play replays/replay_12345_20260604.jsonSee docs/replay-ux.md and docs/ghost-racing.md.
A lightweight JavaScript/Canvas implementation is available in web/.
Browser runtime capabilities:
- Canvas rendering for local arcade play
- Touch/swipe and directional-pad controls
- PWA manifest and service worker for offline cache behavior
- Replay import/export with local JSON files
- Looping background music with toggle and credit link
- No telemetry, accounts, external backend, wallet logic, or multiplayer
See docs/browser-runtime.md, docs/mobile-controls.md, and docs/pwa.md.
HissTastic is packaged as a native Android app via Capacitor.
- Download the latest APK from the releases page
- Enable "Install from unknown sources" on your Android device
- Open the APK to install
# Prerequisites: Android SDK 35+ (target/compile SDK 36), Java 21+, Node.js 18+
npm install
npx cap sync
npm run cap:bundle:release
# APK at android/app/build/outputs/apk/debug/app-debug.apk
# AAB at android/app/build/outputs/bundle/release/app-release.aabSee BUILD_ANDROID.md for detailed debug, release, and signing instructions.
On first launch, HissTastic creates a local anonymous player profile:
- player_id: locally generated UUID
- username: player-chosen or generated whimsical name
- created_at / updated_at: local profile timestamps
- local settings: theme, audio, stats, and score history
No email, phone number, real name, location, contacts, device advertising ID, analytics ID, or account login is collected.
Score behavior:
- Every completed game is saved to local score history.
- The local personal best is updated only when a new best score is reached.
- The global leaderboard is updated only for a new personal best.
- Global leaderboard rows store one best score per player, not every game.
- If offline, the latest pending personal best is saved locally and synced next time the app is online.
Supabase stores:
players: anonymousplayer_id, username, created/updated timestampsleaderboard_scores: anonymousplayer_id, username snapshot, best score, updated timestamp
Score history remains local-only.
# Python validation suite
python validation.py
python -m unittest discover -v
# Local health check (browser assets + Python)
bash scripts/check-local.shSee docs/packaging.md for standalone executable instructions.
- The browser runtime is the primary Play/PWA runtime; Python remains the reference implementation.
- There is no online multiplayer, telemetry, account system, advertising SDK, crash reporting SDK, or wallet/onchain logic.
- Global leaderboard access uses Supabase REST calls to sync/read anonymous username and personal-best rows.
- Replay files are local JSON artifacts only when explicitly recorded, imported, or exported.
- Ghost racing is local-only and score-neutral.
- PWA support is limited to installability and offline asset caching.
HissTastic is part of Sparsh Sam's broader public software ecosystem as a preserved AI-assisted game prototype and modernization candidate.
This project is licensed under the MIT License.
This repository follows the ecosystem standards.
Last updated: June 2026
| Layer | Choice |
|---|---|
| Python reference | Python + Pygame |
| Browser game | HTML/CSS/JavaScript Canvas |
| Android package | Capacitor + Gradle |
| Testing | unittest, local health checks, Gradle builds |
Welcome screen with username setup • App icon — #00BF63 green



