1
+ import sys
2
+ from time import sleep
3
+
4
+ import pygame
5
+
6
+ from settings import Settings
7
+ from game_stats import GameStats
8
+ from scoreboard import Scoreboard
9
+ from button import Button
10
+ from ship import Ship
11
+ from bullet import Bullet
12
+ from alien import Alien
13
+ import serial
14
+
15
+ class AlienInvasion :
16
+ """Overall class to manage game assets and behavior."""
17
+
18
+ def __init__ (self ):
19
+ """Initialize the game, and create game resources."""
20
+ pygame .init ()
21
+ self .clock = pygame .time .Clock ()
22
+ self .settings = Settings ()
23
+
24
+ self .screen = pygame .display .set_mode ((0 , 0 ), pygame .FULLSCREEN )
25
+ pygame .display .set_caption ("Alien Invasion" )
26
+
27
+ # Establish serial connection
28
+ self .ser = serial .Serial ('COM3' , 9600 , timeout = 1 ) # Replace 'COM_PORT' with your Arduino's serial port
29
+
30
+ # Create a game statistics instance
31
+ self .stats = GameStats (self )
32
+ self .sb = Scoreboard (self )
33
+
34
+ self .ship = Ship (self )
35
+ self .bullets = pygame .sprite .Group ()
36
+ self .aliens = pygame .sprite .Group ()
37
+
38
+ # Create the fleet
39
+ self ._create_fleet ()
40
+
41
+ # Start the game in an inactive state
42
+ self .game_active = False
43
+
44
+ # Make the Play button
45
+ self .play_button = Button (self , "Play" )
46
+
47
+ def run_game (self ):
48
+ """Start the main loop for the game."""
49
+ while True :
50
+ self ._check_events ()
51
+
52
+ if self .game_active :
53
+ self .ship .update ()
54
+ self ._update_bullets ()
55
+ self ._update_aliens ()
56
+
57
+ self ._update_screen ()
58
+ self .clock .tick (60 )
59
+
60
+ def _check_events (self ):
61
+ """Respond to keypresses and mouse events."""
62
+ self .process_serial_data () # Read joystick input directly
63
+ for event in pygame .event .get ():
64
+ if event .type == pygame .QUIT :
65
+ sys .exit ()
66
+ if event .type == pygame .KEYDOWN :
67
+ sys .exit ()
68
+ elif event .type == pygame .MOUSEBUTTONDOWN :
69
+ mouse_pos = pygame .mouse .get_pos ()
70
+ self ._check_play_button (mouse_pos )
71
+
72
+ def process_serial_data (self ):
73
+ """Read and parse serial data."""
74
+ if self .ser .in_waiting > 0 :
75
+ try :
76
+ data = self .ser .readline ().decode ('utf-8' ).rstrip ()
77
+ joystick_values = list (map (int , data .split (',' )))
78
+ if len (joystick_values ) == 2 :
79
+ joystick_x = joystick_values [0 ]
80
+ joystick_switch = joystick_values [1 ]
81
+
82
+ self .handle_game_controls (joystick_x ,joystick_switch ) # Send X value to handle movement
83
+ except ValueError :
84
+ print ("Invalid data received" )
85
+
86
+ def handle_game_controls (self , joystick_x ,switch ):
87
+ """Control ship movement with joystick."""
88
+ # Center is approximately 523; adjust movement thresholds as necessary
89
+ if joystick_x > 600 : # Right
90
+ self .ship .moving_right = True
91
+ self .ship .moving_left = False
92
+ elif joystick_x < 450 : # Left
93
+ self .ship .moving_left = True
94
+ self .ship .moving_right = False
95
+ else : # Center position
96
+ self .ship .moving_right = False
97
+ self .ship .moving_left = False
98
+
99
+ if switch == 0 :
100
+ self ._fire_bullet ()
101
+ def _check_play_button (self , mouse_pos ):
102
+ """Start a new game when the player clicks Play."""
103
+ button_clicked = self .play_button .rect .collidepoint (mouse_pos )
104
+ if button_clicked and not self .game_active :
105
+ # Reset the game settings.
106
+ self .settings .initialize_dynamic_settings ()
107
+
108
+ # Reset the game statistics.
109
+ self .stats .reset_stats ()
110
+ self .sb .prep_score ()
111
+ self .sb .prep_level ()
112
+ self .sb .prep_ships ()
113
+ self .game_active = True
114
+
115
+ # Get rid of any remaining bullets and aliens.
116
+ self .bullets .empty ()
117
+ self .aliens .empty ()
118
+
119
+ # Create a new fleet and center the ship.
120
+ self ._create_fleet ()
121
+ self .ship .center_ship ()
122
+
123
+ # Hide the mouse cursor.
124
+ pygame .mouse .set_visible (False )
125
+
126
+ def _check_keydown_events (self , event ):
127
+ """Respond to keypresses."""
128
+ if event .key == pygame .K_RIGHT :
129
+ self .ship .moving_right = True
130
+ elif event .key == pygame .K_LEFT :
131
+ self .ship .moving_left = True
132
+ elif event .key == pygame .K_q :
133
+ sys .exit ()
134
+ elif event .key == pygame .K_SPACE :
135
+ self ._fire_bullet ()
136
+
137
+ def _check_keyup_events (self , event ):
138
+ """Respond to key releases."""
139
+ if event .key == pygame .K_RIGHT :
140
+ self .ship .moving_right = False
141
+ elif event .key == pygame .K_LEFT :
142
+ self .ship .moving_left = False
143
+
144
+ def _fire_bullet (self ):
145
+ """Create a new bullet and add it to the bullets group."""
146
+ if len (self .bullets ) < self .settings .bullets_allowed :
147
+ new_bullet = Bullet (self )
148
+ self .bullets .add (new_bullet )
149
+
150
+ def _update_bullets (self ):
151
+ """Update position of bullets and get rid of old bullets."""
152
+ # Update bullet positions.
153
+ self .bullets .update ()
154
+
155
+ # Get rid of bullets that have disappeared.
156
+ for bullet in self .bullets .copy ():
157
+ if bullet .rect .bottom <= 0 :
158
+ self .bullets .remove (bullet )
159
+
160
+ self ._check_bullet_alien_collisions ()
161
+
162
+ def _check_bullet_alien_collisions (self ):
163
+ """Respond to bullet-alien collisions."""
164
+ # Remove any bullets and aliens that have collided.
165
+ collisions = pygame .sprite .groupcollide (
166
+ self .bullets , self .aliens , True , True )
167
+
168
+ if collisions :
169
+ for aliens in collisions .values ():
170
+ self .stats .score += self .settings .alien_points * len (aliens )
171
+ self .sb .prep_score ()
172
+ self .sb .check_high_score ()
173
+
174
+ if not self .aliens :
175
+ # Destroy existing bullets and create new fleet.
176
+ self .bullets .empty ()
177
+ self ._create_fleet ()
178
+ self .settings .increase_speed ()
179
+
180
+ # Increase level.
181
+ self .stats .level += 1
182
+ self .sb .prep_level ()
183
+
184
+ def _ship_hit (self ):
185
+ """Respond to the ship being hit by an alien."""
186
+ if self .stats .ships_left > 0 :
187
+ # Decrement ships_left, and update scoreboard.
188
+ self .stats .ships_left -= 1
189
+ self .sb .prep_ships ()
190
+
191
+ # Get rid of any remaining bullets and aliens.
192
+ self .bullets .empty ()
193
+ self .aliens .empty ()
194
+
195
+ # Create a new fleet and center the ship.
196
+ self ._create_fleet ()
197
+ self .ship .center_ship ()
198
+
199
+ # Pause.
200
+ sleep (0.5 )
201
+ else :
202
+ self .game_active = False
203
+ pygame .mouse .set_visible (True )
204
+
205
+ def _update_aliens (self ):
206
+ """Check if the fleet is at an edge, then update positions."""
207
+ self ._check_fleet_edges ()
208
+ self .aliens .update ()
209
+
210
+ # Look for alien-ship collisions.
211
+ if pygame .sprite .spritecollideany (self .ship , self .aliens ):
212
+ self ._ship_hit ()
213
+
214
+ # Look for aliens hitting the bottom of the screen.
215
+ self ._check_aliens_bottom ()
216
+
217
+ def _check_aliens_bottom (self ):
218
+ """Check if any aliens have reached the bottom of the screen."""
219
+ for alien in self .aliens .sprites ():
220
+ if alien .rect .bottom >= self .settings .screen_height :
221
+ # Treat this the same as if the ship got hit.
222
+ self ._ship_hit ()
223
+ break
224
+
225
+ def _create_fleet (self ):
226
+ """Create the fleet of aliens."""
227
+ # Create an alien and keep adding aliens until there's no room left.
228
+ # Spacing between aliens is one alien width and one alien height.
229
+ alien = Alien (self )
230
+ alien_width , alien_height = alien .rect .size
231
+
232
+ current_x , current_y = alien_width , alien_height
233
+ while current_y < (self .settings .screen_height - 3 * alien_height ):
234
+ while current_x < (self .settings .screen_width - 2 * alien_width ):
235
+ self ._create_alien (current_x , current_y )
236
+ current_x += 2 * alien_width
237
+
238
+ # Finished a row; reset x value, and increment y value.
239
+ current_x = alien_width
240
+ current_y += 2 * alien_height
241
+
242
+ def _create_alien (self , x_position , y_position ):
243
+ """Create an alien and place it in the fleet."""
244
+ new_alien = Alien (self )
245
+ new_alien .x = x_position
246
+ new_alien .rect .x = x_position
247
+ new_alien .rect .y = y_position
248
+ self .aliens .add (new_alien )
249
+
250
+ def _check_fleet_edges (self ):
251
+ """Respond appropriately if any aliens have reached an edge."""
252
+ for alien in self .aliens .sprites ():
253
+ if alien .check_edges ():
254
+ self ._change_fleet_direction ()
255
+ break
256
+
257
+ def _change_fleet_direction (self ):
258
+ """Drop the entire fleet and change the fleet's direction."""
259
+ for alien in self .aliens .sprites ():
260
+ alien .rect .y += self .settings .fleet_drop_speed
261
+ self .settings .fleet_direction *= - 1
262
+
263
+ def _update_screen (self ):
264
+ """Update images on the screen, and flip to the new screen."""
265
+ self .screen .fill (self .settings .bg_color )
266
+ for bullet in self .bullets .sprites ():
267
+ bullet .draw_bullet ()
268
+ self .ship .blitme ()
269
+ self .aliens .draw (self .screen )
270
+
271
+ # Draw the score information.
272
+ self .sb .show_score ()
273
+
274
+ # Draw the play button if the game is inactive.
275
+ if not self .game_active :
276
+ self .play_button .draw_button ()
277
+
278
+ pygame .display .flip ()
279
+
280
+
281
+ if __name__ == '__main__' :
282
+ # Make a game instance, and run the game.
283
+ ai = AlienInvasion ()
284
+ ai .run_game ()
0 commit comments