《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)

 

posted @ 2020-08-13 19:12  彳朝闻道亍  阅读(336)  评论(0)    收藏  举报