diff --git a/.DS_Store b/.DS_Store index 48f3106..6356478 100644 Binary files a/.DS_Store and b/.DS_Store differ 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 0000000..dbe01a0 Binary files /dev/null and b/images/alien.bmp differ 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)