8c9697e96bdbf910f45fc7bdbd16e7f5f34a0a54
Corrige los proxies de /api y /ws para apuntar al servidor Colyseus en puerto 2567 en lugar del puerto 3000. Esto resuelve el problema de que las APIs del admin devolvían HTML en lugar de JSON.
Snatch Game - Competitive Clicker
A real-time multiplayer competitive clicker game built with Colyseus.js and Vue 3.
Features
- 🎮 Real-time multiplayer gameplay
- 🏆 10-minute competitive clicking battles
- 👥 2 players per room with automatic matchmaking
- 🎯 Unique player naming system with auto-increment
- 🎛️ Admin dashboard for game management
- 📊 Real-time statistics and monitoring
- 🔄 Automatic reconnection support
- ⏸️ Pause/Resume/Restart game controls
Tech Stack
- Backend: Colyseus.js, Express, TypeScript
- Frontend: Vue 3, Vite, TypeScript
- Real-time: WebSockets
- Styling: Custom CSS
System Architecture
How It Works
The game uses a client-server architecture with WebSocket connections for real-time communication:
1. Connection Flow
Player → Lobby Room → Game Room → Game Session
- Initial Connection: When a player opens the app, they automatically join the
LobbyRoom - Name Assignment: Players receive a unique name (guest, guest-2, etc.) with auto-increment per unique base name
- Matchmaking: Players click "Quick Play" to find or create a game room
- Room Transition: Players leave the lobby and join a
GameRoom(max 2 players) - Game Start: When 2 players are in a room, the game automatically starts
2. Room Management
LobbyRoom:
- Single shared room for all waiting players
- Manages unique player names
- Handles matchmaking requests
- Shows available game rooms
- Tracks which players are in games
GameRoom:
- Individual rooms with exactly 2 players maximum
- Manages game state (waiting, playing, paused, finished)
- 10-minute countdown timer
- Click counting and winner determination
- Auto-restart after game ends
3. State Synchronization
The game uses Colyseus Schema for state management:
GameState {
players: Map<Player> // Connected players
gameStatus: string // waiting|playing|paused|finished
timeRemaining: number // Seconds left in game
winner: string // Winner's name
}
Player {
sessionId: string
name: string
clicks: number
connected: boolean
}
State Updates:
- Server authoritative - only server can modify state
- Automatic synchronization to all clients
- Delta compression - only changes are sent
- 60Hz update rate for real-time feel
4. Communication Protocol
Client → Server Messages:
setName: Change player name in lobbyquickPlay: Request matchmakingclick: Register a click in gamejoinRoom: Join specific room
Server → Client Messages:
gameJoined: Room ID to joinplayerInfo: Player's session infogameStart: Game has startedgameEnd: Game finished with resultsgamePaused: Game pausedgameRestart: Game restarting
State Callbacks:
onAdd: Player joinedonRemove: Player leftonChange: Property changedlisten: Specific field updates
5. Name Management System
Base: "jose"
- First jose → "jose"
- Second jose → "jose-2"
- Third jose → "jose-3"
Base: "maria"
- First maria → "maria"
- Second maria → "maria-2"
- Names are managed by a singleton NameManager
- Each unique base name has its own counter
- Names are released when players disconnect
- Names persist when moving between rooms
6. Game Flow Sequence
-
Lobby Phase:
Connect → Assign Name → Show Online Players → Wait for Action -
Matchmaking:
Quick Play → Find Available Room → No Room? Create New → Join Room -
Waiting Phase:
Join Room → Show "Waiting for opponent" → Display Players (1/2) -
Game Phase:
2 Players Connected → Start Timer → Enable Clicking → Count Clicks -
End Phase:
Timer Reaches 0 → Determine Winner → Show Results → Auto-restart in 5s
7. Reconnection Handling
- 30-second grace period for disconnected players
- Game pauses if a player disconnects during play
- Game resumes when player reconnects
- Maintains click count and game state
8. Admin Dashboard
The dashboard connects via HTTP REST API and WebSocket monitoring:
REST Endpoints (Port 3000):
GET /api/rooms- List all active roomsGET /api/rooms/:id/stats- Get room statisticsPOST /api/rooms/:id/pause- Pause a gamePOST /api/rooms/:id/restart- Restart a gamePOST /api/rooms/:id/kick/:playerId- Kick a player
Real-time Monitoring:
- Total CCU (Concurrent Users)
- Active rooms and their status
- Player statistics per room
- Live game state updates
Installation
# Install all dependencies
npm run install:all
Development
# Start both server and client in development mode
npm run dev
This will start:
- Server on http://localhost:3000
- Client on http://localhost:5173
Environment Variables (Client)
Create client/.env (or copy client/.env.example) to configure endpoints:
VITE_WS_URL=ws://localhost:3000
VITE_API_URL=http://localhost:3000/api
For production over HTTPS, use wss:// for VITE_WS_URL and an HTTPS API base for VITE_API_URL.
URLs
- Game: http://localhost:5173
- Admin Dashboard: http://localhost:5173/dashboard
- Colyseus Monitor: http://localhost:3000/colyseus
- API Endpoints: http://localhost:3000/api
Project Structure
snatchgame/
├── server/ # Backend Colyseus server
│ ├── src/
│ │ ├── rooms/ # Game and Lobby rooms
│ │ ├── schemas/ # State schemas
│ │ ├── utils/ # Utilities (name manager)
│ │ ├── adminApi.ts # Admin REST API
│ │ └── index.ts # Server entry point
│ └── package.json
│
├── client/ # Frontend Vue application
│ ├── src/
│ │ ├── views/ # Vue components (Lobby, Game, Dashboard)
│ │ ├── services/ # Colyseus client service
│ │ ├── router/ # Vue Router
│ │ └── main.ts # App entry point
│ └── package.json
│
└── shared/ # Shared types between client and server
└── types.ts
Game Rules
- Players enter the lobby and choose a username
- Click "Quick Play" to join or create a game room
- Game starts when 2 players join a room
- Players have 10 minutes to click as fast as possible
- The player with the most clicks wins
- Games automatically restart after finishing
Admin Dashboard
The admin dashboard provides:
- View all active rooms and their status
- Pause/Resume games in progress
- Restart games
- Kick players from rooms
- View real-time statistics
- Monitor server performance
API Endpoints
GET /api/rooms- List all active roomsGET /api/rooms/:roomId/stats- Get room statisticsPOST /api/rooms/:roomId/pause- Pause a gamePOST /api/rooms/:roomId/resume- Resume a gamePOST /api/rooms/:roomId/restart- Restart a gamePOST /api/rooms/:roomId/kick/:playerId- Kick a playerGET /api/stats- Get global server statistics
Description
Languages
Vue
66.8%
TypeScript
26.6%
Mermaid
3.2%
Shell
2.2%
JavaScript
0.6%
Other
0.6%