This is a real-time Pictionary game developed with a Python (FastAPI) backend and a React (TypeScript) frontend.
The solution is divided into two main components:
- Backend: A Python server based on FastAPI that manages the game logic, player connections, and real-time communication via WebSockets.
- Frontend: A Single Page Application (SPA) built with React and TypeScript, which provides the user interface for drawing, guessing, and interacting with the game.
- Real-time communication with WebSockets.
- Interactive drawing canvas.
- Turn-based system for drawing.
- Chat for submitting guesses.
- Dynamic game state updates for all players.
Backend:
- Python 3.10+
- FastAPI
- WebSockets
- Uvicorn (ASGI server)
Frontend:
- React
- TypeScript
- Tailwind CSS
- Create React App
/
├── backend/
│ ├── main.py # Main server logic and WebSocket
│ ├── game.py # Class that manages game logic
│ ├── connection_manager.py # WebSocket connection manager
│ ├── words.json # List of words for the game
│ └── ...
├── frontend/
│ ├── src/ # React components source code
│ ├── public/ # Static files
│ ├── package.json # Frontend dependencies and scripts
│ └── ...
└── README.md # This file
The backend exposes a WebSocket endpoint for real-time communication.
-
WebSocket Endpoint:
ws://localhost:8000/ws/{client_id}
The
client_id
is a unique identifier for each player.
Messages are sent as JSON strings.
-
Set Player Name
{ "type": "set_name", "name": "PlayerName" }
-
Drawing Actions (sent only by the current drawer)
// Start drawing { "type": "start", "payload": { "x": 10, "y": 20 } } // Draw { "type": "draw", "payload": { "x": 50, "y": 60 } } // End drawing { "type": "end" }
-
Send Guess
{ "type": "guess", "payload": "word" }
-
Game State Update
{ "type": "game_state", "drawer_name": "PlayerDrawing", "is_drawing": true, // or false "word": "w _ r d" // or "word" for the drawer }
-
General Notifications
{ "type": "notification", "message": "PlayerName guessed the word!" }
-
Chat Messages
{ "type": "chat", "sender_name": "PlayerGuessing", "message": "Could it be...?" }