本章知识小结:没什么特别重要的,主要是熟悉前面的知识
计分
1、alien_invasion.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 import sysfrom time import sleepimport pygamefrom settings import Settingsfrom game_stats import GameStatsfrom scoreboard import Scoreboardfrom button import Buttonfrom ship import Shipfrom bullet import Bulletfrom alien import Alienclass AlienInvasion : """管理游戏资源和行为的总类。""" def __init__ (self ): """初始化游戏并创建游戏资源。""" 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 .stats = GameStats(self ) self .sb = Scoreboard(self ) self .ship = Ship(self ) self .bullets = pygame.sprite.Group() self .aliens = pygame.sprite.Group() self ._create_fleet() self .play_button = Button(self , "Play" ) def run_game (self ): """启动游戏的主循环。""" while True : self ._check_events() if self .stats.game_active: self .ship.update() self ._update_bullets() self ._update_aliens() self ._update_screen() def _check_events (self ): """响应按键和鼠标事件。""" 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) elif event.type == pygame.MOUSEBUTTONDOWN: mouse_pos = pygame.mouse.get_pos() self ._check_play_button(mouse_pos) def _check_play_button (self, mouse_pos ): """玩家单击Play按钮时开始新游戏。""" button_clicked = self .play_button.rect.collidepoint(mouse_pos) if button_clicked and not self .stats.game_active: self .settings.initialize_dynamic_settings() self .stats.reset_stats() self .stats.game_active = True self .sb.prep_score() self .sb.prep_level() self .sb.prep_ships() self .aliens.empty() self .bullets.empty() self ._create_fleet() self .ship.center_ship() pygame.mouse.set_visible(False ) def _check_keydown_events (self, event ): """响应按键。""" 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 ): """响应按键松开。""" 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 ): """创建一颗新子弹并将其加入到子弹编组中。""" if len (self .bullets) < self .settings.bullets_allowed: new_bullet = Bullet(self ) self .bullets.add(new_bullet) def _update_bullets (self ): """更新子弹的位置并删除已消失的子弹。""" self .bullets.update() for bullet in self .bullets.copy(): if bullet.rect.bottom <= 0 : self .bullets.remove(bullet) self ._check_bullet_alien_collisions() def _check_bullet_alien_collisions (self ): """响应子弹与外星人的碰撞。""" collisions = pygame.sprite.groupcollide( self .bullets, self .aliens, True , True ) if collisions: for aliens in collisions.values(): self .stats.score += self .settings.alien_points * len (aliens) self .sb.prep_score() self .sb.check_high_score() if not self .aliens: self .bullets.empty() self ._create_fleet() self .settings.increase_speed() self .stats.level += 1 self .sb.prep_level() def _update_aliens (self ): """ 检查外星人是否位于屏幕边缘, 然后更新外星人群中所有外星人的位置。 """ self ._check_fleet_edges() self .aliens.update() if pygame.sprite.spritecollideany(self .ship, self .aliens): self ._ship_hit() self ._check_aliens_bottom() def _check_aliens_bottom (self ): """检查是否有外星人到达屏幕底端。""" screen_rect = self .screen.get_rect() for alien in self .aliens.sprites(): if alien.rect.bottom >= screen_rect.bottom: self ._ship_hit() break def _ship_hit (self ): """响应飞船被外星人撞击。""" if self .stats.ships_left > 0 : self .stats.ships_left -= 1 self .sb.prep_ships() self .aliens.empty() self .bullets.empty() self ._create_fleet() self .ship.center_ship() sleep(0.5 ) else : self .stats.game_active = False pygame.mouse.set_visible(True ) def _create_fleet (self ): """创建外星人舰队。""" 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) 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) 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 ): """创建外星人并将其放置在行中。""" 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 ): """适时响应外星人到达边缘的情况。""" for alien in self .aliens.sprites(): if alien.check_edges(): self ._change_fleet_direction() break def _change_fleet_direction (self ): """下移整个外星人舰队并改变舰队的方向。""" for alien in self .aliens.sprites(): alien.rect.y += self .settings.fleet_drop_speed self .settings.fleet_direction *= -1 def _update_screen (self ): """更新屏幕上的图像并翻转到新屏幕。""" self .screen.fill(self .settings.bg_color) self .ship.blitme() for bullet in self .bullets.sprites(): bullet.draw_bullet() self .aliens.draw(self .screen) self .sb.show_score() if not self .stats.game_active: self .play_button.draw_button() pygame.display.flip() if __name__ == '__main__' : ai = AlienInvasion() ai.run_game()
2、alien.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import pygamefrom pygame.sprite import Spriteclass Alien (Sprite ): """表示舰队中单个外星人的类。""" 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 ): """如果外星人位于屏幕边缘,则返回True。""" screen_rect = self .screen.get_rect() if self .rect.right >= screen_rect.right or self .rect.left <= 0 : return True def update (self ): """将外星人向右或向左移动。""" self .x += (self .settings.alien_speed * self .settings.fleet_direction) self .rect.x = self .x
3、bullet.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import pygamefrom pygame.sprite import Spriteclass Bullet (Sprite ): """管理从飞船发射的子弹的类""" def __init__ (self, ai_game ): """在飞船当前位置创建子弹对象。""" super ().__init__() self .screen = ai_game.screen self .settings = ai_game.settings self .color = self .settings.bullet_color self .rect = pygame.Rect(0 , 0 , self .settings.bullet_width, self .settings.bullet_height) self .rect.midtop = ai_game.ship.rect.midtop self .y = float (self .rect.y) def update (self ): """将子弹向上移动屏幕。""" self .y -= self .settings.bullet_speed self .rect.y = self .y def draw_bullet (self ): """将子弹绘制到屏幕上。""" pygame.draw.rect(self .screen, self .color, self .rect)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import pygame.fontclass Button : def __init__ (self, ai_game, msg ): """初始化按钮属性。""" self .screen = ai_game.screen self .screen_rect = self .screen.get_rect() self .width, self .height = 200 , 50 self .button_color = (0 , 255 , 0 ) self .text_color = (255 , 255 , 255 ) self .font = pygame.font.SysFont(None , 48 ) self .rect = pygame.Rect(0 , 0 , self .width, self .height) self .rect.center = self .screen_rect.center self ._prep_msg(msg) def _prep_msg (self, msg ): """将消息转换为渲染图像并使文本居中在按钮上。""" self .msg_image = self .font.render(msg, True , self .text_color, self .button_color) self .msg_image_rect = self .msg_image.get_rect() self .msg_image_rect.center = self .rect.center def draw_button (self ): self .screen.fill(self .button_color, self .rect) self .screen.blit(self .msg_image, self .msg_image_rect)
5、game_stats.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class GameStats : """跟踪《Alien Invasion》的统计信息。""" def __init__ (self, ai_game ): """初始化统计信息。""" self .settings = ai_game.settings self .reset_stats() self .game_active = False self .high_score = 0 def reset_stats (self ): """初始化游戏中可能会变化的统计信息。""" self .ships_left = self .settings.ship_limit self .score = 0 self .level = 1
6、scoreboard.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import pygame.fontfrom pygame.sprite import Groupfrom ship import Shipclass Scoreboard : """报告得分信息的类。""" def __init__ (self, ai_game ): """初始化记分属性。""" self .ai_game = ai_game self .screen = ai_game.screen self .screen_rect = self .screen.get_rect() self .settings = ai_game.settings self .stats = ai_game.stats self .text_color = (30 , 30 , 30 ) self .font = pygame.font.SysFont(None , 48 ) self .prep_score() self .prep_high_score() self .prep_level() self .prep_ships() def prep_score (self ): """将得分转换为渲染图像。""" rounded_score = round (self .stats.score, -1 ) score_str = "{:,}" .format (rounded_score) self .score_image = self .font.render(score_str, True , self .text_color, self .settings.bg_color) self .score_rect = self .score_image.get_rect() self .score_rect.right = self .screen_rect.right - 20 self .score_rect.top = 20 def prep_high_score (self ): """将最高得分转换为渲染图像。""" high_score = round (self .stats.high_score, -1 ) high_score_str = "{:,}" .format (high_score) self .high_score_image = self .font.render(high_score_str, True , self .text_color, self .settings.bg_color) self .high_score_rect = self .high_score_image.get_rect() self .high_score_rect.centerx = self .screen_rect.centerx self .high_score_rect.top = self .score_rect.top def prep_level (self ): """将级别转换为渲染图像。""" level_str = str (self .stats.level) self .level_image = self .font.render(level_str, True , self .text_color, self .settings.bg_color) self .level_rect = self .level_image.get_rect() self .level_rect.right = self .score_rect.right self .level_rect.top = self .score_rect.bottom + 10 def prep_ships (self ): """显示剩余的飞船数量。""" self .ships = Group() for ship_number in range (self .stats.ships_left): ship = Ship(self .ai_game) ship.rect.x = 10 + ship_number * ship.rect.width ship.rect.y = 10 self .ships.add(ship) def check_high_score (self ): """检查是否有新的最高得分。""" if self .stats.score > self .stats.high_score: self .stats.high_score = self .stats.score self .prep_high_score() def show_score (self ): """在屏幕上绘制得分、级别和飞船数量。""" self .screen.blit(self .score_image, self .score_rect) self .screen.blit(self .high_score_image, self .high_score_rect) self .screen.blit(self .level_image, self .level_rect) self .ships.draw(self .screen)
7、settings.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class Settings : """存储《Alien Invasion》的所有设置的类。""" def __init__ (self ): """初始化游戏的静态设置。""" self .screen_width = 1200 self .screen_height = 800 self .bg_color = (230 , 230 , 230 ) self .ship_limit = 3 self .bullet_width = 3 self .bullet_height = 15 self .bullet_color = (60 , 60 , 60 ) self .bullets_allowed = 3 self .fleet_drop_speed = 10 self .speedup_scale = 1.1 self .score_scale = 1.5 self .initialize_dynamic_settings() def initialize_dynamic_settings (self ): """初始化在游戏中变化的设置。""" self .ship_speed = 1.5 self .bullet_speed = 3.0 self .alien_speed = 1.0 self .fleet_direction = 1 self .alien_points = 50 def increase_speed (self ): """增加速度设置和外星人点数值。""" self .ship_speed *= self .speedup_scale self .bullet_speed *= self .speedup_scale self .alien_speed *= self .speedup_scale self .alien_points = int (self .alien_points * self .score_scale)
8、ship.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import pygamefrom pygame.sprite import Spriteclass Ship (Sprite ): """管理飞船的类。""" def __init__ (self, ai_game ): """初始化飞船并设置其起始位置。""" super ().__init__() self .screen = ai_game.screen self .settings = ai_game.settings self .screen_rect = ai_game.screen.get_rect() self .image = pygame.image.load('images/ship.bmp' ) self .rect = self .image.get_rect() self .rect.midbottom = self .screen_rect.midbottom self .x = float (self .rect.x) self .moving_right = False self .moving_left = False def update (self ): """根据移动标志更新飞船的位置。""" 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 self .rect.x = self .x def blitme (self ): """在当前位置绘制飞船。""" self .screen.blit(self .image, self .rect) def center_ship (self ): """将飞船居中在屏幕上。""" self .rect.midbottom = self .screen_rect.midbottom self .x = float (self .rect.x)
9、测试