From 3e8aa3442737ffe151b731895584e9e4f56b7814 Mon Sep 17 00:00:00 2001 From: JasonHomeWorkstationUbuntu Date: Sat, 12 Sep 2020 16:30:48 +1000 Subject: [PATCH] Finished Chapter 13 source code programming --- src/project_i_alien_invasion/alien.bmp | Bin 0 -> 10494 bytes src/project_i_alien_invasion/alien.py | 36 ++++++ .../alien_invasion.py | 121 +++++++++++++++++- src/project_i_alien_invasion/game_stats.py | 14 ++ src/project_i_alien_invasion/settings.py | 12 +- src/project_i_alien_invasion/ship.py | 7 +- 6 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 src/project_i_alien_invasion/alien.bmp create mode 100644 src/project_i_alien_invasion/alien.py create mode 100644 src/project_i_alien_invasion/game_stats.py diff --git a/src/project_i_alien_invasion/alien.bmp b/src/project_i_alien_invasion/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/src/project_i_alien_invasion/alien.py b/src/project_i_alien_invasion/alien.py new file mode 100644 index 0000000..a3f9f24 --- /dev/null +++ b/src/project_i_alien_invasion/alien.py @@ -0,0 +1,36 @@ +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('alien.bmp') + self.rect = self.image.get_rect() + + # Start each new alien near the top left of the screen + # Add a space to the left of alien (which equals to the alien's width) + 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 + else: + return False + + def update(self): + """Move the alien to the right""" + self.x += self.settings.alien_speed * self.settings.fleet_direction + self.rect.x = self.x # track the alien's exact position with self.x attribute. \ No newline at end of file diff --git a/src/project_i_alien_invasion/alien_invasion.py b/src/project_i_alien_invasion/alien_invasion.py index a026276..04ccaf2 100644 --- a/src/project_i_alien_invasion/alien_invasion.py +++ b/src/project_i_alien_invasion/alien_invasion.py @@ -1,8 +1,14 @@ 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 + class AlienInvasion: """Overall class to manage game assets and behaviour""" @@ -20,16 +26,25 @@ class AlienInvasion: self.settings.screen_height = self.screen.get_rect().height pygame.display.set_caption("Alien Invasion") + # Create an instance to store game statistics + self.stats = GameStats(self) + 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() + + if self.stats.game_active: + self.ship.update() + self._update_bullets() + self._update_aliens() self._update_screen() @@ -77,6 +92,42 @@ class AlienInvasion: if bullet.rect.bottom <= 0: self.bullets.remove(bullet) print(len(self.bullets)) + self._check_bullet_alien_collisions() + + def _check_bullet_alien_collisions(self): + """Respond to the bullet-alien collisions""" + # Check for any bullets that have hit aliens. + # If so, get rid of the bullet and the alien + collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True) + + # If alien fleet is destroyed, repopulate another one + if not self.aliens: + self.bullets.empty() + self._create_fleet() + + def _check_aliens_bottom(self): + """Check if any aliens have reached the bottom of screen""" + screen_rect = self.screen.get_rect() + for alien in self.aliens.sprites(): + if alien.rect.bottom >= screen_rect.bottom: + # Treat this the same as if the ship got hit + self._ship_hit() + break + + def _update_aliens(self): + """ + Check if the fleet is at an edge, + Update the positions of all aliens in the fleet + """ + self._check_fleet_edges() + self.aliens.update() + + # Look for alien-ship collisions + if pygame.sprite.spritecollideany(self.ship, self.aliens): + self._ship_hit() + + # Look for aliens hitting the bottom of the screen + self._check_aliens_bottom() def _update_screen(self): """Update images on the screen, and flip to the new screen""" @@ -84,9 +135,75 @@ class AlienInvasion: self.ship.blitme() for bullet in self.bullets.sprites(): bullet.draw_bullet() + self.aliens.draw(self.screen) pygame.display.flip() + def _create_fleet(self): + """ + Create the fleet of aliens. + """ + # Create an alien and find the number of alines in a row + # Spacing between each alien is equal to one alien width. + alien = Alien(self) + alien_width, alien_height = alien.rect.size + availalbe_space_x = self.settings.screen_width - (2 * alien_width) + number_aliens_x = availalbe_space_x // (2 * alien_width) + + # Determine the number of rows of aliens that fit on the screen + ship_height = self.ship.rect.height + availalbe_space_y = (self.settings.screen_height - (3 * alien_height) - ship_height) + number_rows = availalbe_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): + # Create an alien and place it in the row + self._create_alien(alien_number, row_number) + + def _create_alien(self, alien_number, row_number): + """Create an alien and place it in the row in correct place""" + alien = Alien(self) + alien_width, alein_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 _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 _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 # Break out of the loop if an alien is at edge + + def _ship_hit(self): + """Respond to the ship being hit by an alien""" + + if self.stats.ships_left > 0: + # Decrement ships_left + self.stats.ships_left -= 1 + + # Get rid of any remaining aliens and bullets + self.aliens.empty() + self.bullets.empty() + + # Create a new fleet and center the ship + self._create_fleet() + self.ship.center_ship() + + # Pause + sleep(0.5) + else: + self.stats.game_active = False + if __name__ == '__main__': ai = AlienInvasion() ai.run_game() \ No newline at end of file diff --git a/src/project_i_alien_invasion/game_stats.py b/src/project_i_alien_invasion/game_stats.py new file mode 100644 index 0000000..03db2dd --- /dev/null +++ b/src/project_i_alien_invasion/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 statics that can change during the game""" + self.ships_left = self.settings.ship_limit \ No newline at end of file diff --git a/src/project_i_alien_invasion/settings.py b/src/project_i_alien_invasion/settings.py index 9f1e1fc..49f98c8 100644 --- a/src/project_i_alien_invasion/settings.py +++ b/src/project_i_alien_invasion/settings.py @@ -11,10 +11,18 @@ class Settings: # Ship settings self.ship_speed = 1.5 + self.ship_limit = 3 # Bullet settings - self.bullet_speed = 1.0 + self.bullet_speed = 1.5 self.bullet_width = 3 self.bullet_height = 15 self.bullet_color = (60,60,60) - self.bullets_allowed = 3 \ No newline at end of file + self.bullets_allowed = 3 + + # Alien settings + self.alien_speed = 1.0 + self.fleet_drop_speed = 10 + # fleet_direction of 1 represents right; -1 represent left + self.fleet_direction = 1 + diff --git a/src/project_i_alien_invasion/ship.py b/src/project_i_alien_invasion/ship.py index 9d27b08..452f153 100644 --- a/src/project_i_alien_invasion/ship.py +++ b/src/project_i_alien_invasion/ship.py @@ -33,4 +33,9 @@ class Ship: def blitme(self): """Draw the ship at its current location""" - self.screen.blit(self.image,self.rect) \ No newline at end of file + self.screen.blit(self.image,self.rect) + + def center_ship(self): + """Center the ship on the screen""" + self.rect.midbottom = self.screen_rect.midbottom + self.x = float(self.rect.x) \ No newline at end of file