| import sys
|
|
|
| import pygame
|
|
|
| from settings import Settings
|
| from ship import Ship
|
| from bullet import Bullet
|
| from alien import Alien
|
|
|
|
|
| class AlienInvasion:
|
| """Overall class to manage game assets and behavior."""
|
|
|
| def __init__(self):
|
| """Initialize the game, and create game resources."""
|
| pygame.init()
|
| self.settings = Settings()
|
|
|
| self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
|
| self.settings.screen_width = self.screen.get_rect().width
|
| self.settings.screen_height = self.screen.get_rect().height
|
| pygame.display.set_caption("Alien Invasion")
|
|
|
| self.ship = Ship(self)
|
| self.bullets = pygame.sprite.Group()
|
| self.aliens = pygame.sprite.Group()
|
|
|
| self._create_fleet()
|
|
|
| def run_game(self):
|
| """Start the main loop for the game."""
|
| while True:
|
| self._check_events()
|
| self.ship.update()
|
| self._update_bullets()
|
| self._update_aliens()
|
| self._update_screen()
|
|
|
| def _check_events(self):
|
| """Respond to keypresses and mouse events."""
|
| for event in pygame.event.get():
|
| if event.type == pygame.QUIT:
|
| sys.exit()
|
| elif event.type == pygame.KEYDOWN:
|
| self._check_keydown_events(event)
|
| elif event.type == pygame.KEYUP:
|
| self._check_keyup_events(event)
|
|
|
| def _check_keydown_events(self, event):
|
| """Respond to keypresses."""
|
| if event.key == pygame.K_RIGHT:
|
| self.ship.moving_right = True
|
| elif event.key == pygame.K_LEFT:
|
| self.ship.moving_left = True
|
| elif event.key == pygame.K_q:
|
| sys.exit()
|
| elif event.key == pygame.K_SPACE:
|
| self._fire_bullet()
|
|
|
| def _check_keyup_events(self, event):
|
| """Respond to key releases."""
|
| if event.key == pygame.K_RIGHT:
|
| self.ship.moving_right = False
|
| elif event.key == pygame.K_LEFT:
|
| self.ship.moving_left = False
|
|
|
| def _fire_bullet(self):
|
| """Create a new bullet and add it to the bullets group."""
|
| if len(self.bullets) < self.settings.bullets_allowed:
|
| new_bullet = Bullet(self)
|
| self.bullets.add(new_bullet)
|
|
|
| def _update_bullets(self):
|
| """Update position of bullets and get rid of old bullets."""
|
| # Update bullet positions.
|
| self.bullets.update()
|
|
|
| # Get rid of bullets that have disappeared.
|
| for bullet in self.bullets.copy():
|
| if bullet.rect.bottom <= 0:
|
| self.bullets.remove(bullet)
|
|
|
| def _update_aliens(self):
|
| """
|
| Check if the fleet is at an edge,
|
| then update the positions of all aliens in the fleet.
|
| """
|
| self._check_fleet_edges()
|
| self.aliens.update()
|
|
|
| def _create_fleet(self):
|
| """Create the fleet of aliens."""
|
| # Create an alien and find the number of aliens in a row.
|
| # Spacing between each alien is equal to one alien width.
|
| alien = Alien(self)
|
| alien_width, alien_height = alien.rect.size
|
| available_space_x = self.settings.screen_width - (2 * alien_width)
|
| number_aliens_x = available_space_x // (2 * alien_width)
|
|
|
| # Determine the number of rows of aliens that fit on the screen.
|
| ship_height = self.ship.rect.height
|
| available_space_y = (self.settings.screen_height -
|
| (3 * alien_height) - ship_height)
|
| number_rows = available_space_y // (2 * alien_height)
|
|
|
| # Create the full fleet of aliens.
|
| for row_number in range(number_rows):
|
| for alien_number in range(number_aliens_x):
|
| self._create_alien(alien_number, row_number)
|
|
|
| def _create_alien(self, alien_number, row_number):
|
| """Create an alien and place it in the row."""
|
| alien = Alien(self)
|
| alien_width, alien_height = alien.rect.size
|
| alien.x = alien_width + 2 * alien_width * alien_number
|
| alien.rect.x = alien.x
|
| alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
|
| 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 the fleet's direction."""
|
| for alien in self.aliens.sprites():
|
| alien.rect.y += self.settings.fleet_drop_speed
|
| self.settings.fleet_direction *= -1
|
|
|
| def _update_screen(self):
|
| """Update images on the screen, and flip to the new screen."""
|
| self.screen.fill(self.settings.bg_color)
|
| self.ship.blitme()
|
| for bullet in self.bullets.sprites():
|
| bullet.draw_bullet()
|
| self.aliens.draw(self.screen)
|
|
|
| pygame.display.flip()
|
|
|
|
|
| if __name__ == '__main__':
|
| # Make a game instance, and run the game.
|
| ai = AlienInvasion()
|
| ai.run_game()
|
| import pygame
|
| from pygame.sprite import Sprite
|
|
|
| class Bullet(Sprite):
|
| """A class to manage bullets fired from the ship"""
|
|
|
| def __init__(self, ai_game):
|
| """Create a bullet object at the ship's current position."""
|
| super().__init__()
|
| self.screen = ai_game.screen
|
| self.settings = ai_game.settings
|
| self.color = self.settings.bullet_color
|
|
|
| # Create a bullet rect at (0, 0) and then set correct position.
|
| self.rect = pygame.Rect(0, 0, self.settings.bullet_width,
|
| self.settings.bullet_height)
|
| self.rect.midtop = ai_game.ship.rect.midtop
|
|
|
| # Store the bullet's position as a decimal value.
|
| self.y = float(self.rect.y)
|
|
|
| def update(self):
|
| """Move the bullet up the screen."""
|
| # Update the decimal position of the bullet.
|
| self.y -= self.settings.bullet_speed
|
| # Update the rect position.
|
| self.rect.y = self.y
|
|
|
| def draw_bullet(self):
|
| """Draw the bullet to the screen."""
|
| pygame.draw.rect(self.screen, self.color, self.rect)
|
| import pygame
|
|
|
| class Ship:
|
| """A class to manage the ship."""
|
|
|
| def __init__(self, ai_game):
|
| """Initialize the ship and set its starting position."""
|
| self.screen = ai_game.screen
|
| self.settings = ai_game.settings
|
| self.screen_rect = ai_game.screen.get_rect()
|
|
|
| # Load the ship image and get its rect.
|
| self.image = pygame.image.load('images/ship.bmp')
|
| self.rect = self.image.get_rect()
|
|
|
| # Start each new ship at the bottom center of the screen.
|
| self.rect.midbottom = self.screen_rect.midbottom
|
|
|
| # Store a decimal value for the ship's horizontal position.
|
| self.x = float(self.rect.x)
|
|
|
| # Movement flags
|
| self.moving_right = False
|
| self.moving_left = False
|
|
|
| def update(self):
|
| """Update the ship's position based on movement flags."""
|
| # Update the ship's x value, not the rect.
|
| if self.moving_right and self.rect.right < self.screen_rect.right:
|
| self.x += self.settings.ship_speed
|
| if self.moving_left and self.rect.left > 0:
|
| self.x -= self.settings.ship_speed
|
|
|
| # Update rect object from self.x.
|
| self.rect.x = self.x
|
|
|
| def blitme(self):
|
| """Draw the ship at its current location."""
|
| self.screen.blit(self.image, self.rect)
|
| class Settings:
|
| """A class to store all settings for Alien Invasion."""
|
|
|
| def __init__(self):
|
| """Initialize the game's settings."""
|
| # Screen settings
|
| self.screen_width = 1200
|
| self.screen_height = 800
|
| self.bg_color = (230, 230, 230)
|
|
|
| # Ship settings
|
| self.ship_speed = 1.5
|
|
|
| # Bullet settings
|
| self.bullet_speed = 1.0
|
| self.bullet_width = 3
|
| self.bullet_height = 15
|
| self.bullet_color = (60, 60, 60)
|
| self.bullets_allowed = 3
|
|
|
| # Alien settings
|
| self.alien_speed = 1.0
|
| self.fleet_drop_speed = 5
|
| # fleet_direction of 1 represents right; -1 represents left.
|
| self.fleet_direction = 1
|
| 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):
|
| """Initialize the alien and set its starting position."""
|
| super().__init__()
|
| self.screen = ai_game.screen
|
| self.settings = ai_game.settings
|
|
|
| # Load the alien image and set its rect attribute.
|
| self.image = pygame.image.load('images/alien.bmp')
|
| self.rect = self.image.get_rect()
|
|
|
| # Start each new alien near the top left of the screen.
|
| self.rect.x = self.rect.width
|
| self.rect.y = self.rect.height
|
|
|
| # Store the alien's exact horizontal position.
|
| 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()
|
| if self.rect.right >= screen_rect.right or self.rect.left <= 0:
|
| return True
|
|
|
| def update(self):
|
| """Move the alien right or left."""
|
| self.x += (self.settings.alien_speed *
|
| self.settings.fleet_direction)
|
| self.rect.x = self.x
|