Initial commit: Multiplayer Snake game with server discovery

Implemented a complete network multiplayer Snake game with the following features:

Core Game:
- Client-server architecture using asyncio for networking
- Pygame-based rendering at 60 FPS
- Server-authoritative game state with 10 TPS
- Collision detection (walls, self, other players)
- Food spawning and score tracking
- Support for multiple players with color-coded snakes

Server Discovery:
- UDP multicast-based automatic server discovery (239.255.0.1:9999)
- Server beacon broadcasts presence every 2 seconds
- Client discovery with 3-second timeout
- Server selection UI for multiple servers
- Auto-connect for single server
- Graceful fallback to manual connection

Project Structure:
- src/shared/ - Protocol, models, constants, discovery utilities
- src/server/ - Game server, game logic, server beacon
- src/client/ - Game client, renderer, discovery, server selector
- tests/ - Unit tests for game logic, models, and discovery

Command-line interface with argparse for both server and client.
Comprehensive documentation in README.md and CLAUDE.md.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Vladyslav Doloman
2025-10-04 13:50:16 +03:00
commit 0703561446
28 changed files with 2523 additions and 0 deletions

47
run_server.py Normal file
View File

@@ -0,0 +1,47 @@
"""Run the Snake game server."""
import asyncio
import argparse
from src.server.game_server import GameServer
from src.shared.constants import DEFAULT_HOST, DEFAULT_PORT
async def main() -> None:
"""Run the server with command line arguments."""
parser = argparse.ArgumentParser(description="Run the Snake game server")
parser.add_argument(
"--host",
default=DEFAULT_HOST,
help=f"Host address to bind to (default: {DEFAULT_HOST})",
)
parser.add_argument(
"--port",
type=int,
default=DEFAULT_PORT,
help=f"Port number to bind to (default: {DEFAULT_PORT})",
)
parser.add_argument(
"--name",
default="Snake Server",
help="Server name for discovery (default: Snake Server)",
)
parser.add_argument(
"--no-discovery",
action="store_true",
help="Disable multicast discovery beacon",
)
args = parser.parse_args()
server = GameServer(
host=args.host,
port=args.port,
server_name=args.name,
enable_discovery=not args.no_discovery,
)
await server.start()
if __name__ == "__main__":
asyncio.run(main())