A lightweight, browser-based 2D top-down shooter where players join a single shared arena, compete in real-time combat, and climb the leaderboard.
- React 18 with TypeScript
- HTML5 Canvas for rendering
- Zustand for state management
- Socket.io-client for real-time communication
- Vite for fast development
- Tailwind CSS for styling
- Node.js with TypeScript
- Express.js server
- Socket.io for WebSocket communication
- 60 TPS game loop
- Node.js 20+
- npm or yarn
- Install dependencies for all workspaces:
npm install- Start the development servers:
Option 1: Start both servers together
npm run devOption 2: Start servers separately
Terminal 1 (Server):
cd server
npm run devTerminal 2 (Client):
cd client
npm run dev- Client: http://localhost:5173
- Server: http://localhost:3001
- WASD - Move your character
- Mouse - Aim your weapon
- Left Click - Shoot
- TAB - Toggle leaderboard
voxelwars/
├── client/ # React frontend
│ ├── src/
│ │ ├── components/ # React components
│ │ │ ├── UI/ # UI components (HUD, Leaderboard, StartScreen)
│ │ │ ├── Game.tsx # Main game component
│ │ │ └── Canvas.tsx # Canvas renderer
│ │ ├── game/ # Game logic
│ │ │ ├── renderer.ts # Canvas drawing
│ │ │ ├── input.ts # Input handling
│ │ │ ├── interpolation.ts # Smooth movement
│ │ │ └── particles.ts # Effects system
│ │ ├── network/ # Socket.io client
│ │ ├── store/ # Zustand state management
│ │ └── types/ # TypeScript types
│ └── package.json
│
├── server/ # Node.js backend
│ ├── src/
│ │ ├── game/ # Game engine
│ │ │ ├── GameEngine.ts # Main game loop
│ │ │ ├── Player.ts # Player entity
│ │ │ ├── Bullet.ts # Bullet entity
│ │ │ ├── World.ts # World state
│ │ │ ├── Physics.ts # Collision detection
│ │ │ └── Terrain.ts # Map generation
│ │ ├── network/ # Socket.io server
│ │ ├── services/ # Services (Leaderboard)
│ │ └── types/ # TypeScript types
│ └── package.json
│
└── shared/ # Shared types between client/server
└── types/
└── index.ts # Common interfaces
- Real-time multiplayer combat
- 8-directional movement (WASD)
- Mouse-aim shooting
- Health system (100 HP)
- Respawn system (3 seconds)
- Scoring (+10 per kill, -5 on death)
- Walls: Solid obstacles that block movement and bullets
- Crates: Destructible cover (50 HP)
- Bushes: Visual cover (semi-transparent, bullets pass through)
- Top-down 2D perspective
- Minimalist geometric shapes
- Color-coded players (unique hue per player)
- Health bars above players
- Minimap in corner
- Bullet trails and effects
- Real-time synchronization
- Client-side prediction
- Server-authoritative physics
- Interpolation for smooth rendering
- Live leaderboard (top 10 players)
- Player count display
npm run buildClient:
cd client
npm run buildServer:
cd server
npm run build
npm startVITE_SERVER_URL=http://localhost:3001
PORT=3001
CORS_ORIGIN=http://localhost:5173
- Setup monorepo with client/server
- WebSocket connection established
- Basic player join/disconnect
- Canvas rendering
- Player movement (WASD)
- Player shooting (mouse)
- Bullet physics
- Collision detection
- Health/damage system
- Client-side prediction
- Server reconciliation
- Interpolation for remote players
- Generate static map
- Walls, crates, bushes
- Destructible objects
- Collision with terrain
- Leaderboard implementation
- HUD (health, score)
- Death/respawn animations
- Minimap
- Particle effects for impacts
- Audio feedback
- Power-ups (health, speed boost)
- Multiple game modes
- Persistent stats with Redis
- Client FPS: 60 (target) / 45 (minimum)
- Server TPS: 60 (target) / 30 (minimum)
- Network latency: <50ms (target) / <150ms (maximum)
- Max players per room: 30 (target) / 50 (maximum)
- Bundle size (gzipped): <150KB (target) / <300KB (maximum)
- Initial load time: <2s (target) / <4s (maximum)
This is a learning project following the technical specification in CLAUDE.md.
MIT