dcrey7 commited on
Commit
093737e
·
verified ·
1 Parent(s): c5f9032

Update static/js/game.js

Browse files
Files changed (1) hide show
  1. static/js/game.js +145 -58
static/js/game.js CHANGED
@@ -1,4 +1,4 @@
1
- // Initialize Socket.IO connection
2
  const socket = io({
3
  reconnection: true,
4
  reconnectionAttempts: 5,
@@ -7,21 +7,24 @@ const socket = io({
7
 
8
  class Game {
9
  constructor() {
10
- // Core game state
11
  this.state = {
12
  gameId: null,
13
  currentPhase: 'landing',
14
  players: [],
15
  currentQuestion: null,
16
  isRecording: false,
17
- recordingTime: 30,
18
- listeningTime: 60,
19
- votingTime: 60,
 
 
 
20
  maxPlayers: 5,
21
  minPlayers: 3
22
  };
23
 
24
- // Wait for DOM to be loaded
25
  if (document.readyState === 'loading') {
26
  document.addEventListener('DOMContentLoaded', () => this.initialize());
27
  } else {
@@ -30,14 +33,17 @@ class Game {
30
  }
31
 
32
  initialize() {
33
- console.log('Initializing game...');
34
- this.initializeEventListeners();
35
  this.bindUIElements();
 
36
  this.initializeSocketHandlers();
 
37
  this.showPage('landing');
38
  }
39
 
40
  bindUIElements() {
 
 
41
  this.ui = {
42
  gameContainer: document.getElementById('game-container'),
43
  pages: {
@@ -50,42 +56,63 @@ class Game {
50
  },
51
  buttons: {
52
  play: document.getElementById('play-button'),
 
53
  start: document.getElementById('start-button'),
54
- addPlayer: document.getElementById('add-player-button')
55
  },
56
- playerList: document.getElementById('player-list')
 
 
 
 
57
  };
58
  }
59
 
60
  initializeEventListeners() {
61
- // Play button handler
62
- if (this.ui?.buttons.play) {
 
 
63
  this.ui.buttons.play.addEventListener('click', () => this.handlePlayButton());
64
  }
65
 
66
- // Add player button handler
67
- if (this.ui?.buttons.addPlayer) {
68
  this.ui.buttons.addPlayer.addEventListener('click', () => this.addPlayer());
69
  }
70
 
71
- // Start game button handler
72
- if (this.ui?.buttons.start) {
73
  this.ui.buttons.start.addEventListener('click', () => this.startGame());
74
  }
 
 
 
 
 
 
 
75
  }
76
 
77
  initializeSocketHandlers() {
 
78
  socket.on('connect', () => {
79
  console.log('Connected to server');
80
  });
81
 
82
- socket.on('game_created', (data) => {
83
- this.handleGameCreated(data);
 
84
  });
85
 
86
- socket.on('round_start', (data) => {
87
- this.handleRoundStart(data);
88
- });
 
 
 
 
 
 
 
89
  }
90
 
91
  async handlePlayButton() {
@@ -100,25 +127,38 @@ class Game {
100
  }
101
  }
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  addDefaultPlayers() {
104
- // Clear existing players
105
- this.state.players = [];
106
- // Add two default players
107
- this.addPlayer();
108
- this.addPlayer();
109
  this.updatePlayerControls();
110
  }
111
 
112
- addPlayer() {
113
  if (this.state.players.length >= this.state.maxPlayers) {
114
- this.handleError('Maximum player limit reached');
115
  return;
116
  }
117
 
118
- const playerNumber = this.state.players.length + 1;
119
  const newPlayer = {
120
- id: playerNumber,
121
- name: `Player ${playerNumber}`
122
  };
123
 
124
  this.state.players.push(newPlayer);
@@ -127,23 +167,23 @@ class Game {
127
 
128
  socket.emit('join_game', {
129
  gameId: this.state.gameId,
130
- playerName: newPlayer.name
131
  });
132
  }
133
 
134
  updatePlayerList() {
135
- if (!this.ui.playerList) return;
136
 
137
- this.ui.playerList.innerHTML = '';
 
138
 
139
- // Create player grid container
140
  const gridContainer = document.createElement('div');
141
  gridContainer.className = 'player-grid';
142
 
143
  this.state.players.forEach(player => {
144
- const playerElement = document.createElement('div');
145
- playerElement.className = 'player-card';
146
-
147
  const circle = document.createElement('div');
148
  circle.className = 'player-circle';
149
  circle.textContent = player.id;
@@ -152,12 +192,12 @@ class Game {
152
  name.className = 'player-name';
153
  name.textContent = player.name;
154
 
155
- playerElement.appendChild(circle);
156
- playerElement.appendChild(name);
157
- gridContainer.appendChild(playerElement);
158
  });
159
 
160
- this.ui.playerList.appendChild(gridContainer);
161
  }
162
 
163
  updatePlayerControls() {
@@ -172,20 +212,6 @@ class Game {
172
  }
173
  }
174
 
175
- async createGame() {
176
- try {
177
- socket.emit('create_game');
178
- } catch (error) {
179
- console.error('Error creating game:', error);
180
- throw new Error('Failed to create game');
181
- }
182
- }
183
-
184
- handleGameCreated(data) {
185
- console.log('Game created:', data);
186
- this.state.gameId = data.gameId;
187
- }
188
-
189
  async startGame() {
190
  console.log('Starting game...');
191
  try {
@@ -216,6 +242,38 @@ class Game {
216
  this.state.currentQuestion = data.question;
217
  this.state.currentPhase = 'recording';
218
  this.showPage('recording');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  }
220
 
221
  showPage(pageName) {
@@ -231,20 +289,49 @@ class Game {
231
  if (pageToShow) {
232
  pageToShow.classList.add('active');
233
  this.state.currentPhase = pageName;
 
 
234
  }
235
  }
236
 
237
  handleError(message) {
238
- console.error(message);
239
  const errorElement = document.createElement('div');
240
  errorElement.className = 'error-message';
241
  errorElement.textContent = message;
242
  this.ui.gameContainer.appendChild(errorElement);
243
  setTimeout(() => errorElement.remove(), 3000);
244
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  }
246
 
247
- // Initialize the game
248
  document.addEventListener('DOMContentLoaded', () => {
 
249
  window.game = new Game();
250
  });
 
1
+ // Initialize Socket.IO connection with automatic reconnection
2
  const socket = io({
3
  reconnection: true,
4
  reconnectionAttempts: 5,
 
7
 
8
  class Game {
9
  constructor() {
10
+ // Core game state with all necessary properties
11
  this.state = {
12
  gameId: null,
13
  currentPhase: 'landing',
14
  players: [],
15
  currentQuestion: null,
16
  isRecording: false,
17
+ recordingTime: 30, // seconds
18
+ listeningTime: 60, // seconds
19
+ votingTime: 60, // seconds
20
+ recordings: new Map(),
21
+ votes: new Map(),
22
+ impostor: null,
23
  maxPlayers: 5,
24
  minPlayers: 3
25
  };
26
 
27
+ // Initialize if DOM is ready, otherwise wait for it
28
  if (document.readyState === 'loading') {
29
  document.addEventListener('DOMContentLoaded', () => this.initialize());
30
  } else {
 
33
  }
34
 
35
  initialize() {
36
+ console.log('Initializing game components...');
 
37
  this.bindUIElements();
38
+ this.initializeEventListeners();
39
  this.initializeSocketHandlers();
40
+ this.initializeAudioManager();
41
  this.showPage('landing');
42
  }
43
 
44
  bindUIElements() {
45
+ console.log('Binding UI elements...');
46
+ // Cache all UI elements for quick access
47
  this.ui = {
48
  gameContainer: document.getElementById('game-container'),
49
  pages: {
 
56
  },
57
  buttons: {
58
  play: document.getElementById('play-button'),
59
+ addPlayer: document.getElementById('add-player-button'),
60
  start: document.getElementById('start-button'),
61
+ record: document.getElementById('record-button')
62
  },
63
+ displays: {
64
+ timer: document.getElementById('timer-display'),
65
+ question: document.getElementById('question-display'),
66
+ playerList: document.getElementById('player-list')
67
+ }
68
  };
69
  }
70
 
71
  initializeEventListeners() {
72
+ console.log('Setting up event listeners...');
73
+
74
+ // Button event listeners
75
+ if (this.ui.buttons.play) {
76
  this.ui.buttons.play.addEventListener('click', () => this.handlePlayButton());
77
  }
78
 
79
+ if (this.ui.buttons.addPlayer) {
 
80
  this.ui.buttons.addPlayer.addEventListener('click', () => this.addPlayer());
81
  }
82
 
83
+ if (this.ui.buttons.start) {
 
84
  this.ui.buttons.start.addEventListener('click', () => this.startGame());
85
  }
86
+
87
+ if (this.ui.buttons.record) {
88
+ this.ui.buttons.record.addEventListener('click', () => this.toggleRecording());
89
+ }
90
+
91
+ // Handle window resize for responsive layout
92
+ window.addEventListener('resize', () => this.handleResize());
93
  }
94
 
95
  initializeSocketHandlers() {
96
+ // Server connection events
97
  socket.on('connect', () => {
98
  console.log('Connected to server');
99
  });
100
 
101
+ socket.on('disconnect', () => {
102
+ console.log('Disconnected from server');
103
+ this.handleError('Connection lost. Please refresh the page.');
104
  });
105
 
106
+ // Game events
107
+ socket.on('game_created', (data) => this.handleGameCreated(data));
108
+ socket.on('player_joined', (data) => this.handlePlayerJoined(data));
109
+ socket.on('round_start', (data) => this.handleRoundStart(data));
110
+ socket.on('round_result', (data) => this.handleRoundResult(data));
111
+ }
112
+
113
+ initializeAudioManager() {
114
+ // Initialize audio context for recording
115
+ this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
116
  }
117
 
118
  async handlePlayButton() {
 
127
  }
128
  }
129
 
130
+ createGame() {
131
+ return new Promise((resolve, reject) => {
132
+ console.log('Creating new game...');
133
+ socket.emit('create_game');
134
+
135
+ socket.once('game_created', (data) => {
136
+ this.state.gameId = data.gameId;
137
+ console.log('Game created:', data);
138
+ resolve(data);
139
+ });
140
+
141
+ setTimeout(() => reject(new Error('Game creation timeout')), 5000);
142
+ });
143
+ }
144
+
145
  addDefaultPlayers() {
146
+ // Add two default players to start
147
+ this.addPlayer('Player 1');
148
+ this.addPlayer('Player 2');
 
 
149
  this.updatePlayerControls();
150
  }
151
 
152
+ addPlayer(defaultName = null) {
153
  if (this.state.players.length >= this.state.maxPlayers) {
154
+ this.handleError('Maximum players reached');
155
  return;
156
  }
157
 
158
+ const playerName = defaultName || `Player ${this.state.players.length + 1}`;
159
  const newPlayer = {
160
+ id: this.state.players.length + 1,
161
+ name: playerName
162
  };
163
 
164
  this.state.players.push(newPlayer);
 
167
 
168
  socket.emit('join_game', {
169
  gameId: this.state.gameId,
170
+ playerName: playerName
171
  });
172
  }
173
 
174
  updatePlayerList() {
175
+ if (!this.ui.displays.playerList) return;
176
 
177
+ const playerList = this.ui.displays.playerList;
178
+ playerList.innerHTML = '';
179
 
 
180
  const gridContainer = document.createElement('div');
181
  gridContainer.className = 'player-grid';
182
 
183
  this.state.players.forEach(player => {
184
+ const playerCard = document.createElement('div');
185
+ playerCard.className = 'player-card';
186
+
187
  const circle = document.createElement('div');
188
  circle.className = 'player-circle';
189
  circle.textContent = player.id;
 
192
  name.className = 'player-name';
193
  name.textContent = player.name;
194
 
195
+ playerCard.appendChild(circle);
196
+ playerCard.appendChild(name);
197
+ gridContainer.appendChild(playerCard);
198
  });
199
 
200
+ playerList.appendChild(gridContainer);
201
  }
202
 
203
  updatePlayerControls() {
 
212
  }
213
  }
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  async startGame() {
216
  console.log('Starting game...');
217
  try {
 
242
  this.state.currentQuestion = data.question;
243
  this.state.currentPhase = 'recording';
244
  this.showPage('recording');
245
+ this.updateQuestionDisplay();
246
+ this.startTimer(this.state.recordingTime);
247
+ }
248
+
249
+ updateQuestionDisplay() {
250
+ if (this.ui.displays.question && this.state.currentQuestion) {
251
+ this.ui.displays.question.textContent = this.state.currentQuestion;
252
+ }
253
+ }
254
+
255
+ startTimer(duration) {
256
+ let timeLeft = duration;
257
+ this.updateTimerDisplay(timeLeft);
258
+
259
+ this.timer = setInterval(() => {
260
+ timeLeft--;
261
+ this.updateTimerDisplay(timeLeft);
262
+
263
+ if (timeLeft <= 0) {
264
+ clearInterval(this.timer);
265
+ this.handlePhaseEnd();
266
+ }
267
+ }, 1000);
268
+ }
269
+
270
+ updateTimerDisplay(timeLeft) {
271
+ if (this.ui.displays.timer) {
272
+ const minutes = Math.floor(timeLeft / 60);
273
+ const seconds = timeLeft % 60;
274
+ this.ui.displays.timer.textContent =
275
+ `${minutes}:${seconds.toString().padStart(2, '0')}`;
276
+ }
277
  }
278
 
279
  showPage(pageName) {
 
289
  if (pageToShow) {
290
  pageToShow.classList.add('active');
291
  this.state.currentPhase = pageName;
292
+ } else {
293
+ console.error(`Page ${pageName} not found`);
294
  }
295
  }
296
 
297
  handleError(message) {
298
+ console.error('Error:', message);
299
  const errorElement = document.createElement('div');
300
  errorElement.className = 'error-message';
301
  errorElement.textContent = message;
302
  this.ui.gameContainer.appendChild(errorElement);
303
  setTimeout(() => errorElement.remove(), 3000);
304
  }
305
+
306
+ handleResize() {
307
+ // Update any size-dependent UI elements
308
+ if (window.innerWidth < 768) {
309
+ this.ui.gameContainer.classList.add('mobile');
310
+ } else {
311
+ this.ui.gameContainer.classList.remove('mobile');
312
+ }
313
+ }
314
+
315
+ cleanup() {
316
+ // Clear all intervals and timeouts
317
+ if (this.timer) clearInterval(this.timer);
318
+
319
+ // Remove event listeners
320
+ window.removeEventListener('resize', this.handleResize);
321
+
322
+ // Reset game state
323
+ this.state = {
324
+ gameId: null,
325
+ currentPhase: 'landing',
326
+ players: [],
327
+ currentQuestion: null,
328
+ isRecording: false
329
+ };
330
+ }
331
  }
332
 
333
+ // Initialize the game when the DOM is loaded
334
  document.addEventListener('DOMContentLoaded', () => {
335
+ console.log('Initializing game...');
336
  window.game = new Game();
337
  });