From c79f8f7fd20b9bf068d1c0ac1ad80f98a7e8eba9 Mon Sep 17 00:00:00 2001 From: oabrivard Date: Sat, 9 Aug 2025 09:36:15 +0200 Subject: [PATCH] Added alien fleet --- .DS_Store | Bin 6148 -> 6148 bytes alien.py | 24 +++++++++++++ alien_invasion.py | 86 ++++++++++++++++++++++++++++++++++++++++++++-- game_stats.py | 14 ++++++++ images/alien.bmp | Bin 0 -> 10494 bytes settings.py | 1 + ship.py | 5 +++ 7 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 alien.py create mode 100644 game_stats.py create mode 100644 images/alien.bmp diff --git a/.DS_Store b/.DS_Store index 48f3106bc5e0f83eeb82612232bafc3a2f8cac8a..63564789ebe21326a676a5b65aa3ea4c1c7dc081 100644 GIT binary patch delta 170 zcmZoMXfc@J&&a(oU^g=(_hcRxOHK}kM1~xOOor6S2`pkvOzD%&SOS$f8Il-Efxt_+S0E)2dvT8|-@AqCYSpd16ky#HXpz_582>n_I4>>Pjj E0mJYt-2eap delta 73 zcmV-P0Ji^xFoZCWPXP$AP`d*G2$Kv1Ig@n+LX+tPL;<;zE(LK58GCy)H#00CF)%Ze fsRbMXi<8C$9|4S$<^?#jPzJXFk${u42MGNSIPVv1 diff --git a/alien.py b/alien.py new file mode 100644 index 0000000..c92933c --- /dev/null +++ b/alien.py @@ -0,0 +1,24 @@ +import pygame +from pygame.sprite import Sprite + +class Alien(Sprite): + """A class to represent a single alien in the fleet.""" + def __init__(self, ai_game): + super().__init__() + self.screen = ai_game.screen + self.settings = ai_game.settings + self.image = pygame.image.load("images/alien.bmp") + self.rect = self.image.get_rect() + self.rect.x = self.rect.width + self.rect.y = self.rect.height + self.x = float(self.rect.x) + + def check_edges(self): + """Return True if alien is at edge of screen.""" + screen_rect = self.screen.get_rect() + return self.rect.right >= screen_rect.right or self.rect.left <= 0 + + def update(self): + """Move the alien right or left.""" + self.x += self.settings.alien_speed * self.settings.fleet_direction + self.rect.x = self.x diff --git a/alien_invasion.py b/alien_invasion.py index d658390..b4e9392 100644 --- a/alien_invasion.py +++ b/alien_invasion.py @@ -1,8 +1,11 @@ import sys +from time import sleep import pygame from settings import Settings +from game_stats import GameStats from ship import Ship from bullet import Bullet +from alien import Alien from pygame.sprite import Group @@ -18,20 +21,59 @@ class AlienInvasion: self.settings.screen_height = self.screen.get_rect().height pygame.display.set_caption("Alien Invasion") self.bg_color = self.settings.bg_color + self.stats = GameStats(self) self.ship = Ship(self) self.bullets = Group() + self.aliens = Group() + self._create_fleet() def run_game(self): """Start the main loop for the game.""" while True: # Check for events and update the game state. self._check_events() - self.ship.update() - self._update_bullets() + if self.stats.game_active: + # Update the ship, bullets, and aliens. + self.ship.update() + self._update_bullets() + self._update_aliens() # Redraw the screen during each pass through the loop. self._update_screen() self.clock.tick(60) + def _create_fleet(self): + """Create a fleet of aliens.""" + alien = Alien(self) + alien_width, alien_height = alien.rect.size + current_x, current_y = alien_width, alien_height + while current_y < (self.settings.screen_height - 3 * alien_height): + while current_x < (self.settings.screen_width - 2 * alien_width): + self._create_alien(current_x, current_y) + current_x += 2 * alien_width + current_x = alien_width + current_y += 2 * alien_height + + def _create_alien(self, x_position, y_position): + """Create an alien and place it in the fleet.""" + alien = Alien(self) + alien.x = x_position + alien.rect.x = x_position + alien.rect.y = y_position + self.aliens.add(alien) + + def _check_fleet_edges(self): + """Respond appropriately if any aliens have reached an edge.""" + for alien in self.aliens.sprites(): + if alien.check_edges(): + self._change_fleet_direction() + break + + def _change_fleet_direction(self): + """Drop the entire fleet and change its direction.""" + for alien in self.aliens.sprites(): + alien.rect.y += self.settings.fleet_drop_speed + self.settings.fleet_direction *= -1 + def _check_events(self): """Respond to keypresses and mouse events.""" for event in pygame.event.get(): @@ -73,6 +115,45 @@ class AlienInvasion: for bullet in self.bullets.copy(): if bullet.rect.bottom <= 0: self.bullets.remove(bullet) + self._check_bullet_alien_collisions() + + def _check_alien_bottom(self): + """Check if any aliens have reached the bottom of the screen.""" + for alien in self.aliens.sprites(): + if alien.rect.bottom >= self.settings.screen_height: + self._ship_hit() + break + + def _check_bullet_alien_collisions(self): + """Respond to bullet-alien collisions.""" + collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True) + if not self.aliens: + # If the fleet is empty, create a new fleet. + self.bullets.empty() + self._create_fleet() + + def _ship_hit(self): + """Respond to the ship being hit by an alien.""" + if self.stats.ships_left > 0: + # Decrement ships_left and reset the game state. + self.stats.ships_left -= 1 + self.bullets.empty() + self.aliens.empty() + self._create_fleet() + self.ship.center_ship() + sleep(0.5) + else: + self.stats.game_active = False + pygame.mouse.set_visible(True) + + def _update_aliens(self): + """Update the positions of aliens.""" + self._check_fleet_edges() + self.aliens.update() + if pygame.sprite.spritecollideany(self.ship, self.aliens): + self._ship_hit() + self._check_bullet_alien_collisions() + self._check_alien_bottom() def _update_screen(self): """Update images on the screen and flip to the new screen.""" @@ -80,6 +161,7 @@ class AlienInvasion: for bullet in self.bullets.sprites(): bullet.draw_bullet() self.ship.blitme() + self.aliens.draw(self.screen) pygame.display.flip() if __name__ == '__main__': diff --git a/game_stats.py b/game_stats.py new file mode 100644 index 0000000..2c361ac --- /dev/null +++ b/game_stats.py @@ -0,0 +1,14 @@ +class GameStats: + """Track statistics for Alien Invasion.""" + + def __init__(self, ai_game): + """Initialize statistics.""" + self.settings = ai_game.settings + self.reset_stats() + # Start Alien Invasion in an active state. + self.game_active = True + + def reset_stats(self): + """Initialize statistics that can change during the game.""" + self.ships_left = self.settings.ship_limit + self.score = 0 \ No newline at end of file diff --git a/images/alien.bmp b/images/alien.bmp new file mode 100644 index 0000000000000000000000000000000000000000..dbe01a05de0f6f904459b92fd2d99193aea0bbad GIT binary patch literal 10494 zcmdU!y-piJ5P+Qui3kc(kVi-hMFdd_paP*(JPSRdMNlJX;RUb|FF=tpT|$xqTi!fI zln*8ujb``u?)J{cL1$}jc6R35+1Ve9oln2t4W9qr^Zg`#@EJbF22U zKx_zYDi9RUI#eY>fzP-L&T&P_#Z7HBr{PrbY)Vzx7cPnVpi?<_?pVHVMc{o94>JZ-1xEPMl+=iMvO0pRuJD2Ch1m^upH#ow7W07wn60 z;i430AO^;>q$tj_1SNW$!@LGO2Q04z*h%18W(??Vg|!bnHE%$3s#EGxGI0HC)NXI%S=H`tuRT3T_d zgRLqa7ad4Y?Y7_y3SRLEd_!P2d(~zq~={}L&S@V%CGW2ZCV=_avrM@ zIR=&@aXVEPRA!v%E~}y#y9(IVb`xOPC2qpa)@aM_6|zgfygk~sdbPwL&ZN^Ej1QK- zFQdedvSox}7&;I7N;nCPkY57YB^Kyt{lo^M!7Kx5o05BogdlIloEb3Ok_SS>Hnmj& zx!ZFfB9e^BRKMS!3^&vds6=R)EjLIgg#t47PM^NLxi> zfkh_giX;LWPKV4%3i)-oW`4C}awSR`W0qNfcwj{K%q1b}Rs?6@iVYip?YKA>s)moN z+i)vjbhN#Y=}40`a3uQbI`XPb4FyP?6LOyEt7&wpKAao^oarb{B*cZ&B-Hk`25v5D zonUYu?(txw$1`X{SebAb^TbtZ&88vWg}X_Z2(}xhodO7_5xv%@X2$J%@_XlKa%4TY zA3?KEroh-5aMdnNIu^I0?RIU)H3Qk*leKiU2G}PBgBj5Qs@V((lOY_o*eD*tOVw?X zR+SV0spAnmO|p<@F8u1@Wd&OUn(g9ZVAJN3%oUounY}HmtW8{riw90t71auE)2sCl z17KArZ?d~|NnSgX_M&vPZJCi9ViUAW(wJyGEIlk`IJF5R2N}QCV(*XlbMyn z=q1pmnk+RWjLq`l`f4S~654J@$-OZqbQ(MGzVMQMSScF13wHA}E{V}rX@A1lTJ0X@GI;3) L9{J~)(n;|LYGj&< literal 0 HcmV?d00001 diff --git a/settings.py b/settings.py index c066102..93f7b7d 100644 --- a/settings.py +++ b/settings.py @@ -9,6 +9,7 @@ class Settings: # Ship settings self.ship_speed = 1.5 + self.ship_limit = 3 # Bullet settings self.bullet_speed = 3.0 diff --git a/ship.py b/ship.py index 6a90b47..caa28be 100644 --- a/ship.py +++ b/ship.py @@ -26,3 +26,8 @@ class Ship: def blitme(self): """Draw the ship at its current location.""" self.screen.blit(self.image, self.rect) + + def center_ship(self): + """Center the ship on the screen.""" + self.rect.midbottom = self.screen.get_rect().midbottom + self.x = float(self.rect.x)