[Python]簡單的外星人入侵游戲


alien_invasion.py:

 

 1 import sys
 2 
 3 import pygame
 4 
 5 from setting import Settings
 6 from ship import Ship
 7 import game_function as gf
 8 from pygame.sprite import Group
 9 from  alien import Alien
10 from game_stats import GameStats
11 from button import Button
12 from scoreboard import ScoreBoard
13 
14 def run_game():
15     # 初始化游戲並創建於一個屏幕對象
16     pygame.init()
17     ai_setting = Settings()
18     screen = pygame.display.set_mode((ai_setting.screen_width, ai_setting.screen_height))
19     pygame.display.set_caption("Alien Invasion")
20 
21     # 創建一艘飛船、一個子彈編組和一個外星人編組
22     ship = Ship(ai_setting, screen)
23     bullets = Group()
24     aliens = Group()
25 
26     # 創建外星人群
27     gf.create_fleet(ai_setting, screen, ship, aliens)
28     stats = GameStats(ai_setting)
29     # 創建存儲游戲統計信息的實例,並創建及分牌
30     sb = ScoreBoard(ai_setting, screen, stats)
31     # 創建Play按鈕
32     play_button = Button(ai_setting, screen, "Play")
33 
34     # 開始游戲的主循環
35     while True:
36         gf.check_events(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets)
37         if stats.game_active:
38             ship.update()
39             gf.update_bullets(ai_setting, screen, stats,  sb, ship, aliens, bullets)
40             gf.update_aliens(ai_setting, stats, screen, sb, ship, aliens, bullets)
41 
42         gf.update_screen(ai_setting, screen, stats, sb, ship, aliens, bullets, play_button)
43 
44 run_game()

 

game_stats.py:

 

 1 class GameStats():
 2     """跟蹤游戲的統計信息"""
 3 
 4     def __init__(self, ai_setting):
 5         """初始化統計信息"""
 6         self.ai_setting = ai_setting
 7         self.reset_stats()
 8         self.game_active = False
 9         # 在任何情況下都不應該充值最高得分
10         self.high_score = 0
11 
12     def reset_stats(self):
13         """初始化在游戲運行期間可能變化的統計信息"""
14         self.ship_left = self.ai_setting.ship_limit
15         self.score = 0
16         self.level = 1

 

scoreboard.py:

 

 1 import pygame.font
 2 from pygame.sprite import Group
 3 from ship import Ship
 4 
 5 class ScoreBoard():
 6     """現實得分信息的類"""
 7 
 8     def __init__(self, ai_setting, screen, stats):
 9         """初始化現實得分涉及的屬性"""
10         self.screen = screen
11         self.screen_rect = screen.get_rect()
12         self.ai_setting = ai_setting
13         self.stats =stats
14 
15         # 顯示得分信息時使用的設置
16         self.text_color = (30, 30, 30)
17         self.font = pygame.font.SysFont(None, 48)
18 
19         # 准備包含最高得分和當前得分的圖像
20         self.prep_score()
21         self.prep_high_score()
22         self.prep_level()
23         self.prep_ships()
24 
25     def prep_ships(self):
26         """顯示還有下多少艘飛船"""
27         self.ships = Group()
28         for ship_number in range(self.stats.ship_left):
29             ship = Ship(self.ai_setting, self.screen)
30             ship.rect.x = 10 + ship_number * ship.rect.width
31             ship.rect.y = 10
32             self.ships.add(ship)
33 
34     def prep_score(self):
35         """將得分轉換為一幅渲染的圖像"""
36         rounded_score = int(round(self.stats.score, -1))
37         score_str = "{:,}".format(rounded_score)
38         self.score_image = self.font.render(score_str, True, self.text_color, self.ai_setting.bg_color)
39 
40         # 將得分放在屏幕右上角
41         self.score_rect = self.score_image.get_rect()
42         self.score_rect.right = self.screen_rect.right - 20
43         self.score_rect.top = 20
44 
45     def show_score(self):
46         """在屏幕上顯示得分"""
47         self.screen.blit(self.score_image, self.score_rect)
48         self.screen.blit(self.high_score_image, self.high_score_rect)
49         self.screen.blit(self.level_image, self.level_rect)
50         # 繪制飛船
51         self.ships.draw(self.screen)
52 
53     def prep_high_score(self):
54         """將最高得分轉化為渲染的圖像"""
55         high_score = int(round(self.stats.high_score, -1))
56         high_score_str = "{:,}".format(high_score)
57         self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.ai_setting.bg_color)
58 
59         #將最高分放在屏幕頂部中央
60         self.high_score_rect = self.high_score_image.get_rect()
61         self.high_score_rect.centerx = self.screen_rect.centerx
62         self.high_score_rect.top = self.score_rect.top
63 
64     def prep_level(self):
65         """降等級轉化為渲染的圖像"""
66         self.level_image = self.font.render(str(self.stats.level), True, self.text_color, self.ai_setting.bg_color)
67 
68         # 降等級放在得分下方
69         self.level_rect = self.level_image.get_rect()
70         self.level_rect.right = self.score_rect.right
71         self.level_rect.top = self.score_rect.bottom + 10

 

button.py:

 

 1 import pygame.font
 2 
 3 class Button():
 4     def __init__(self, ai_setting, screen, msg):
 5         """初始化按鈕的屬性"""
 6         self.screen = screen
 7         self.screen_rect = screen.get_rect()
 8 
 9         # 設置按鈕的尺寸和其他屬性
10         self.width = 200
11         self.height = 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         # 創建按鈕的rect對象,並使其居中
17         self.rect = pygame.Rect(0, 0, self.width, self.height)
18         self.rect.center = self.screen_rect.center
19 
20         # 按鈕的標簽只需創建一次
21         self.prep_msg(msg)
22 
23     def prep_msg(self, msg):
24         """將msg渲染為圖像並使其在按鈕上居中"""
25         self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)
26         self.msg_image_rect = self.msg_image.get_rect()
27         self.msg_image_rect.center = self.rect.center
28 
29     def draw_button(self):
30         # 繪制一個用顏色填充的按鈕,在繪制文本
31         self.screen.fill(self.button_color, self.rect)
32         self.screen.blit(self.msg_image, self.msg_image_rect)

 

game_function.py:

 

  1 import sys
  2 
  3 import pygame
  4 from bullet import Bullet
  5 from alien import Alien
  6 from time import sleep
  7 
  8 def check_events(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets):
  9     """響應按鍵和鼠標事件"""
 10     for event in pygame.event.get():
 11         if event.type == pygame.QUIT:
 12             sys.exit()
 13 
 14         elif event.type == pygame.KEYDOWN:
 15             if event.key == pygame.K_RIGHT:
 16                 # 向右移動飛船
 17                 ship.moving_right = True
 18             elif event.key == pygame.K_LEFT:
 19                 ship.moving_left = True
 20             elif event.key == pygame.K_SPACE:
 21                 # 創建一顆子彈,並將其加入到編組bullets中
 22                 if len(bullets) < ai_setting.bullets_allowed:
 23                     new_bullet = Bullet(ai_setting, screen, ship)
 24                     bullets.add(new_bullet)
 25             elif event.key == pygame.K_q:
 26                 sys.exit()
 27         elif event.type == pygame.MOUSEBUTTONDOWN:
 28             mouse_x, mouse_y = pygame.mouse.get_pos()
 29             check_play_button(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y)
 30 
 31         elif event.type == pygame.KEYUP:
 32             if event.key == pygame.K_RIGHT:
 33                 ship.moving_right = False
 34             elif event.key == pygame.K_LEFT:
 35                 ship.moving_left = False
 36 
 37 def check_play_button(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y):
 38     """玩家單擊Play按鈕時開始新游戲"""
 39     button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
 40     if button_clicked and not stats.game_active:
 41         #重置游戲設置
 42         ai_setting.initialize_dynamic_settings()
 43 
 44         # 隱藏光標
 45         pygame.mouse.set_visible(False)
 46         # 重置游戲信息
 47         stats.reset_stats()
 48         stats.game_active = True
 49 
 50         # 重置記分牌圖像
 51         sb.prep_score()
 52         sb.prep_high_score()
 53         sb.prep_level()
 54         sb.prep_ships()
 55 
 56         # 清空外星人列表和子彈列表
 57         aliens.empty()
 58         bullets.empty()
 59 
 60         # 創建一群新的外星人,並讓飛船居中
 61         create_fleet(ai_setting, screen, ship, aliens)
 62         ship.center_ship()
 63 
 64 def update_screen(ai_setting, screen, stats, sb, ship,alien, bullets, play_button):
 65     """更新屏幕上的圖像,並切換到新屏幕"""
 66     # 每次循環時都重繪屏幕
 67     screen.fill(ai_setting.bg_color)
 68     # 在飛船和外星人后面重繪所有子彈
 69     for bullet in bullets.sprites():
 70         bullet.draw_bullet()
 71     ship.blitme()
 72     alien.draw(screen)
 73     # 顯示得分
 74     sb.show_score()
 75 
 76     # 如果游戲處於非活動狀態,繪制Play按鈕
 77     if not stats.game_active:
 78         play_button.draw_button()
 79 
 80     # 讓最近繪制的屏幕可見
 81     pygame.display.flip()
 82 
 83 def update_bullets(ai_setting, screen, stats,  sb, ship, aliens, bullets):
 84     """更新子彈位置,並刪除已消失的子彈"""
 85     # 刪除子彈的位置
 86     bullets.update()
 87     # 刪除已消失的子彈
 88     for bullet in bullets.copy():
 89         if bullet.rect.bottom <= 0:
 90             bullets.remove(bullet)
 91     check_bullet_alien_colisions(ai_setting, screen, stats,  sb, ship, aliens, bullets)
 92 
 93 def check_high_score(stats, sb):
 94     """檢查是否誕生了新的最高得分"""
 95     if stats.score > stats.high_score:
 96         stats.high_score = stats.score
 97         sb.prep_high_score()
 98 
 99 def check_bullet_alien_colisions(ai_setting, screen, stats,  sb, ship, aliens, bullets):
100     """響應是否有子彈擊中了外星人"""
101     # 如果是這樣,就刪除相應的子彈和外星人
102     collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
103 
104     if collisions:
105         for aliens in collisions.values():
106             stats.score += ai_setting.alien_points * len(aliens)
107             sb.prep_score()
108         check_high_score(stats, sb)
109 
110     if len(aliens) == 0:
111         # 刪除現在的子彈,加快游戲節奏,並新建一群外星人
112         bullets.empty()
113         ai_setting.increase_speed()
114 
115         # 提高一個等級
116         stats.level += 1
117         sb.prep_level()
118 
119         create_fleet(ai_setting, screen, ship, aliens)
120 
121 
122 def get_number_alien_x(ai_setting, alien_width):
123     """計算每行可容納多少個個外星人"""
124     available_space_x = ai_setting.screen_width - 2 * alien_width
125     number_aliens_x = int(available_space_x / (2 * alien_width))
126     return number_aliens_x
127 
128 def create_alien(ai_setting, screen, aliens, alien_number, row_number):
129     # 創建一個外星人並將其加入當前行
130     alien = Alien(ai_setting, screen)
131     alien_width = alien.rect.width
132     alien.x = alien_width + 2 * alien_width * alien_number
133     alien.rect.x = alien.x
134     alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
135     aliens.add(alien)
136 
137 def create_fleet(ai_setting, screen, ship, aliens):
138     """創建外星人群"""
139     # 創建一個外星人,並計算一行可容納多少個外星人
140     # 外星人間距為外星人寬度
141     alien = Alien(ai_setting, screen)
142     number_aliens_x = get_number_alien_x(ai_setting, alien.rect.width)
143     number_rows = get_number_rows(ai_setting, ship.rect.height, alien.rect.height)
144 
145     # 創建第一行外星人
146     for row_number in range(number_rows):
147         for alien_number in range(number_aliens_x):
148             create_alien(ai_setting, screen, aliens, alien_number, row_number)
149 
150 
151 def get_number_rows(ai_setting, ship_height, alien_height):
152     """計算屏幕可容納多少行外星人"""
153     available_space_y = (ai_setting.screen_height - (3 * alien_height) - ship_height)
154     number_rows = int(available_space_y / (2 * alien_height))
155     return number_rows
156 
157 def check_fleet_edges(ai_setting, aliens):
158     """有外星人到達邊緣時采取相應的措施"""
159     for alien in aliens.sprites():
160         if alien.check_edges():
161             change_fleet_direction(ai_setting, aliens)
162             break
163 
164 def change_fleet_direction(ai_setting, aliens):
165     """將整群外星人下移"""
166     for alien in aliens.sprites():
167         alien.rect.y += ai_setting.fleet_drop_speed
168     ai_setting.fleet_direction *= -1
169 
170 def update_aliens(ai_setting, stats, screen, sb, ship, aliens, bullets):
171     check_fleet_edges(ai_setting, aliens)
172     aliens.update()
173 
174     # 檢測外星人和飛船之間的碰撞
175     if pygame.sprite.spritecollideany(ship, aliens):
176         ship_hit(ai_setting, stats, screen, sb, ship, aliens, bullets)
177     # 檢查是否有外星人大大屏幕底端
178     check_aliens_bottom(ai_setting, stats, screen, sb, ship, aliens, bullets)
179 
180 def ship_hit(ai_setting, stats, screen, sb, ship, aliens, bullets):
181     """響應被外星人撞到的飛船"""
182     if stats.ship_left > 0:
183         # 將ship_left減1
184         stats.ship_left -= 1
185 
186         # 更新記分牌
187         sb.prep_ships()
188 
189         #清空外星人列表和子彈列表
190         aliens.empty()
191         bullets.empty()
192 
193         # 創建一群新的外星人,並將飛船放到屏幕低端中央
194         create_fleet(ai_setting, screen, ship, aliens)
195         ship.center_ship()
196 
197         # 暫停
198         sleep(0.5)
199     else:
200         stats.game_active = False
201 
202 def check_aliens_bottom(ai_setting, stats, screen, sb, ship, aliens, bullets):
203     """檢查是否有外星人到達了屏幕底端"""
204     screen_rect = screen.get_rect()
205     for alien in aliens.sprites():
206         if alien.rect.bottom >= screen_rect.bottom:
207             # 像飛船被撞到一樣進行處理
208             ship_hit(ai_setting, stats, screen, sb, ship, aliens, bullets)
209             break

 

alien.py:

 

 1 import pygame
 2 from pygame.sprite import Sprite
 3 
 4 class Alien(Sprite):
 5     """表示單個外星人的類"""
 6 
 7     def __init__(self, ai_setting, screen):
 8         """初始化外星人並設置其起始位置"""
 9         super(Alien, self).__init__()
10         self.screen = screen
11         self.ai_setting = ai_setting
12 
13         # 加載外星人圖像,並設計其rect屬性
14         self.image = pygame.image.load('images/alien.bmp')
15         self.rect = self.image.get_rect()
16 
17         # 每個外星人最初都在屏幕左上角附近
18         self.rect.x = self.rect.width
19         self.rect.y = self.rect.height
20 
21         # 存儲外星人的准確位置
22         self.x = float(self.rect.x)
23 
24     def blitme(self):
25         """在指定位置繪制外星人"""
26         self.screen.blit(self.image, self.rect)
27 
28     def check_edges(self):
29         """如果外星人位於屏幕邊緣,就返回True"""
30         screen_rect = self.screen.get_rect()
31         if self.rect.right >= screen_rect.right:
32             return True
33         elif self.rect.left <= 0:
34             return True
35 
36     def update(self):
37         """向右移動外星人"""
38         self.x += (self.ai_setting.alien_speed_factor * self.ai_setting.fleet_direction)
39         self.rect.x = self.x

 

setting.py:

 

 1 class Settings():
 2     """存儲《外星人入侵》的所有設置的類"""
 3 
 4     def __init__(self):
 5         """初始化游戲的設置"""
 6         # 屏幕設置
 7         self.screen_width = 900
 8         self.screen_height = 600
 9         self.bg_color = (230, 230, 230)
10         # 飛船的設置
11         self.ship_speed_factor = 1.5
12         # 子彈設置
13         self.bullet_speed_factor = 3
14         self.bullet_width = 3
15         self.bullet_height = 15
16         self.bullet_color = 60, 60, 60
17         self.bullets_allowed = 3
18         self.alien_speed_factor = 1
19         self.fleet_drop_speed = 10
20         self.fleet_direction = 1
21         self.ship_limit = 3
22         # 以什么樣的速度加快游戲的節奏
23         self.speedup_scale = 1.1
24         #外星人點數的提高速度
25         self.score_scale = 1.5
26 
27         self.initialize_dynamic_settings()
28 
29     def initialize_dynamic_settings(self):
30         """初始化隨游戲進行而變化的位置"""
31         self.ship_speed_factor = 1.5
32         self.bullet_speed_factor = 3
33         self.alien_speed_factor = 1
34 
35         # fleet_direction為1表示向右;為-1表示向左
36         self.fleet_direction =1
37         # 記分
38         self.alien_points = 50
39 
40     def increase_speed(self):
41         """提高速度設置"""
42         self.ship_speed_factor *= self.speedup_scale
43         self.bullet_speed_factor *= self.speedup_scale
44         self.bullet_speed_factor *= self.speedup_scale
45         self.alien_points = int(self.alien_points * self.score_scale)

 

bullet.py:

 

 1 import pygame
 2 from pygame.sprite import Sprite
 3 
 4 class Bullet(Sprite):
 5     """一個對飛船發射的子彈進行管理的類"""
 6     def __init__(self, ai_setting, screen, ship):
 7         """在飛船所處的位置創建一個子彈對象"""
 8         super(Bullet, self).__init__()
 9         self.screen = screen
10 
11         # 在(0,0)處創建一個表示子彈的矩形,在設置正確的位置
12         self.rect = pygame.Rect(0, 0, ai_setting.bullet_width, ai_setting.bullet_height)
13         self.rect.centerx = ship.rect.centerx
14         self.rect.top = ship.rect.top
15 
16         # 存儲用小數表示的子彈位置
17         self.y = float(self.rect.y)
18 
19         self.color = ai_setting.bullet_color
20         self.speed_factor = ai_setting.bullet_speed_factor
21 
22     def update(self):
23         """向上移動子彈"""
24         # 更新表示子彈位置的小數值
25         self.y -= self.speed_factor
26         # 更新表示子彈的rect的位置
27         self.rect.y = self.y
28 
29     def draw_bullet(self):
30         pygame.draw.rect(self.screen, self.color, self.rect)

 

ship.py:

 

 1 import  pygame
 2 from pygame.sprite import Sprite
 3 
 4 class Ship(Sprite):
 5 
 6     def __init__(self, ai_setting, screen):
 7         """初始化飛船並設置其初始位置"""
 8         super(Ship, self).__init__()
 9         self.screen = screen
10         self.ai_setting = ai_setting
11 
12         """加載飛船圖像並獲取其外接矩陣"""
13         self.image = pygame.image.load('images/ship.bmp')
14         self.rect = self.image.get_rect()
15         self.screen_rect = screen.get_rect()
16 
17         # 將每艘新飛船放在屏幕底部中央
18         self.rect.centerx = self.screen_rect.centerx
19         self.rect.bottom = self.screen_rect.bottom
20 
21         # 在飛船的屬性center中存儲小數值
22         self.center = float(self.rect.centerx)
23 
24         # 移動標志
25         self.moving_right = False
26         self.moving_left = False
27 
28     def update(self):
29         """根據移動標志調增飛船的位置"""
30         if self.moving_right and self.rect.right < self.screen_rect.right:
31             self.center += self.ai_setting.ship_speed_factor
32         if self.moving_left and self.rect.left > 0:
33             self.center -= self.ai_setting.ship_speed_factor
34 
35         """根據self.center調整飛船的位置"""
36         self.rect.centerx = self.center
37 
38     def blitme(self):
39         """在指定為這繪制飛船"""
40         self.screen.blit(self.image, self.rect)
41 
42     def center_ship(self):
43         self.center = self.screen_rect.centerx

 

 

圖片:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM