10
10
11
11
# Pygame Initialization
12
12
pygame .init ()
13
+ pygame .mixer .init () # For sound
13
14
14
15
# Screen dimensions
15
16
WIDTH , HEIGHT = 800 , 600
21
22
BLACK = (0 , 0 , 0 )
22
23
RED = (255 , 0 , 0 )
23
24
BLUE = (0 , 0 , 255 )
25
+ GREEN = (0 , 255 , 0 )
26
+ YELLOW = (255 , 255 , 0 )
27
+
28
+ # Fonts
29
+ font = pygame .font .SysFont ('Arial' , 36 , bold = True )
30
+ title_font = pygame .font .SysFont ('Arial' , 72 , bold = True )
31
+
32
+ # Load win sound effect
33
+ win_sound = pygame .mixer .Sound ("C:\\ Users\\ PAYAL\\ BioAmp-Tool-Python\\ applications\\ brass-fanfare-with-timpani-and-winchimes-reverberated-146260.wav" )
24
34
25
35
# Ball properties
26
36
ball_radius = 20
40
50
41
51
running = True # Game state
42
52
paused = False
53
+ game_started = False
54
+ first_attempt = True # Keeps track if it's the first game or a restart
43
55
44
56
def bandpower (data , sf , band , window_sec = None , relative = False ):
45
57
band = np .asarray (band )
@@ -66,6 +78,7 @@ def eeg_data_thread(eeg_queue):
66
78
return
67
79
68
80
inlet = StreamInlet (streams [0 ])
81
+ channel_assignments = {0 : 'Player A' , 1 : 'Player B' }
69
82
sampling_frequency = 250
70
83
bands = {
71
84
'Delta' : [0.5 , 4 ],
@@ -87,8 +100,8 @@ def eeg_data_thread(eeg_queue):
87
100
try :
88
101
sample , timestamp = inlet .pull_sample ()
89
102
if len (sample ) >= 6 :
90
- channel1_data = sample [0 ] # First channel
91
- channel2_data = sample [1 ] # Second channel
103
+ channel1_data = sample [0 ] # PLAYER A
104
+ channel2_data = sample [1 ] # PLAYER B
92
105
93
106
data_buffer ['Channel1' ].append (channel1_data )
94
107
data_buffer ['Channel2' ].append (channel2_data )
@@ -139,79 +152,159 @@ def eeg_data_thread(eeg_queue):
139
152
eeg_thread .daemon = True
140
153
eeg_thread .start ()
141
154
155
+ def reset_game ():
156
+ global ball_pos , force_player1 , force_player2 , paused , game_started
157
+ ball_pos = [WIDTH // 2 , HEIGHT // 2 ]
158
+ force_player1 = force_player2 = 0
159
+ paused = False # Ensure the game is not paused after reset
160
+ game_started = True # Ensure the game is marked as started
161
+
162
+ # Clear any buffered EEG data
163
+ while not eeg_queue .empty ():
164
+ eeg_queue .get ()
165
+ print ("Empty" )
166
+
142
167
def update_ball_position (force_player1 , force_player2 ):
143
168
global ball_pos
144
- net_force = force_player1 - force_player2
169
+ net_force = force_player2 - force_player1 # force direction
145
170
ball_pos [0 ] += net_force * ball_speed * 0.01
146
-
147
- if ball_pos [0 ] < ball_radius : # Keep the ball within the screen bounds
171
+ if ball_pos [0 ] < ball_radius :
148
172
ball_pos [0 ] = ball_radius
149
173
elif ball_pos [0 ] > WIDTH - ball_radius :
150
174
ball_pos [0 ] = WIDTH - ball_radius
151
175
152
- def restart_game ():
153
- global ball_pos , force_player1 , force_player2
154
- ball_pos [0 ] = WIDTH // 2
155
- ball_pos [1 ] = HEIGHT // 2
156
- force_player1 = 0
157
- force_player2 = 0
158
-
159
- # Initial forces
160
- force_player1 = 0
161
- force_player2 = 0
162
-
163
- while running :
164
- for event in pygame .event .get ():
165
- if event .type == pygame .QUIT :
166
- running = False
167
- pygame .quit ()
168
- sys .exit ()
169
-
170
- # Handle key presses for pause and restart
171
- if event .type == pygame .KEYDOWN :
172
- if event .key == pygame .K_p : # Pause
173
- paused = not paused
174
- elif event .key == pygame .K_r : # Restart
175
- restart_game ()
176
- elif event .key == pygame .K_q : # Quit
177
- running = False
178
-
179
- if not paused :
180
- # Handle keyboard input
181
- keys = pygame .key .get_pressed ()
182
- if keys [pygame .K_LEFT ]:
183
- force_player1 += 0.1 # Apply a small force to player 1
184
- elif keys [pygame .K_RIGHT ]:
185
- force_player1 -= 0.1 # Apply a small force to player 1
186
-
187
- # Update forces from EEG data
188
- if not eeg_queue .empty ():
189
- force_player1_eeg , force_player2_eeg = eeg_queue .get ()
190
- force_player1 += force_player1_eeg
191
- force_player2 += force_player2_eeg
192
-
193
- update_ball_position (force_player1 , force_player2 )
194
-
195
- # Drawing
176
+ print (f"Force Player 1: { force_player1 :.2f} , Force Player 2: { force_player2 :.2f} , Net Force: { net_force :.2f} " ) # Print the forces to the console
177
+
178
+ def handle_input ():
179
+ global force_player1 , force_player2
180
+ keys = pygame .key .get_pressed ()
181
+
182
+ if keys [pygame .K_LEFT ]:
183
+ force_player1 += 0.25
184
+ if keys [pygame .K_RIGHT ]:
185
+ force_player2 += 0.25
186
+
187
+ def draw_buttons (paused , first_attempt ): # Button dimensions and positions
188
+ button_width = 120
189
+ button_height = 40
190
+ button_radius = 15 # Radius for rounded corners
191
+
192
+ # Button positions (y-position is moved up slightly for a better fit)
193
+ start_button_rect = pygame .Rect (WIDTH // 4 - button_width // 2 , HEIGHT - 80 , button_width , button_height )
194
+ resume_pause_button_rect = pygame .Rect (WIDTH // 2 - button_width // 2 , HEIGHT - 80 , button_width , button_height )
195
+ exit_button_rect = pygame .Rect (3 * WIDTH // 4 - button_width // 2 , HEIGHT - 80 , button_width , button_height )
196
+
197
+ # Draw buttons
198
+ pygame .draw .rect (screen , GREEN , start_button_rect , border_radius = button_radius ) # Start/Restart Button
199
+ pygame .draw .rect (screen , YELLOW , resume_pause_button_rect , border_radius = button_radius ) # Resume/Pause Button
200
+ pygame .draw .rect (screen , RED , exit_button_rect , border_radius = button_radius ) # Exit Button
201
+
202
+ # Button Texts
203
+ start_text = font .render ("Restart" if not first_attempt else "Start" , True , BLACK )
204
+ resume_pause_text = font .render ("Resume" if paused else "Pause" , True , BLACK )
205
+ exit_text = font .render ("Exit" , True , BLACK )
206
+
207
+ # Calculate text positions for proper centering inside each button
208
+ start_text_pos = (start_button_rect .x + (button_width - start_text .get_width ()) // 2 ,
209
+ start_button_rect .y + (button_height - start_text .get_height ()) // 2 )
210
+
211
+ resume_pause_text_pos = (resume_pause_button_rect .x + (button_width - resume_pause_text .get_width ()) // 2 ,
212
+ resume_pause_button_rect .y + (button_height - resume_pause_text .get_height ()) // 2 )
213
+
214
+ exit_text_pos = (exit_button_rect .x + (button_width - exit_text .get_width ()) // 2 ,
215
+ exit_button_rect .y + (button_height - exit_text .get_height ()) // 2 )
216
+
217
+ # Draw texts
218
+ screen .blit (start_text , start_text_pos )
219
+ screen .blit (resume_pause_text , resume_pause_text_pos )
220
+ screen .blit (exit_text , exit_text_pos )
221
+
222
+ def draw_players ():
223
+ # Draw Player A
224
+ pygame .draw .rect (screen , BLUE , (player1_pos [0 ], player1_pos [1 ], player_width , player_height )) # Player A
225
+ player_a_label = font .render ("A" , True , WHITE )
226
+ screen .blit (player_a_label , (player1_pos [0 ] - 30 , player1_pos [1 ] + player_height // 2 - player_a_label .get_height () // 2 )) # Position label next to Player A
227
+
228
+ # Draw Player B
229
+ pygame .draw .rect (screen , RED , (player2_pos [0 ], player2_pos [1 ], player_width , player_height )) # Player B
230
+ player_b_label = font .render ("B" , True , WHITE )
231
+ screen .blit (player_b_label , (player2_pos [0 ] + player_width + 10 , player2_pos [1 ] + player_height // 2 - player_b_label .get_height () // 2 )) # Position label next to Player B
232
+
233
+ def check_win_condition ():
234
+ if ball_pos [0 ] <= ball_radius :
235
+ return "PLAYER A WINS!"
236
+ elif ball_pos [0 ] >= WIDTH - ball_radius :
237
+ return "PLAYER B WINS!"
238
+ return None
239
+
240
+ def main ():
241
+ global paused , game_started , first_attempt
242
+ force_player1 = force_player2 = 0
243
+ win_text = None # Initialize win text
244
+ latest_data = (0 , 0 ) # To store the latest EEG data for both players
245
+
246
+ while True :
196
247
screen .fill (BLACK )
197
- pygame .draw .rect (screen , RED , (* player1_pos , player_width , player_height ))
198
- pygame .draw .rect (screen , BLUE , (* player2_pos , player_width , player_height ))
199
- pygame .draw .circle (screen , ball_color , (int (ball_pos [0 ]), int (ball_pos [1 ])), ball_radius )
200
248
201
- # Print net forces
202
- print (f"Net Force - Player 1: { force_player1 :.4f} , Player 2: { force_player2 :.4f} " )
249
+ pygame .draw .circle (screen , ball_color , (int (ball_pos [0 ]), int (ball_pos [1 ])), ball_radius ) # Draw the ball
250
+
251
+ for event in pygame .event .get ():
252
+ if event .type == pygame .QUIT :
253
+ pygame .quit ()
254
+ sys .exit ()
255
+
256
+ if event .type == pygame .KEYDOWN :
257
+ if event .key == pygame .K_ESCAPE :
258
+ pygame .quit ()
259
+ sys .exit ()
260
+
261
+ if event .type == pygame .MOUSEBUTTONDOWN :
262
+ mouse_pos = pygame .mouse .get_pos ()
263
+ if event .button == 1 : # Left mouse button
264
+ # Check if the mouse click is within the bounds of any button
265
+ if pygame .Rect (WIDTH // 4 - 60 , HEIGHT - 80 , 120 , 40 ).collidepoint (mouse_pos ):
266
+ # Start or restart the game
267
+ reset_game ()
268
+ game_started = True
269
+ first_attempt = False
270
+ win_text = None # Reset win text on new game
271
+ elif pygame .Rect (WIDTH // 2 - 60 , HEIGHT - 80 , 120 , 40 ).collidepoint (mouse_pos ):
272
+ # Pause/Resume the game
273
+ paused = not paused
274
+ elif pygame .Rect (3 * WIDTH // 4 - 60 , HEIGHT - 80 , 120 , 40 ).collidepoint (mouse_pos ):
275
+ pygame .quit ()
276
+ sys .exit ()
277
+
278
+ if game_started :
279
+ if not paused :
280
+ handle_input ()
281
+ if not eeg_queue .empty ():
282
+ force_player1 , force_player2 = eeg_queue .get ()
283
+ latest_data = (force_player1 , force_player2 ) # Store latest data
284
+
285
+ update_ball_position (force_player1 , force_player2 )
286
+ else :
287
+ force_player1 = force_player2 = 0 # When paused, stop the ball movement
288
+
289
+ draw_players ()
290
+ draw_buttons (paused , first_attempt )
291
+
292
+ if game_started :
293
+ win_text = check_win_condition ()
294
+ if win_text :
295
+ win_sound .play () # Play sound on win
296
+ paused = True # Automatically pause the game on win
297
+ while not eeg_queue .empty ():
298
+ eeg_queue .get ()
299
+ force_player1 , force_player2 = latest_data # Store the latest data when the game is won
300
+
301
+ # Draw win text if there is a winner
302
+ if win_text :
303
+ win_display = font .render (win_text , True , WHITE )
304
+ screen .blit (win_display , (WIDTH // 2 - win_display .get_width () // 2 , HEIGHT // 2 - win_display .get_height () // 2 ))
203
305
204
306
pygame .display .flip ()
205
307
clock .tick (60 ) # 60 frames per second
206
308
207
- # Check for a win condition
208
- if ball_pos [0 ] < player1_pos [0 ] + player_width and ball_pos [1 ] >= player1_pos [1 ] and ball_pos [1 ] <= player1_pos [1 ] + player_height :
209
- print ("Player 2 wins!" )
210
- pygame .time .wait (3000 ) # Wait for 3 seconds before restarting
211
- restart_game ()
212
- elif ball_pos [0 ] > player2_pos [0 ] - ball_radius and ball_pos [1 ] >= player2_pos [1 ] and ball_pos [1 ] <= player2_pos [1 ] + player_height :
213
- print ("Player 1 wins!" )
214
- pygame .time .wait (3000 ) # Wait for 3 seconds before restarting
215
- restart_game ()
216
-
217
- pygame .quit ()
309
+ if __name__ == "__main__" :
310
+ main ()
0 commit comments