Add web client with WebSocket support
Implemented browser-based web client alongside existing pygame desktop client with dual-protocol server architecture supporting both TCP and WebSocket. Backend Changes: - Refactored GameServer for dual-protocol support (TCP + WebSocket) - Added WebSocketHandler for handling WebSocket connections - Added HTTPServer using aiohttp for serving web client files - Updated protocol handling to work with both connection types - Server tracks clients with protocol metadata (TCP/WebSocket) - Protocol-agnostic message sending and broadcasting - Added WebSocket port (8889) and HTTP port (8000) configuration Web Client: - Complete HTML5/CSS/JavaScript implementation - Responsive dark-themed UI - HTML5 Canvas rendering matching pygame visual style - WebSocket connection with auto-detected server URL - Real-time multiplayer gameplay in browser - Player list with scores and status - Mobile-friendly responsive design Deployment Options: - Development: Built-in HTTP server for local testing - Production: Disable HTTP server, use nginx/Apache for static files - Flexible server configuration (--no-http, --no-websocket flags) - Comprehensive nginx/Apache deployment documentation New Files: - src/server/websocket_handler.py - WebSocket connection handler - src/server/http_server.py - Static file server - web/index.html - Web client interface - web/style.css - Responsive styling - web/protocol.js - Protocol implementation - web/game.js - Game client with Canvas rendering - web/README.md - Deployment documentation Updated Files: - requirements.txt - Added websockets and aiohttp dependencies - src/server/game_server.py - Dual-protocol support - src/shared/constants.py - WebSocket and HTTP port constants - run_server.py - Server options for web support - README.md - Web client documentation - CLAUDE.md - Architecture documentation Features: - Web and desktop clients can play together simultaneously - Same JSON protocol for both client types - Independent server components (disable what you don't need) - Production-ready with reverse proxy support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
118
CLAUDE.md
118
CLAUDE.md
@@ -4,12 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a **network multiplayer Snake game** built with Python 3.11, using asyncio for networking, pygame for graphics, and UDP multicast for automatic server discovery.
|
||||
This is a **network multiplayer Snake game** built with Python 3.11, featuring both web and desktop clients with dual-protocol support (TCP + WebSocket).
|
||||
|
||||
**Project Structure:**
|
||||
- `src/shared/` - Shared code (models, protocol, constants, discovery utilities)
|
||||
- `src/server/` - Game server with authoritative game state and multicast beacon
|
||||
- `src/client/` - Game client with pygame rendering, discovery, and server selection UI
|
||||
- `src/server/` - Dual-protocol game server (TCP + WebSocket), HTTP server, multicast beacon
|
||||
- `src/client/` - Pygame desktop client with discovery and server selection UI
|
||||
- `web/` - Browser-based web client (HTML/CSS/JavaScript)
|
||||
- `tests/` - Test files using pytest
|
||||
|
||||
## Setup Commands
|
||||
@@ -30,27 +31,29 @@ pip install -r requirements-dev.txt
|
||||
## Running the Game
|
||||
|
||||
```bash
|
||||
# Start the server (with discovery beacon enabled by default)
|
||||
python run_server.py --name "My Game" --port 8888
|
||||
# Web Client (easiest - no installation needed)
|
||||
python run_server.py --name "My Game"
|
||||
# Open browser to http://localhost:8000
|
||||
|
||||
# Start clients with auto-discovery (no host needed)
|
||||
# Desktop Client (pygame)
|
||||
python run_client.py --name Alice
|
||||
# If multiple servers found, a selection UI appears
|
||||
# Auto-discovers server on local network
|
||||
|
||||
# Manual connection (skip discovery)
|
||||
python run_client.py 192.168.1.100 --port 8888 --name Bob
|
||||
# Server Options:
|
||||
# --host HOST Bind address (default: localhost)
|
||||
# --port PORT TCP port for desktop clients (default: 8888)
|
||||
# --ws-port PORT WebSocket port for web clients (default: 8889, 0=disable)
|
||||
# --http-port PORT HTTP server port (default: 8000, 0=disable)
|
||||
# --name NAME Server name for discovery
|
||||
# --no-discovery Disable multicast beacon
|
||||
# --no-websocket Disable WebSocket server (desktop clients only)
|
||||
# --no-http Disable HTTP server (use nginx/Apache in production)
|
||||
# --web-dir PATH Web files directory (default: web)
|
||||
|
||||
# Server options:
|
||||
# --host HOST Bind address (default: localhost)
|
||||
# --port PORT Port number (default: 8888)
|
||||
# --name NAME Server name for discovery
|
||||
# --no-discovery Disable multicast beacon
|
||||
|
||||
# Client options:
|
||||
# [host] Server host (omit for auto-discovery)
|
||||
# --port PORT Server port
|
||||
# --name NAME Player name
|
||||
# --discover Force discovery mode
|
||||
# Production Deployment:
|
||||
python run_server.py --no-http --host 0.0.0.0
|
||||
# Use nginx to serve web/ directory and proxy WebSocket to port 8889
|
||||
# See web/README.md for nginx configuration examples
|
||||
|
||||
# Press SPACE to start the game, arrow keys/WASD to move
|
||||
```
|
||||
@@ -76,35 +79,54 @@ mypy src/
|
||||
|
||||
## Architecture
|
||||
|
||||
**Client-Server Model:**
|
||||
- Server (`src/server/game_server.py`) runs the authoritative game loop using asyncio
|
||||
- Clients connect via TCP and send input commands (MOVE, START_GAME, etc.)
|
||||
- Server broadcasts game state updates to all connected clients at 10 FPS
|
||||
- Clients render the game state locally at 60 FPS using pygame
|
||||
**Dual-Protocol Client-Server Model:**
|
||||
- Server runs authoritative game loop using asyncio
|
||||
- **Desktop clients** connect via TCP (port 8888) with newline-delimited JSON
|
||||
- **Web clients** connect via WebSocket (port 8889) with JSON frames
|
||||
- Server broadcasts game state updates to all clients at 10 FPS
|
||||
- Desktop clients render at 60 FPS with pygame
|
||||
- Web clients render at 60 FPS with HTML5 Canvas
|
||||
|
||||
**Key Components:**
|
||||
- `src/shared/protocol.py` - JSON-based message protocol (MessageType enum, Message class)
|
||||
- `src/shared/models.py` - Data models (Snake, Position, Food, GameState) with serialization
|
||||
- `src/shared/constants.py` - Game configuration (grid size, colors, tick rate, multicast settings)
|
||||
- `src/shared/discovery.py` - Multicast discovery utilities (ServerInfo, DiscoveryMessage)
|
||||
- `src/server/game_logic.py` - Game rules (movement, collision detection, food spawning)
|
||||
- `src/server/server_beacon.py` - UDP multicast beacon for server discovery
|
||||
- `src/client/renderer.py` - Pygame rendering of game state
|
||||
- `src/client/server_discovery.py` - Client-side server discovery
|
||||
- `src/client/server_selector.py` - Pygame UI for selecting from multiple servers
|
||||
**Key Backend Components:**
|
||||
- `src/shared/protocol.py` - JSON-based message protocol (same for TCP and WebSocket)
|
||||
- `src/shared/models.py` - Data models with serialization (Snake, Position, Food, GameState)
|
||||
- `src/shared/constants.py` - Configuration (grid, colors, tick rate, ports)
|
||||
- `src/shared/discovery.py` - Multicast discovery utilities
|
||||
- `src/server/game_server.py` - Dual-protocol game server (TCP + WebSocket)
|
||||
- `src/server/game_logic.py` - Game rules (movement, collision, food)
|
||||
- `src/server/websocket_handler.py` - WebSocket connection handler
|
||||
- `src/server/http_server.py` - Static file server for web client (aiohttp)
|
||||
- `src/server/server_beacon.py` - UDP multicast beacon
|
||||
|
||||
**Desktop Client Components:**
|
||||
- `src/client/game_client.py` - pygame client with TCP connection
|
||||
- `src/client/renderer.py` - Pygame rendering
|
||||
- `src/client/server_discovery.py` - Multicast discovery
|
||||
- `src/client/server_selector.py` - Server selection UI
|
||||
|
||||
**Web Client Components:**
|
||||
- `web/index.html` - Main HTML interface
|
||||
- `web/style.css` - Responsive styling (dark theme)
|
||||
- `web/protocol.js` - Protocol implementation (JavaScript)
|
||||
- `web/game.js` - Game client with Canvas rendering and WebSocket connection
|
||||
|
||||
**Game Flow:**
|
||||
1. Server starts on port 8888 and broadcasts presence on multicast group 239.255.0.1:9999
|
||||
2. Clients send DISCOVER message to multicast group and collect SERVER_ANNOUNCE responses
|
||||
3. If multiple servers found, client shows selection UI; if one found, auto-connects
|
||||
4. Clients connect via TCP and receive WELCOME message with player_id
|
||||
5. Any player can press SPACE to send START_GAME message
|
||||
6. Server creates snakes for all connected players and spawns food
|
||||
7. Server runs game loop: update positions → check collisions → broadcast state
|
||||
8. Game ends when only 0-1 snakes remain alive
|
||||
1. Server starts TCP (8888), WebSocket (8889), HTTP (8000), and broadcasts on multicast (9999)
|
||||
2. Desktop clients discover via multicast; web clients use auto-detected WebSocket URL
|
||||
3. Clients connect and receive WELCOME with player_id
|
||||
4. Any player presses SPACE to send START_GAME
|
||||
5. Server creates snakes and spawns food
|
||||
6. Server loop: update → check collisions → broadcast state (protocol-agnostic)
|
||||
7. Game ends when ≤1 snake alive
|
||||
|
||||
**Discovery Protocol:**
|
||||
- Multicast group: 239.255.0.1:9999 (local network)
|
||||
- Client → Multicast: DISCOVER (broadcast request)
|
||||
- Server → Client: SERVER_ANNOUNCE (direct response with host, port, name, player count)
|
||||
- Server also periodically broadcasts presence every 2 seconds
|
||||
**Protocol Handling:**
|
||||
- Server stores clients as `(connection, ClientType.TCP|WEBSOCKET)`
|
||||
- `send_to_client()` detects type and sends via appropriate method
|
||||
- TCP: newline-delimited JSON (`message\n`)
|
||||
- WebSocket: JSON frames (native WebSocket message)
|
||||
|
||||
**Production Deployment:**
|
||||
- Run server with `--no-http` flag
|
||||
- Use nginx/Apache to serve `web/` directory
|
||||
- Proxy WebSocket connections to port 8889
|
||||
- See `web/README.md` for configuration examples
|
||||
|
||||
Reference in New Issue
Block a user