6
6
from scipy .signal import iirnotch , butter , lfilter
7
7
import math
8
8
9
- pygame .init ()
10
-
11
- # Screen setup
12
- screen = pygame .display .set_mode ((800 , 600 ))
13
- pygame .display .set_caption ('Beetle Game' )
14
-
15
- # Beetle properties
16
- beetle_x , beetle_y = 380 , 530
17
- focus_speed_upward = 8 # Speed when moving upward
18
- focus_speed_downward = 4 # Speed when moving downward
19
- focus_timeout = 2 # Time in seconds to stabilize focus
20
- focus_threshold = 5 # Threshold for beta power
21
-
22
- # LSL stream setup
9
+ # Initialize LSL stream
23
10
streams = resolve_stream ('name' , 'BioAmpDataStream' )
24
11
if not streams :
25
12
print ("No LSL stream found!" )
26
- pygame .quit ()
27
13
exit ()
28
14
29
15
inlet = StreamInlet (streams [0 ])
30
16
print ("LSL Stream Started" )
31
17
sampling_rate = int (inlet .info ().nominal_srate ())
32
18
print (f"Sampling rate: { sampling_rate } Hz" )
33
19
34
- b_notch , a_notch = iirnotch (50.0 / (500 / 2 ), 30.0 )
35
- b_band , a_band = butter (4 , [0.5 / (sampling_rate / 2 ), 48.0 / (sampling_rate / 2 )], btype = 'band' )
20
+ b_notch , a_notch = iirnotch (50.0 / (sampling_rate / 2 ), 30.0 )
21
+ b_band , a_band = butter (4 , [0.5 / (sampling_rate / 2 ), 48.0 / (sampling_rate / 2 )], btype = 'band' )
36
22
37
23
# Buffer for EEG data and Focus tracking variables
38
24
buffer = []
39
25
buffer_size = 500
40
- focus_timer = 0
41
- last_focus_time = time .time ()
42
- last_time = time .time ()
43
26
44
- # Load the beetle image
45
- beetle_image = pygame .image .load ('beetle.jpg' )
27
+ # Beetle properties
28
+ beetle_x , beetle_y = 380 , 530
29
+ focus_speed_upward = 15
30
+ focus_speed_downward = 5
31
+ focus_timeout = 2
32
+ focus_threshold = None
33
+
34
+ # Initialize Pygame
35
+ pygame .init ()
36
+ screen = pygame .display .set_mode ((800 , 600 ))
37
+ pygame .display .set_caption ('Beetle Game' )
38
+
39
+ # Load beetle image
40
+ beetle_image = pygame .image .load ('media\\ beetle.jpg' )
46
41
beetle_image = pygame .transform .scale (beetle_image , (80 , 80 ))
47
42
48
- # Function to apply filters
43
+ # Function to display a message on the screen
44
+ def show_message (message , duration = 3 ):
45
+ start_time = time .time ()
46
+ font = pygame .font .Font (None , 50 )
47
+ text = font .render (message , True , (0 , 0 , 0 ))
48
+ text_rect = text .get_rect (center = (400 , 300 ))
49
+
50
+ while time .time () - start_time < duration :
51
+ screen .fill ((255 , 255 , 255 ))
52
+ screen .blit (text , text_rect )
53
+ pygame .display .update ()
54
+
55
+ # Apply filters
49
56
def apply_filters (eeg_point ):
50
57
filtered = lfilter (b_notch , a_notch , [eeg_point ])
51
58
filtered_point = lfilter (b_band , a_band , filtered )
52
59
return filtered_point [0 ]
53
60
54
61
def calculate_focus_level (eeg_data , sampling_rate = 500 ):
55
- window = np .hanning (len (eeg_data )) # Apply a Hanning window
62
+ window = np .hanning (len (eeg_data ))
56
63
eeg_data_windowed = eeg_data * window
57
64
fft_data = np .abs (np .fft .fft (eeg_data_windowed ))[:len (eeg_data_windowed ) // 2 ]
58
65
fft_data /= len (eeg_data_windowed )
59
66
freqs = np .fft .fftfreq (len (eeg_data_windowed ), d = 1 / sampling_rate )[:len (eeg_data_windowed ) // 2 ]
60
67
61
- # Compute power in different bands
62
68
delta_power = math .sqrt (np .sum ((fft_data [(freqs >= 0.5 ) & (freqs <= 4 )]) ** 2 ))
63
69
theta_power = math .sqrt (np .sum ((fft_data [(freqs >= 4 ) & (freqs <= 8 )]) ** 2 ))
64
70
alpha_power = math .sqrt (np .sum ((fft_data [(freqs >= 8 ) & (freqs <= 13 )]) ** 2 ))
65
71
beta_power = math .sqrt (np .sum ((fft_data [(freqs >= 13 ) & (freqs <= 30 )]) ** 2 ))
66
72
gamma_power = math .sqrt (np .sum ((fft_data [(freqs >= 30 ) & (freqs <= 45 )]) ** 2 ))
67
73
68
- power = (beta_power + gamma_power ) / (theta_power + alpha_power )
74
+ power = (beta_power + gamma_power ) / (delta_power + theta_power + alpha_power + beta_power + gamma_power )
69
75
print (power )
70
76
return power
71
77
78
+ # Calibration Phase
79
+ show_message ("Sit still and relax for 10 seconds" , 3 )
80
+
81
+ print ("Starting Calibration... Please relax and stay still for 10 seconds." )
82
+ calibration_data = []
83
+ calibration_duration = 10
84
+ calibration_start_time = time .time ()
85
+
86
+ while time .time () - calibration_start_time < calibration_duration :
87
+ sample , _ = inlet .pull_sample (timeout = 0.1 )
88
+ if sample :
89
+ filtered_sample = apply_filters (sample [0 ])
90
+ calibration_data .append (filtered_sample )
91
+
92
+ if len (calibration_data ) >= buffer_size :
93
+ eeg_data = np .array (calibration_data )
94
+ baseline_focus_levels = [calculate_focus_level (eeg_data [i :i + buffer_size ]) for i in range (0 , len (eeg_data ), buffer_size )]
95
+
96
+ mean_focus = np .mean (baseline_focus_levels )
97
+ std_focus = np .std (baseline_focus_levels )
98
+
99
+ focus_threshold = mean_focus + 1.5 * std_focus
100
+ print (f"Calibration Complete. Focus Threshold set at: { focus_threshold :.2f} " )
101
+ else :
102
+ print ("Calibration failed due to insufficient data." )
103
+ exit ()
104
+
105
+ # Show Game Start Message
106
+ show_message ("Game Starting..." , 1 )
107
+
108
+ # Update beetle position
72
109
def update_beetle_position (focus_level , is_focus_stable ):
73
110
global beetle_y
74
111
if is_focus_stable :
75
- beetle_y = max (10 + beetle_image .get_height () // 2 , beetle_y - focus_speed_upward ) # Prevent moving above border
112
+ beetle_y = max (10 + beetle_image .get_height () // 2 , beetle_y - focus_speed_upward )
76
113
else :
77
- beetle_y = min (580 - beetle_image .get_height () // 2 , beetle_y + focus_speed_downward ) # Prevent moving below border
114
+ beetle_y = min (580 - beetle_image .get_height () // 2 , beetle_y + focus_speed_downward )
78
115
79
- # Game loop
116
+ print ( "STARTING GAME..." )
80
117
running = True
118
+ focus_timer = 0
119
+ last_focus_time = time .time ()
120
+ last_time = time .time ()
121
+
81
122
while running :
82
123
try :
83
124
for event in pygame .event .get ():
84
125
if event .type == pygame .QUIT :
85
126
running = False
86
127
87
- # Read EEG data from the LSL stream
88
128
sample , _ = inlet .pull_sample (timeout = 0.1 )
89
129
if sample :
90
130
filtered_sample = apply_filters (sample [0 ])
@@ -93,33 +133,27 @@ def update_beetle_position(focus_level, is_focus_stable):
93
133
current_time = time .time ()
94
134
if current_time - last_time >= 1 :
95
135
last_time = current_time
96
- release_count = int (len (buffer ) * 0.2 ) # Remove oldest 20%
97
- buffer = buffer [release_count :] # Trim buffer
136
+ buffer = buffer [int (len (buffer ) * 0.2 ):]
98
137
99
- if len (buffer ) >= buffer_size : # Process EEG data when the buffer is full
100
- eeg_data = np .array (buffer ) # Use filtered data
101
- buffer = [] # Clear the buffer
138
+ if len (buffer ) >= buffer_size :
139
+ eeg_data = np .array (buffer )
140
+ buffer = []
102
141
103
142
focus_level = calculate_focus_level (eeg_data )
104
143
105
144
if focus_level > focus_threshold :
106
145
focus_timer = min (focus_timeout , focus_timer + (current_time - last_focus_time ))
107
146
is_focus_stable = focus_timer >= focus_timeout
108
147
update_beetle_position (focus_level , is_focus_stable )
109
-
110
- elif 7 <= focus_level <= 8 : # No movement of the beetle
111
- print ("Beetle remains stationary." )
112
-
113
148
else :
114
149
focus_timer = max (0 , focus_timer - (current_time - last_focus_time ))
115
150
is_focus_stable = focus_timer >= focus_timeout
116
151
update_beetle_position (focus_level , is_focus_stable )
117
152
118
153
last_focus_time = current_time
119
154
120
- # Clear the screen and draw the beetle
121
155
screen .fill ("#FFFFFF" )
122
- pygame .draw .rect (screen , (0 , 0 , 0 ), (10 , 10 , 780 , 580 ), 5 ) # Draw border
156
+ pygame .draw .rect (screen , (0 , 0 , 0 ), (10 , 10 , 780 , 580 ), 5 )
123
157
screen .blit (beetle_image , (beetle_x - beetle_image .get_width () // 2 , beetle_y - beetle_image .get_height () // 2 ))
124
158
125
159
pygame .display .update ()
0 commit comments