本章知识小结:没什么特别重要的,主要是熟悉前面的知识
外星人来了
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
| 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: """管理游戏资源和行为的总体类."""
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.ship = Ship(self) self.bullets = pygame.sprite.Group() self.aliens = pygame.sprite.Group()
self._create_fleet()
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)
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 not self.aliens: self.bullets.empty() self._create_fleet()
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.aliens.empty() self.bullets.empty() self._create_fleet() self.ship.center_ship() sleep(0.5) else: self.stats.game_active = False
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)
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
| import pygame from pygame.sprite import Sprite
class 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.png') 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
|
1.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 pygame from pygame.sprite import Sprite
class 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.4 game_stats.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class GameStats: """跟踪《外星人入侵》的统计信息。"""
def __init__(self, ai_game): """初始化统计信息。""" self.settings = ai_game.settings self.reset_stats()
self.game_active = True
def reset_stats(self): """初始化游戏中可能变化的统计信息。""" self.ships_left = self.settings.ship_limit
|
5、setting.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
| class Settings: """一个存储《外星人入侵》所有设置的类。"""
def __init__(self): """初始化游戏的设置。""" self.screen_width = 1200 self.screen_height = 800 self.bg_color = (230, 230, 230)
self.ship_speed = 1.5 self.ship_limit = 3
self.bullet_speed = 1.5 self.bullet_width = 3 self.bullet_height = 15 self.bullet_color = (60, 60, 60) self.bullets_allowed = 3
self.alien_speed = 1.0 self.fleet_drop_speed = 10 self.fleet_direction = 1
|
1.6 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
| import pygame
class Ship: """管理飞船的类。"""
def __init__(self, ai_game): """初始化飞船并设置其起始位置。""" 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.png') 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)
|
1.7 测试游戏