Skip to content

Commit ff0f0b9

Browse files
authored
Merge pull request #4 from paramsgit/wait-card
Wait card
2 parents f3858b0 + 756b126 commit ff0f0b9

19 files changed

Lines changed: 1190 additions & 30 deletions

README.md

Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
# Scribble - Real-Time Multiplayer Drawing & Guessing Game
2+
3+
A full-stack real-time multiplayer drawing and guessing game built with React, Node.js, Socket.IO, and Redis. Players take turns drawing words while others guess, with real-time synchronization, scoring, and AI-powered drawing recognition.
4+
5+
## 🎮 Features
6+
7+
- **Real-Time Multiplayer Gameplay**: Up to 6 players per room with live drawing synchronization
8+
- **Interactive Drawing Board**: Canvas-based drawing with color selection, undo functionality, and eraser tool
9+
- **Word Guessing System**: Players guess the word being drawn with real-time feedback
10+
- **Scoring System**: Dynamic scoring based on how quickly players guess correctly
11+
- **Room Management**: Automatic room creation and player matching
12+
- **Game States**: State machine pattern with Waiting, Drawing, and Finished states
13+
- **Persistent State**: Redis-based game state persistence with automatic TTL management
14+
- **Responsive UI**: Modern, responsive design built with React and Tailwind CSS
15+
16+
## 🛠️ Tech Stack
17+
18+
### Backend
19+
20+
- **Node.js** with **Express** - RESTful API server
21+
- **TypeScript** - Type-safe development
22+
- **Socket.IO** - Real-time bidirectional communication
23+
- **Redis** (ioredis) - State persistence and room management
24+
- **Docker** - Containerization
25+
26+
### Frontend
27+
28+
- **React 19** - UI framework
29+
- **TypeScript** - Type-safe development
30+
- **Vite** - Build tool and dev server
31+
- **React Router** - Client-side routing
32+
- **Tailwind CSS** - Utility-first CSS framework
33+
- **Socket.IO Client** - Real-time communication
34+
- **Canvas API** - Drawing functionality
35+
36+
## 📁 Project Structure
37+
38+
```
39+
scribble/
40+
├── backend/
41+
│ ├── src/
42+
│ │ ├── app.ts # Express app configuration
43+
│ │ ├── server.ts # Server entry point
44+
│ │ ├── controllers/ # API controllers
45+
│ │ │ ├── apiController.ts
46+
│ │ │ └── drawingGuesser.ts # AI drawing recognition
47+
│ │ ├── game/ # Game logic
48+
│ │ │ ├── game.ts # Core game class
49+
│ │ │ ├── gameManager.ts # Game instance management
50+
│ │ │ ├── roomManager.ts # Room and player management
51+
│ │ │ └── states/ # Game state machine
52+
│ │ │ ├── gameState.ts
53+
│ │ │ ├── waitingState.ts
54+
│ │ │ ├── drawingState.ts
55+
│ │ │ └── finishedState.ts
56+
│ │ ├── sockets/ # Socket.IO handlers
57+
│ │ │ ├── socketManager.ts
58+
│ │ │ ├── handleSocketConnection.ts
59+
│ │ │ └── connectToRedis.ts
60+
│ │ ├── routes/ # API routes
61+
│ │ └── middleware/ # Express middleware
62+
│ ├── config/ # Configuration
63+
│ ├── Dockerfile
64+
│ └── docker-compose.yml
65+
66+
└── frontend/
67+
├── src/
68+
│ ├── App.tsx # Main app component
69+
│ ├── pages/ # Page components
70+
│ │ ├── Home.tsx
71+
│ │ └── Game.tsx
72+
│ ├── components/ # React components
73+
│ │ ├── composed/ # Composite components
74+
│ │ └── game/ # Game-specific components
75+
│ │ ├── DrawingBoard.tsx
76+
│ │ ├── ChatContainer.tsx
77+
│ │ ├── Players.tsx
78+
│ │ └── GameLayout.tsx
79+
│ ├── context/ # React context providers
80+
│ ├── utils/ # Utility functions
81+
│ └── config/ # Frontend configuration
82+
├── Dockerfile
83+
└── docker-compose.yml
84+
```
85+
86+
## 🚀 Getting Started
87+
88+
### Prerequisites
89+
90+
- **Node.js** (v20 or higher)
91+
- **npm** or **yarn**
92+
- **Redis** (for local development) or Docker
93+
- **Docker** and **Docker Compose** (optional, for containerized deployment)
94+
95+
### Installation
96+
97+
1. **Clone the repository**
98+
99+
```bash
100+
git clone <repository-url>
101+
cd scribble
102+
```
103+
104+
2. **Install backend dependencies**
105+
106+
```bash
107+
cd backend
108+
npm install
109+
```
110+
111+
3. **Install frontend dependencies**
112+
```bash
113+
cd ../frontend
114+
npm install
115+
```
116+
117+
### Environment Setup
118+
119+
1. **Backend Environment Variables**
120+
121+
Create a `.env` file in the `backend/` directory:
122+
123+
```env
124+
PORT=5000
125+
NODE_ENV=development
126+
CORS_ORIGIN=http://localhost:5173
127+
REDIS_URL=redis://localhost:6379
128+
```
129+
130+
2. **Frontend Configuration**
131+
132+
Update the socket connection URL in `frontend/src/utils/socket.ts` if needed:
133+
134+
```typescript
135+
SocketManager.instance = io("http://localhost:5000/");
136+
```
137+
138+
### Running Locally
139+
140+
#### Option 1: Run with Docker Compose (Recommended)
141+
142+
**Backend:**
143+
144+
```bash
145+
cd backend
146+
docker-compose up
147+
```
148+
149+
**Frontend:**
150+
151+
```bash
152+
cd frontend
153+
docker-compose up
154+
```
155+
156+
#### Option 2: Run Manually
157+
158+
1. **Start Redis** (if not using Docker)
159+
160+
```bash
161+
redis-server
162+
```
163+
164+
2. **Start Backend Server**
165+
166+
```bash
167+
cd backend
168+
npm run dev
169+
```
170+
171+
Server will run on `http://localhost:5000`
172+
173+
3. **Start Frontend Development Server**
174+
175+
```bash
176+
cd frontend
177+
npm run dev
178+
```
179+
180+
Frontend will run on `http://localhost:5173`
181+
182+
4. **Open your browser**
183+
Navigate to `http://localhost:5173`
184+
185+
### Building for Production
186+
187+
**Backend:**
188+
189+
```bash
190+
cd backend
191+
npm run build
192+
npm start
193+
```
194+
195+
**Frontend:**
196+
197+
```bash
198+
cd frontend
199+
npm run build
200+
npm run preview
201+
```
202+
203+
## 🎯 How to Play
204+
205+
1. **Join a Room**: Enter your name and avatar, then join or create a room
206+
2. **Wait for Players**: Game starts automatically when 2+ players join
207+
3. **Take Turns Drawing**: Each player gets a turn to draw a word
208+
4. **Guess the Word**: Other players try to guess what's being drawn
209+
5. **Score Points**: Faster guesses earn more points
210+
6. **Win**: Player with the highest score wins!
211+
212+
## 🏗️ Architecture
213+
214+
### Game State Machine
215+
216+
The game uses a state machine pattern with three main states:
217+
218+
- **WaitingState**: Waiting for players to join or between rounds
219+
- **DrawingState**: Active drawing and guessing phase
220+
- **FinishedState**: Game completion
221+
222+
### Real-Time Communication
223+
224+
- **Socket.IO Events**:
225+
- `join-room`: Player joins a game room
226+
- `draw-command`: Drawing strokes synchronized in real-time
227+
- `guess`: Player submits a guess
228+
- `room-update`: Room player list updates
229+
- `word-update`: New word/round starts
230+
- `correct-guess`: Player guessed correctly
231+
232+
### Data Persistence
233+
234+
- **Redis** stores:
235+
236+
- Game state (serialized game objects)
237+
- Room player lists
238+
- Player-to-room mappings
239+
- Active rooms set
240+
241+
- **TTL Management**: Automatic expiration (1-2 hours) for cleanup
242+
243+
### Drawing System
244+
245+
- **Command Pattern**: Drawing operations use command pattern for undo functionality
246+
- **Debounced Emission**: Drawing commands are debounced before sending to reduce network traffic
247+
- **Canvas Rendering**: HTML5 Canvas API for drawing operations
248+
249+
## 🔧 Configuration
250+
251+
### Game Settings
252+
253+
Edit `backend/config/index.ts`:
254+
255+
```typescript
256+
gameTime: 20, // Drawing time per round (seconds)
257+
waitTime: 10, // Wait time between rounds (seconds)
258+
```
259+
260+
### CORS Settings
261+
262+
Configure allowed origins in `backend/config/index.ts`:
263+
264+
```typescript
265+
corsOrigin: process.env.CORS_ORIGIN || "*";
266+
```
267+
268+
## 📡 API Endpoints
269+
270+
### REST API
271+
272+
- `GET /api/sample` - Sample data endpoint
273+
- `POST /api/guess` - Submit drawing image for AI recognition
274+
- Body: `multipart/form-data` with `image` file
275+
- Response: `{ message: "recognized word" }`
276+
277+
### Socket.IO Events
278+
279+
See the "Real-Time Communication" section above for event details.
280+
281+
## 🧪 Development
282+
283+
### Scripts
284+
285+
**Backend:**
286+
287+
- `npm run dev` - Start development server with nodemon
288+
- `npm run build` - Compile TypeScript
289+
- `npm run watch` - Watch mode for TypeScript compilation
290+
- `npm start` - Start production server
291+
292+
**Frontend:**
293+
294+
- `npm run dev` - Start Vite dev server
295+
- `npm run build` - Build for production
296+
- `npm run preview` - Preview production build
297+
- `npm run lint` - Run ESLint
298+
299+
## 🐳 Docker Deployment
300+
301+
### Backend Docker
302+
303+
```bash
304+
cd backend
305+
docker-compose up -d
306+
```
307+
308+
Includes:
309+
310+
- Node.js application container
311+
- Redis container
312+
- Automatic dependency management
313+
314+
### Frontend Docker
315+
316+
```bash
317+
cd frontend
318+
docker-compose up -d
319+
```
320+
321+
Includes:
322+
323+
- Multi-stage build (Node.js build + Nginx serve)
324+
- Nginx configuration for static file serving
325+
- Production-optimized build
326+
327+
## 🔐 Security Notes
328+
329+
- **API Keys**: The Google Gemini API key is currently hardcoded in `drawingGuesser.ts`. Move this to environment variables in production.
330+
- **CORS**: Configure appropriate CORS origins for production
331+
- **Redis**: Secure Redis instance in production (password, network isolation)
332+
333+
## 🚧 Future Enhancements
334+
335+
- [ ] User authentication and profiles
336+
- [ ] Custom word lists and categories
337+
- [ ] Private rooms with passwords
338+
- [ ] Spectator mode
339+
- [ ] Drawing history and replays
340+
- [ ] Mobile app support
341+
- [ ] Enhanced AI drawing analysis
342+
- [ ] Leaderboards and statistics
343+
- [ ] Custom avatars and themes
344+
345+
## 📝 License
346+
347+
ISC
348+
349+
## 👥 Contributing
350+
351+
Contributions are welcome! Please feel free to submit a Pull Request.
352+
353+
## 📧 Contact
354+
355+
For questions or support, please open an issue on the repository.
356+
357+
---

backend/config/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interface Config {
1313
const config: Config = {
1414
port: parseInt(process.env.PORT || "3000", 10),
1515
nodeEnv: process.env.NODE_ENV || "development",
16-
corsOrigin: process.env.CORS_ORIGIN || "http://localhost:3000",
16+
corsOrigin: process.env.CORS_ORIGIN || "*",
1717
gameTime: 20,
1818
waitTime: 10,
1919
};

backend/dump.rdb

88 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)