Combat Pong is a territory-control arcade game inspired by Pong Wars, rebuilt around an anonymous duel fantasy.
There are no accounts and no backend dependency in the critical gameplay loop. Every match drops the player into an instant anonymous duel built for fast starts, sharp pressure, and repeat plays.
- The board starts split between your side and the rival side.
- Balls convert enemy tiles on impact.
- Clean paddle returns build a streak and make your touches more dangerous.
- Every match introduces a fresh rival identity and pressure profile.
- After 90 seconds, whoever controls more territory wins the duel.
- Removed all account, auth, matchmaking, storage, and realtime code.
- Rebuilt the main game loop around faster anonymous duel pacing.
- Upgraded the board feel with cleaner rendering, better trails, impact rings, particles, and stronger HUD feedback.
- Moved player progression to a simple on-device stats model.
- Reworked sharing so score cards are created on the fly with no upload step.
- Updated UI copy and metadata so the product no longer claims real multiplayer.
| Layer | Technology |
|---|---|
| Framework | React 18 + TypeScript |
| Build | Vite |
| Styling | Tailwind CSS + custom CSS variables |
| Rendering | HTML5 canvas + requestAnimationFrame |
| Persistence | localStorage |
| Deployment | Vercel |
src/
├── App.tsx # Tiny pathname router + route rendering
├── index.css # Global theme, surface system, shared UI classes
├── components/
│ ├── MainMenu.tsx # Anonymous duel lobby / mode selection
│ ├── SEOPages.tsx # Mode landing pages + how-to-play
│ ├── MoreSEOPages.tsx # FAQ, About, Tips, anonymous duel guide
│ ├── ExtendedSEOPages.tsx # Mechanics guides
│ ├── AdditionalSEOPages.tsx # History, updates, challenges, browser support
│ ├── TargetedSEOPages.tsx # Audience-targeted landing pages
│ ├── MoreTargetedSEOPages.tsx
│ ├── FinalSEOPages.tsx
│ └── SEOFooter.tsx
├── game/
│ ├── GameCanvas.tsx # Canvas shell, HUD, overlays, post-match flow
│ ├── GameLoop.ts # Anonymous duel engine
│ ├── ShareCard.ts # Local share card generation + share fallback
│ ├── PlayerStats.ts # Local-only career stats
│ ├── rivals.ts # Rival persona generation and feed helpers
│ ├── constants.ts # Tuning surface for feel and visuals
│ └── types.ts # Core engine types
└── main.tsx
- Node.js 18+
- npm
git clone https://github.com/slegarraga/combat-pong.git
cd combat-pong
npm installNo environment variables are required.
npm run dev
npm run build
npm run lint
npm run previewsrc/game/GameLoop.ts owns the entire match:
- Creates a rival persona for the selected difficulty.
- Initializes the grid, paddles, and ball set.
- Runs a frame loop that updates AI timing, collisions, tiles, streaks, and effects.
- Emits a lightweight “live duel” feed and fluctuating signal/ping values.
- Keeps React state updates focused on HUD values, while canvas rendering stays imperative.
src/game/rivals.ts generates:
- Rival aliases
- Rival titles and signatures
- Aggression / precision / wobble parameters
- Feed lines for opening pressure, lead changes, clutch moments, and resets
src/game/PlayerStats.ts stores:
- wins / losses
- best board percentage
- best streak
- best margin
- favorite difficulty
- last rival alias
Everything is stored in localStorage.
Good next directions:
- add opt-in audio feedback
- add new rival archetypes
- add alternate board themes
- add daily challenge rulesets
- add accessibility presets for motion and contrast
- Inspired by Pong Wars by Koen van Gilst
- Built with React, Vite, and Tailwind CSS