《Python从入门到实践》外星人入侵游戏
写在前面的:
在原版的基础基础上,1.飞船能在水平、垂直方向上运动;2.背景图更换。
文件目录:

效果图:

源码:
alien.py
1 import pygame 2 from pygame.sprite import Sprite 3 4 class Alien(Sprite): 5 """A class to represent a single alien in the fleet.""" 6 7 def __init__(self, ai_settings, screen): 8 """Initialize the alien, and set its starting position.""" 9 super(Alien, self).__init__() 10 self.screen = screen 11 self.ai_settings = ai_settings 12 13 # Load the alien image, and set its rect attribute. 14 self.image = pygame.image.load('images/alien.bmp') 15 self.rect = self.image.get_rect() 16 17 # Start each new alien near the top left of the screen. 18 self.rect.x = self.rect.width 19 self.rect.y = self.rect.height 20 21 # Store the alien's exact position. 22 self.x = float(self.rect.x) 23 24 def check_edges(self): 25 """Return True if alien is at edge of screen.""" 26 screen_rect = self.screen.get_rect() 27 if self.rect.right >= screen_rect.right: 28 return True 29 elif self.rect.left <= 0: 30 return True 31 32 def update(self): 33 """Move the alien right or left.""" 34 self.x += (self.ai_settings.alien_speed_factor * 35 self.ai_settings.fleet_direction) 36 self.rect.x = self.x 37 38 def blitme(self): 39 """Draw the alien at its current location.""" 40 self.screen.blit(self.image, self.rect)
alien_invasion.py
1 import pygame 2 from pygame.sprite import Group 3 from settings import Settings 4 from game_stats import GameStats 5 from scoreboard import Scoreboard 6 from button import Button 7 from ship import Ship 8 import game_functions as gf 9 10 def run_game(): 11 """初始化游戏并创建一个屏幕对象""" 12 pygame.init() 13 ai_settings = Settings() 14 screen = pygame.display.set_mode( 15 (ai_settings.screen_width, ai_settings.screen_height)) 16 pygame.display.set_caption("Alien Invasion") 17 18 """创建Play按钮""" 19 play_button = Button(ai_settings, screen, "Play") 20 21 """创建一个用于存储游戏统计信息的实例,并创建记分牌""" 22 stats = GameStats(ai_settings) 23 sb = Scoreboard(ai_settings, screen, stats) 24 25 """创建一艘飞船""" 26 ship = Ship(ai_settings, screen) 27 28 """创建一个用于存储子弹的编组""" 29 bullets = Group() 30 31 """创建一个外星人""" 32 aliens = Group() 33 34 """创建一个外星群""" 35 gf.create_fleet(ai_settings, screen, ship, aliens) 36 37 """开始游戏的主循环""" 38 while True: 39 #监察键盘和鼠标事件 40 gf.check_events(ai_settings, screen, stats, sb, play_button, ship, 41 aliens, bullets) 42 43 if stats.game_active: 44 ship.update() 45 gf.update_bullets(ai_settings, screen, stats, sb, ship, aliens, 46 bullets) 47 gf.update_aliens(ai_settings, screen, stats, sb, ship, aliens, 48 bullets) 49 #更新屏幕上的图像,并切换到新的屏幕 50 gf.update_screen(ai_settings, screen, stats, sb, ship, aliens, 51 bullets, play_button) 52 53 run_game()
bullet.py
1 import pygame 2 from pygame.sprite import Sprite 3 4 class Bullet(Sprite): 5 """A class to manage bullets fired from the ship.""" 6 7 def __init__(self, ai_settings, screen, ship): 8 """Create a bullet object, at the ship's current position.""" 9 super(Bullet, self).__init__() 10 self.screen = screen 11 12 # Create bullet rect at (0, 0), then set correct position. 13 self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, 14 ai_settings.bullet_height) 15 self.rect.centerx = ship.rect.centerx 16 self.rect.top = ship.rect.top 17 18 # Store a decimal value for the bullet's position. 19 self.y = float(self.rect.y) 20 21 self.color = ai_settings.bullet_color 22 self.speed_factor = ai_settings.bullet_speed_factor 23 24 def update(self): 25 """Move the bullet up the screen.""" 26 # Update the decimal position of the bullet. 27 self.y -= self.speed_factor 28 # Update the rect position. 29 self.rect.y = self.y 30 31 def draw_bullet(self): 32 """Draw the bullet to the screen.""" 33 pygame.draw.rect(self.screen, self.color, self.rect)
button.py
1 import pygame.font 2 3 class Button(): 4 5 def __init__(self, ai_settings, screen, msg): 6 """Initialize button attributes.""" 7 self.screen = screen 8 self.screen_rect = screen.get_rect() 9 10 # Set the dimensions and properties of the button. 11 self.width, self.height = 200, 50 12 self.button_color = (0, 255, 0) 13 self.text_color = (255, 255, 255) 14 self.font = pygame.font.SysFont(None, 48) 15 16 # Build the button's rect object, and center it. 17 self.rect = pygame.Rect(0, 0, self.width, self.height) 18 self.rect.center = self.screen_rect.center 19 20 # The button message only needs to be prepped once. 21 self.prep_msg(msg) 22 23 def prep_msg(self, msg): 24 """Turn msg into a rendered image, and center text on the button.""" 25 self.msg_image = self.font.render(msg, True, self.text_color, 26 self.button_color) 27 self.msg_image_rect = self.msg_image.get_rect() 28 self.msg_image_rect.center = self.rect.center 29 30 def draw_button(self): 31 # Draw blank button, then draw message. 32 self.screen.fill(self.button_color, self.rect) 33 self.screen.blit(self.msg_image, self.msg_image_rect)
game_functions.py
1 import sys 2 from time import sleep 3 4 import pygame 5 6 from bullet import Bullet 7 from alien import Alien 8 9 def check_keydown_events(event, ai_settings, screen, ship, bullets): 10 """响应按键""" 11 if event.key == pygame.K_RIGHT: 12 ship.moving_right = True 13 elif event.key == pygame.K_LEFT: 14 ship.moving_left = True 15 elif event.key == pygame.K_UP: 16 ship.moving_up = True 17 elif event.key == pygame.K_DOWN: 18 ship.moving_down = True 19 elif event.key == pygame.K_SPACE: 20 fire_bullet(ai_settings, screen, ship, bullets) 21 elif event.key == pygame.K_q: 22 sys.exit() 23 24 def check_keyup_events(event, ai_settings, screen, ship, bullets): 25 """松开响应""" 26 if event.key == pygame.K_RIGHT: 27 ship.moving_right = False 28 elif event.key == pygame.K_LEFT: 29 ship.moving_left = False 30 elif event.key == pygame.K_UP: 31 ship.moving_up = False 32 elif event.key == pygame.K_DOWN: 33 ship.moving_down = False 34 35 def check_events(ai_settings, screen, stats, sb, play_button, ship, aliens, 36 bullets): 37 """响应按键和鼠标事件""" 38 for event in pygame.event.get(): 39 if event.type == pygame.QUIT: 40 sys.exit() 41 elif event.type == pygame.KEYDOWN: 42 check_keydown_events(event, ai_settings, screen, ship, bullets) 43 44 elif event.type == pygame.KEYUP: 45 check_keyup_events(event, ai_settings, screen, ship, bullets) 46 47 elif event.type == pygame.MOUSEBUTTONDOWN: 48 mouse_x, mouse_y = pygame.mouse.get_pos() 49 check_play_button(ai_settings, screen, stats, sb, play_button, 50 ship, aliens, bullets, mouse_x, mouse_y) 51 52 def check_play_button(ai_settings, screen, stats, sb, play_button, ship, 53 aliens, bullets, mouse_x, mouse_y): 54 """在玩家单击Play按钮时开始新游戏""" 55 button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y) 56 if button_clicked and not stats.game_active: 57 # 重置游戏设置 58 ai_settings.initialize_dynamic_settings() 59 60 # 隐藏光标 61 pygame.mouse.set_visible(False) 62 63 # 重置游戏统计信息 64 stats.reset_stats() 65 stats.game_active = True 66 67 # 重置记分牌图像 68 sb.prep_score() 69 sb.prep_high_score() 70 sb.prep_level() 71 sb.prep_ships() 72 73 # 清空外星人列表和子弹列表 74 aliens.empty() 75 bullets.empty() 76 77 # 创建一群新的外星人,并让飞船居中 78 create_fleet(ai_settings, screen, ship, aliens) 79 ship.center_ship() 80 81 def fire_bullet(ai_settings, screen, ship, bullets): 82 """Fire a bullet, if limit not reached yet.""" 83 # Create a new bullet, add to bullets group. 84 if len(bullets) < ai_settings.bullets_allowed: 85 new_bullet = Bullet(ai_settings, screen, ship) 86 bullets.add(new_bullet) 87 88 def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, 89 play_button): 90 """Update images on the screen, and flip to the new screen.""" 91 # Redraw the screen, each pass through the loop. 92 #screen.fill(ai_settings.bg_color) 93 screen.blit(ai_settings.background,(0,0)) 94 95 # Redraw all bullets, behind ship and aliens. 96 for bullet in bullets.sprites(): 97 bullet.draw_bullet() 98 ship.blitme() 99 aliens.draw(screen) 100 101 # Draw the score information. 102 sb.show_score() 103 104 # Draw the play button if the game is inactive. 105 if not stats.game_active: 106 play_button.draw_button() 107 108 # Make the most recently drawn screen visible. 109 pygame.display.flip() 110 111 def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets): 112 """Update position of bullets, and get rid of old bullets.""" 113 # Update bullet positions. 114 bullets.update() 115 116 # Get rid of bullets that have disappeared. 117 for bullet in bullets.copy(): 118 if bullet.rect.bottom <= 0: 119 bullets.remove(bullet) 120 121 check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, 122 aliens, bullets) 123 124 def check_high_score(stats, sb): 125 """Check to see if there's a new high score.""" 126 if stats.score > stats.high_score: 127 stats.high_score = stats.score 128 sb.prep_high_score() 129 130 def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, 131 aliens, bullets): 132 """Respond to bullet-alien collisions.""" 133 # Remove any bullets and aliens that have collided. 134 collisions = pygame.sprite.groupcollide(bullets, aliens, True, True) 135 136 if collisions: 137 for aliens in collisions.values(): 138 stats.score += ai_settings.alien_points * len(aliens) 139 sb.prep_score() 140 check_high_score(stats, sb) 141 142 if len(aliens) == 0: 143 # If the entire fleet is destroyed, start a new level. 144 bullets.empty() 145 ai_settings.increase_speed() 146 147 # Increase level. 148 stats.level += 1 149 sb.prep_level() 150 151 create_fleet(ai_settings, screen, ship, aliens) 152 153 def check_fleet_edges(ai_settings, aliens): 154 """Respond appropriately if any aliens have reached an edge.""" 155 for alien in aliens.sprites(): 156 if alien.check_edges(): 157 change_fleet_direction(ai_settings, aliens) 158 break 159 160 def change_fleet_direction(ai_settings, aliens): 161 """Drop the entire fleet, and change the fleet's direction.""" 162 for alien in aliens.sprites(): 163 alien.rect.y += ai_settings.fleet_drop_speed 164 ai_settings.fleet_direction *= -1 165 166 def ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets): 167 """Respond to ship being hit by alien.""" 168 if stats.ships_left > 0: 169 # Decrement ships_left. 170 stats.ships_left -= 1 171 172 # Update scoreboard. 173 sb.prep_ships() 174 175 else: 176 stats.game_active = False 177 pygame.mouse.set_visible(True) 178 179 # Empty the list of aliens and bullets. 180 aliens.empty() 181 bullets.empty() 182 183 # Create a new fleet, and center the ship. 184 create_fleet(ai_settings, screen, ship, aliens) 185 ship.center_ship() 186 187 # Pause. 188 sleep(0.5) 189 190 def check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens, 191 bullets): 192 """Check if any aliens have reached the bottom of the screen.""" 193 screen_rect = screen.get_rect() 194 for alien in aliens.sprites(): 195 if alien.rect.bottom >= screen_rect.bottom: 196 # Treat this the same as if the ship got hit. 197 ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets) 198 break 199 200 def update_aliens(ai_settings, screen, stats, sb, ship, aliens, bullets): 201 """ 202 Check if the fleet is at an edge, 203 then update the postions of all aliens in the fleet. 204 """ 205 check_fleet_edges(ai_settings, aliens) 206 aliens.update() 207 208 # Look for alien-ship collisions. 209 if pygame.sprite.spritecollideany(ship, aliens): 210 ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets) 211 212 # Look for aliens hitting the bottom of the screen. 213 check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens, bullets) 214 215 def get_number_aliens_x(ai_settings, alien_width): 216 """Determine the number of aliens that fit in a row.""" 217 available_space_x = ai_settings.screen_width - 2 * alien_width 218 number_aliens_x = int(available_space_x / (2 * alien_width)) 219 return number_aliens_x 220 221 def get_number_rows(ai_settings, ship_height, alien_height): 222 """Determine the number of rows of aliens that fit on the screen.""" 223 available_space_y = (ai_settings.screen_height - 224 (3 * alien_height) - ship_height) 225 number_rows = int(available_space_y / (2 * alien_height)) 226 return number_rows 227 228 def create_alien(ai_settings, screen, aliens, alien_number, row_number): 229 """Create an alien, and place it in the row.""" 230 alien = Alien(ai_settings, screen) 231 alien_width = alien.rect.width 232 alien.x = alien_width + 2 * alien_width * alien_number 233 alien.rect.x = alien.x 234 alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number 235 aliens.add(alien) 236 237 def create_fleet(ai_settings, screen, ship, aliens): 238 """Create a full fleet of aliens.""" 239 # Create an alien, and find number of aliens in a row. 240 alien = Alien(ai_settings, screen) 241 number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width) 242 number_rows = get_number_rows(ai_settings, ship.rect.height, 243 alien.rect.height) 244 245 # Create the fleet of aliens. 246 for row_number in range(number_rows): 247 for alien_number in range(number_aliens_x): 248 create_alien(ai_settings, screen, aliens, alien_number, 249 row_number)
game_stats.py
1 class GameStats(): 2 """Track statistics for Alien Invasion.""" 3 4 def __init__(self, ai_settings): 5 """Initialize statistics.""" 6 self.ai_settings = ai_settings 7 self.reset_stats() 8 9 # Start game in an inactive state. 10 self.game_active = False 11 12 # High score should never be reset. 13 self.high_score = 0 14 15 def reset_stats(self): 16 """Initialize statistics that can change during the game.""" 17 self.ships_left = self.ai_settings.ship_limit 18 self.score = 0 19 self.level = 1
scoreboard.py
1 import pygame.font 2 from pygame.sprite import Group 3 4 from ship import Ship 5 6 class Scoreboard(): 7 """A class to report scoring information.""" 8 9 def __init__(self, ai_settings, screen, stats): 10 """Initialize scorekeeping attributes.""" 11 self.screen = screen 12 self.screen_rect = screen.get_rect() 13 self.ai_settings = ai_settings 14 self.stats = stats 15 16 # Font settings for scoring information. 17 self.text_color = (255, 255, 0) 18 self.font = pygame.font.SysFont(None, 48) 19 20 # Prepare the initial score images. 21 self.prep_score() 22 self.prep_high_score() 23 self.prep_level() 24 self.prep_ships() 25 26 def prep_score(self): 27 """Turn the score into a rendered image.""" 28 rounded_score = int(round(self.stats.score, -1)) 29 score_str = "{:,}".format(rounded_score) 30 self.score_image = self.font.render(score_str, True, self.text_color, 31 self.ai_settings.background) 32 33 # Display the score at the top right of the screen. 34 self.score_rect = self.score_image.get_rect() 35 self.score_rect.right = self.screen_rect.right - 20 36 self.score_rect.top = 20 37 38 def prep_high_score(self): 39 """Turn the high score into a rendered image.""" 40 high_score = int(round(self.stats.high_score, -1)) 41 high_score_str = "{:,}".format(high_score) 42 self.high_score_image = self.font.render(high_score_str, True, 43 self.text_color, self.ai_settings.background) 44 45 # Center the high score at the top of the screen. 46 self.high_score_rect = self.high_score_image.get_rect() 47 self.high_score_rect.centerx = self.screen_rect.centerx 48 self.high_score_rect.top = self.score_rect.top 49 50 def prep_level(self): 51 """Turn the level into a rendered image.""" 52 self.level_image = self.font.render(str(self.stats.level), True, 53 self.text_color, self.ai_settings.background) 54 55 # Position the level below the score. 56 self.level_rect = self.level_image.get_rect() 57 self.level_rect.right = self.score_rect.right 58 self.level_rect.top = self.score_rect.bottom + 10 59 60 def prep_ships(self): 61 """Show how many ships are left.""" 62 self.ships = Group() 63 for ship_number in range(self.stats.ships_left): 64 ship = Ship(self.ai_settings, self.screen) 65 ship.rect.x = 10 + ship_number * ship.rect.width 66 ship.rect.y = 10 67 self.ships.add(ship) 68 69 def show_score(self): 70 """Draw score to the screen.""" 71 self.screen.blit(self.score_image, self.score_rect) 72 self.screen.blit(self.high_score_image, self.high_score_rect) 73 self.screen.blit(self.level_image, self.level_rect) 74 # Draw ships. 75 self.ships.draw(self.screen)
settings.py
1 import pygame 2 class Settings(): 3 """A class to store all settings for Alien Invasion.""" 4 5 def __init__(self): 6 """Initialize the game's static settings.""" 7 # Screen settings. 8 self.screen_width = 1000 9 self.screen_height = 600 10 #self.bg_color = (255, 255, 230) 11 self.background = pygame.image.load(r'.\images\bg.bmp')#加载图像数据 12 13 # Ship settings. 14 self.ship_limit = 3 15 16 # Bullet settings. 17 self.bullet_width = 300 18 self.bullet_height = 15 19 self.bullet_color = 255, 255, 0 20 self.bullets_allowed = 3 21 22 # Alien settings. 23 self.fleet_drop_speed = 10 24 25 # How quickly the game speeds up. 26 self.speedup_scale = 1.1 27 # How quickly the alien point values increase. 28 self.score_scale = 1.5 29 30 self.initialize_dynamic_settings() 31 32 def initialize_dynamic_settings(self): 33 """Initialize settings that change throughout the game.""" 34 self.ship_speed_factor = 1.5 35 self.bullet_speed_factor = 3 36 self.alien_speed_factor = 1 37 38 # Scoring. 39 self.alien_points = 50 40 41 # fleet_direction of 1 represents right, -1 represents left. 42 self.fleet_direction = 1 43 44 def increase_speed(self): 45 """Increase speed settings and alien point values.""" 46 self.ship_speed_factor *= self.speedup_scale 47 self.bullet_speed_factor *= self.speedup_scale 48 self.alien_speed_factor *= self.speedup_scale 49 50 self.alien_points = int(self.alien_points * self.score_scale)
ship.py
1 #ship类,用于管理飞船的行为,用于飞船的图像并显示 2 import pygame 3 from pygame.sprite import Sprite 4 import sys 5 class Ship(Sprite): 6 7 def __init__(self, ai_settings, screen): 8 """初始化飞船并设置其初始位置""" 9 super(Ship, self).__init__() 10 self.screen = screen 11 self.ai_settings = ai_settings 12 13 """加载飞船图像并获得其外接矩形""" 14 self.image = pygame.image.load('images/ship.bmp') 15 self.rect = self.image.get_rect() 16 self.screen_rect = screen.get_rect() 17 18 """将每艘新飞船放在屏幕底部中央""" 19 self.rect.centerx = self.screen_rect.centerx #控制X轴rect对象的属性居中 20 self.rect.centery = self.screen_rect.centery #控制Y轴rect对象的属性居中 21 self.rect.bottom = self.screen_rect.bottom #游戏元素与底部对齐 22 23 """在飞船的属性centerx中存储小数,更细致的控制飞船的速度""" 24 self.centerx = float(self.rect.centerx) 25 self.centery = float(self.rect.centery) 26 27 """移动标志,按键飞船移动为True,不动为False""" 28 self.moving_right = False 29 self.moving_left = False 30 self.moving_up =False 31 self.moving_down =False 32 33 def center_ship(self): 34 """把飞船放在屏幕中央.""" 35 self.center = self.screen_rect.centerx 36 37 def update(self): 38 """根据移动标志调整飞船的位置,并限制其活动范围""" 39 if self.moving_right and self.rect.right < self.screen_rect.right: 40 self.centerx += self.ai_settings.ship_speed_factor 41 if self.moving_left and self.rect.left > 0: 42 self.centerx -= self.ai_settings.ship_speed_factor 43 if self.moving_up and self.rect.top > 0: 44 self.centery -= self.ai_settings.ship_speed_factor 45 if self.moving_down and self.rect.bottom < self.screen_rect.bottom: 46 self.centery += self.ai_settings.ship_speed_factor 47 48 self.rect.centerx = self.centerx 49 self.rect.centery = self.centery 50 51 52 def blitme(self): 53 """在指定位置绘制飞船""" 54 self.screen.blit(self.image, self.rect)

浙公网安备 33010602011771号