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>
74 lines
2.9 KiB
HTML
74 lines
2.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Multiplayer Snake Game</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<header>
|
|
<h1>🐍 Multiplayer Snake</h1>
|
|
</header>
|
|
|
|
<div id="connection-panel" class="panel">
|
|
<h2>Connect to Server</h2>
|
|
<div class="form-group">
|
|
<label for="player-name">Your Name:</label>
|
|
<input type="text" id="player-name" placeholder="Enter your name" value="Player" maxlength="20">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="server-url">Server URL:</label>
|
|
<input type="text" id="server-url" placeholder="ws://localhost:8889" value="">
|
|
</div>
|
|
<button id="connect-btn" class="btn btn-primary">Connect</button>
|
|
<div id="connection-status" class="status"></div>
|
|
</div>
|
|
|
|
<div id="game-panel" class="panel" style="display: none;">
|
|
<div class="game-area">
|
|
<canvas id="game-canvas"></canvas>
|
|
<div id="game-overlay" class="overlay">
|
|
<div class="overlay-content">
|
|
<h2>Waiting for game to start...</h2>
|
|
<p>Press <kbd>SPACE</kbd> to start the game</p>
|
|
<p>Use <kbd>↑</kbd> <kbd>↓</kbd> <kbd>←</kbd> <kbd>→</kbd> or <kbd>W</kbd> <kbd>A</kbd> <kbd>S</kbd> <kbd>D</kbd> to move</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<aside class="sidebar">
|
|
<div class="score-panel">
|
|
<h3>Players</h3>
|
|
<div id="players-list"></div>
|
|
</div>
|
|
<div class="controls-panel">
|
|
<h3>Controls</h3>
|
|
<div class="control-info">
|
|
<p><kbd>↑</kbd> <kbd>↓</kbd> <kbd>←</kbd> <kbd>→</kbd> Move</p>
|
|
<p><kbd>W</kbd> <kbd>A</kbd> <kbd>S</kbd> <kbd>D</kbd> Move</p>
|
|
<p><kbd>SPACE</kbd> Start Game</p>
|
|
</div>
|
|
<button id="disconnect-btn" class="btn btn-secondary">Disconnect</button>
|
|
</div>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="protocol.js"></script>
|
|
<script src="game.js"></script>
|
|
<script>
|
|
// Auto-detect WebSocket URL
|
|
const wsUrl = document.getElementById('server-url');
|
|
if (window.location.protocol === 'file:') {
|
|
wsUrl.value = 'ws://localhost:8889';
|
|
} else {
|
|
const host = window.location.hostname;
|
|
const port = window.location.port ? parseInt(window.location.port) + 889 : 8889;
|
|
wsUrl.value = `ws://${host}:${port}`;
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|