Python pygame庫的應用


今天想用pygame庫寫一個擊打外星人飛船的python程序

這個游戲的效果是操縱一個位於屏幕底端的飛船,通過上下左右控制飛船移動方向,按空格發射子彈。游戲中擊殺一批飛船后進入下一關卡。每一關卡擊打飛船獲得的得分遞增。若外星飛船觸碰飛船或屏幕底端則減一條命。最終計算總得分。

游戲中主要包括了:飛船對象,alien對象,子彈對象,游戲設置,游戲狀態,游戲控制按鈕,計分板。

1.飛船部分

由於pygame中已有sprite類,故飛船可直接繼承sprite類
注意在繼承類時class中標注繼承了什么類,_ _init_ _函數中要使用super(Ship,self).__init__()來完成繼承工作。同時init中也引入了ai—setting和screen(這些部分的代碼會在后面寫出)

然后為了構建這個飛船的形態,需要在當前文件夾中保存一個飛船的圖像。初始化時設置飛船矩形(rect)的中心與游戲界面的中心位於同一垂直線上,飛船底部位於屏幕底端。初始化時定義四個位移變量(上下左右)並設置為false,以便后面按鍵時對其進行改變。
接下來定義了update函數,這個函數的作用是改變飛船的當前狀態,如按下←鍵時使得飛船左移。同時需要注意:飛船的左側不能超過屏幕的左端,否則會很影響游戲體驗。其余同理。
然后是blitme函數,這個函數完成了將飛船狀態及時更新在屏幕上的工作。
最后寫了一個centership函數,是用來在需要的時刻將飛船重新放置到屏幕中央。

 1 import pygame
 2 from pygame.sprite import Sprite
 3 
 4 class Ship(Sprite):#繼承sprite類
 5 
 6 def __init__(self,ai_settings,screen):
 7 super(Ship,self).__init__()
 8 self.screen=screen
 9 self.ai_settings=ai_settings
10 
11 self.image=pygame.image.load('images/ship.bmp')
12 self.rect=self.image.get_rect()
13 self.screen_rect=screen.get_rect()
14 
15 self.rect.centerx=self.screen_rect.centerx
16 self.rect.bottom=self.screen_rect.bottom
17 
18 self.center=float(self.rect.centerx)
19 self.high=float(self.rect.bottom)
20 
21 self.moving_right=False
22 self.moving_left=False
23 self.moving_up=False
24 self.moving_down=False
25 
26 
27 def update(self):
28 if self.moving_right and self.rect.right<self.screen_rect.right:
29 #self.rect.centerx+=1
30 self.center+=self.ai_settings.ship_speed_factor_horizen
31 if self.moving_left and self.rect.left>self.screen_rect.left:
32 #self.rect.centerx-=1
33 self.center-=self.ai_settings.ship_speed_factor_horizen
34 if self.moving_up and self.rect.top>self.screen_rect.top:
35 
36 self.high-=self.ai_settings.ship_speed_factor_height
37 if self.moving_down and self.rect.bottom<self.screen_rect.bottom:
38 
39 self.high+=self.ai_settings.ship_speed_factor_height
40 
41 
42 
43 self.rect.centerx=self.center
44 self.rect.bottom=self.high
45 
46 def blitme(self):
47 
48 self.screen.blit(self.image,self.rect)
49 def center_ship(self):
50 self.center=self.screen_rect.centerx
View Code(ship)

 


給出alien部分:
alien部分生成了飛船群
然后為了產生初始的隨機方向飛行,引入了random庫。
同樣的,這里的alien也繼承了Sprite精靈。
注意,這里的飛船圖像必須保存在當前文件夾下,然后用pygame.load來加載圖片。
一個細節,由於alien移動距離是浮點型,所以要先計算移動的浮點類型,最后將其轉換成整形以保證移動的連續性。同時由於alien圖像必須保證一直處在screen內,所以這里定義了一個方法check_edges,通過self.screen.get_rect()來獲取屏幕的位置,將alien與screen都視為矩形,比較兩者的邊界即可。

 1 import pygame
 2 import random##########
 3 from pygame.sprite import Sprite
 4 
 5 class Alien(Sprite):
 6 
 7 def __init__(self,ai_settings,screen):
 8 super(Alien,self).__init__()
 9 self.screen=screen
10 self.ai_settings=ai_settings
11 
12 
13 self.image=pygame.image.load('images/alien.bmp')
14 self.rect=self.image.get_rect()
15 
16 self.rect.x=self.rect.width#-20
17 self.rect.y=self.rect.height#-20
18 
19 self.direction=random.choice([1,-1])
20 
21 
22 self.x=float(self.rect.x)
23 
24 def check_edges(self):
25 screen_rect=self.screen.get_rect()
26 if self.rect.right>=screen_rect.right:
27 return True
28 elif self.rect.left<=screen_rect.left:
29 return True
30 
31 
32 def blitme(self):
33 self.screen.blit(self.image,self.rect)
34 
35 
36 def update(self):
37 #由於x可以精確到小數,故先更新x,再用x更新rect
38 self.x+=(self.ai_settings.alien_speed_factor*
39 self.direction)#*random.choice([1,-1])#####
40 self.rect.x=self.x
View Code(alien)

 

給出bullet部分。
bullet同ship,alien一樣,也繼承了sprite。
注意,由於子彈是由飛船從飛船上部發出,故初始化子彈時要將其位置設置在飛船上部中央,子彈大小也不能過大。因為子彈大小較小,所以用pygame中的draw.rect(self.screen,self.color,self.rect)來畫出一個小矩形即可,這種方法比較省事。如果想要使子彈的形狀更加美觀,可以用上面ship和alien中加載位圖的方式。

 1 import pygame
 2 from pygame.sprite import Sprite
 3 
 4 class Bullet(Sprite):
 5 
 6 
 7 def __init__(self,ai_settings,screen,ship):
 8 
 9 super(Bullet,self).__init__()
10 self.screen=screen
11 
12 self.rect=pygame.Rect(0,0,ai_settings.bullet_width,
13 ai_settings.bullet_height)
14 self.rect.centerx=ship.rect.centerx
15 self.rect.bottom=ship.rect.bottom
16 
17 self.y=float(self.rect.y)
18 
19 self.color=ai_settings.bullet_color
20 self.speed_factor=ai_settings.bullet_speed_factor
21 
22 def update(self):
23 self.y-=self.speed_factor
24 self.rect.y=self.y
25 
26 def draw_bullet(self):
27 pygame.draw.rect(self.screen,self.color,self.rect)
View Code(bullet)

 

給出游戲設置部分。
我們把游戲中所有涉及數據的部分都放在這個文件中,包括了屏幕,速度,子彈,飛船,外星人,游戲節奏以及游戲關卡更新。

 1 class Settings():
 2 """存儲所有設置的類"""
 3 def __init__(self):
 4 self.high_score=0
 5 
 6 #屏幕設置
 7 self.screen_width=1200
 8 self.screen_height=650
 9 self.bg_color=(230,230,230)
10 #速度設置
11 self.ship_speed_factor_horizen=1
12 self.ship_speed_factor_height=0.5
13 self.ship_limit=3
14 
15 #子彈設置
16 self.bullet_speed_factor=1
17 self.bullet_width=3
18 self.bullet_height=15
19 self.bullet_color=60,60,60
20 self.bullets_allowed=3
21 
22 #外星人設置
23 self.alien_speed_factor=1
24 self.fleet_drop_speed=10
25 #direction為1表示右移,-1表示左移
26 self.fleet_direction=1
27 self.alien_points=50
28 
29 #游戲節奏設置
30 self.speedup_scale=1.1
31 self.score_scale=1.5
32 
33 self.initialize_dynamic_settings()
34 
35 def initialize_dynamic_settings(self):
36 self.ship_speed_factor=1.5
37 self.bullet_speed_factor=3
38 self.alien_speed_factor=1
39 
40 self.fleet_direction=1
41 
42 def increase_speed(self):
43 self.ship_speed_factor*=self.speedup_scale
44 self.bullet_speed_factor*=self.speedup_scale
45 self.alien_speed_factor*=self.speedup_scale
46 
47 self.alien_points=int(self.alien_points*self.score_scale)
View Code(settings)

 

給出游戲狀態部分。
將游戲中的狀態部分都放置在這個文件中。

 1 class GameStats():
 2 def __init__(self,ai_settings):
 3 self.ai_settings=ai_settings
 4 self.reset_stats()
 5 self.game_active=False
 6 
 7 self.high_score=0
 8 
 9 def reset_stats(self):
10 
11 self.ships_left=self.ai_settings.ship_limit
12 self.score=0
13 self.level=1
View Code(state)

 


由於游戲初始通常有一個START按鈕用於開始游戲,所以這里需要定義一個按鈕類。這里需要引入pygame.font用於其中的字體部分。
loading.......

 1 import pygame.font
 2 
 3 class Button():
 4 
 5 def __init__(self,ai_settings,screen,message):
 6 '''初始化按鈕的屬性'''
 7 self.screen=screen
 8 self.screen_rect=screen.get_rect()
 9 
10 self.width,self.height=200,50
11 self.button_color=(0,255,0)
12 self.text_color=(255,255,255)
13 self.font=pygame.font.SysFont(None,48)
14 
15 self.rect=pygame.Rect(0,0,self.width,self.height)
16 self.rect.center=self.screen_rect.center
17 
18 
19 self.prep_message(message)
20 
21 
22 def prep_message(self,message):
23 #圖像渲染
24 self.message_image=self.font.render(message,True,self.text_color,
25 self.button_color)
26 self.message_image_rect=self.message_image.get_rect()
27 self.message_image_rect.center=self.rect.center
28 
29 def draw_button(self):
30 self.screen.fill(self.button_color,self.rect)
31 self.screen.blit(self.message_image,self.message_image_rect)
View Code(button)


給出計分板部分:

 1 import pygame.font
 2 from pygame.sprite import Group
 3 
 4 from ship import Ship
 5 
 6 class Scoreboard():
 7 
 8 
 9 def __init__(self,ai_settings,screen,stats):
10 self.screen=screen
11 self.screen_rect=screen.get_rect()
12 self.ai_settings=ai_settings
13 self.stats=stats
14 
15 self.text_color=(30,30,30)
16 self.font=pygame.font.SysFont(None,48)
17 
18 
19 
20 self.prep_score()
21 self.prep_high_score()
22 self.prep_history_high_score()##########
23 self.prep_level()
24 self.prep_ships()
25 
26 
27 def prep_score(self):
28 '''將得分渲染成圖像'''
29 rounded_score=int(round(self.stats.score,-1))
30 score_str="score:"+"{:,}".format(rounded_score)
31 self.score_image=self.font.render(score_str,True,self.text_color,
32 self.ai_settings.bg_color)
33 
34 
35 #將得分放在右上角
36 self.score_rect=self.score_image.get_rect()
37 self.score_rect.right=self.screen_rect.right-20
38 self.score_rect.top=20#存疑
39 
40 def prep_high_score(self):
41 high_score=int(round(self.stats.high_score,-1))
42 high_score_str="High score:"+"{:,}".format(high_score)
43 self.high_score_image=self.font.render(high_score_str,True,
44 self.text_color,self.ai_settings.bg_color)
45 self.high_score_rect=self.high_score_image.get_rect()
46 self.high_score_rect.centerx=self.screen_rect.centerx-195
47 self.high_score_rect.top=self.score_rect.top
48 
49 def prep_history_high_score(self):###########
50 with open("highscore.txt") as file1:
51 lines=file1.readlines()
52 temp_string=''
53 for line in lines:
54 temp_string+=line.rstrip()
55 history_high_score=eval(temp_string)
56 history_high_score_str="Highest score:"+"{:,}".format(history_high_score)
57 self.history_high_score_image=self.font.render(history_high_score_str,
58 True,self.text_color,self.ai_settings.bg_color)
59 self.history_high_score_rect=self.history_high_score_image.get_rect()
60 self.history_high_score_rect.left=self.high_score_rect.right+45
61 self.history_high_score_rect.top=self.high_score_rect.top
62 
63 def prep_level(self):
64 self.level_image=self.font.render("Level:"+str(self.stats.level),True,
65 self.text_color,self.ai_settings.bg_color)
66 '''將等級放在得分下方'''
67 self.level_rect=self.level_image.get_rect()
68 self.level_rect.right=self.score_rect.right
69 self.level_rect.top=self.score_rect.bottom+10
70 
71 def prep_ships(self):
72 self.ships=Group()
73 for ship_number in range(self.stats.ships_left):
74 ship=Ship(self.ai_settings,self.screen)
75 ship.rect.x=10+ship_number*ship.rect.width
76 ship.rect.y=10
77 self.ships.add(ship)
78 
79 def show_score(self):
80 self.screen.blit(self.score_image,self.score_rect)
81 self.screen.blit(self.high_score_image,self.high_score_rect)
82 self.screen.blit(self.history_high_score_image,
83 self.history_high_score_rect)####
84 self.screen.blit(self.level_image,self.level_rect)
85 self.ships.draw(self.screen)
View Code(scoreboard)

 

給出游戲中用到的各種函數部分:

  1 import sys
  2 import pygame
  3 import random
  4 import time
  5 from bullet import Bullet
  6 from alien import Alien
  7 from time import sleep
  8 
  9 
 10 def check_keydown_events(event,ai_settings,stats,screen,ship,bullets):#stats
 11 if event.key==pygame.K_RIGHT:
 12 #向右移動一格
 13 ship.moving_right=True
 14 elif event.key==pygame.K_LEFT:
 15 ship.moving_left=True
 16 elif event.key==pygame.K_UP:
 17 ship.moving_up=True
 18 elif event.key==pygame.K_DOWN:
 19 ship.moving_down=True
 20 elif event.key==pygame.K_SPACE:
 21 fire_bullets(ai_settings,screen,ship,bullets)
 22 elif event.key==pygame.K_q:#按q鍵退出界面
 23 renew_history_high_score(stats)###########
 24 pygame.quit()
 25 sys.exit()
 26 
 27 def check_keyup_events(event,ship):
 28 if event.key==pygame.K_RIGHT:
 29 ship.moving_right=False
 30 elif event.key==pygame.K_LEFT:
 31 ship.moving_left=False
 32 elif event.key==pygame.K_UP:
 33 ship.moving_up=False
 34 elif event.key==pygame.K_DOWN:
 35 ship.moving_down=False
 36 
 37 
 38 def fire_bullets(ai_settings,screen,ship,bullets):
 39 if len(bullets)<ai_settings.bullets_allowed:
 40 
 41 new_bullet=Bullet(ai_settings,screen,ship)
 42 bullets.add(new_bullet)
 43 
 44 
 45 def check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,
 46 bullets):
 47 
 48 for event in pygame.event.get():
 49 
 50 if event.type==pygame.QUIT:
 51 renew_history_high_score(stats)###########
 52 pygame.quit()
 53 sys.exit()
 54 
 55 elif event.type==pygame.KEYDOWN:
 56 check_keydown_events(event,ai_settings,stats,screen,ship,bullets)
 57 ##########stats
 58 elif event.type==pygame.KEYUP:
 59 check_keyup_events(event,ship)
 60 elif event.type==pygame.MOUSEBUTTONDOWN:
 61 mouse_x,mouse_y=pygame.mouse.get_pos()
 62 check_play_button(ai_settings,screen,stats,sb,play_button,ship,
 63 aliens,bullets,mouse_x,mouse_y)
 64 
 65 
 66 def check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,
 67 bullets,mouse_x,mouse_y):
 68 button_clicked=play_button.rect.collidepoint(mouse_x,mouse_y)
 69 if button_clicked and not stats.game_active:
 70 ai_settings.initialize_dynamic_settings()
 71 #隱藏光標
 72 pygame.mouse.set_visible(False)
 73 #重置統計信息
 74 stats.reset_stats()
 75 stats.game_active=True
 76 #重置記分牌圖像
 77 sb.prep_score()
 78 sb.prep_high_score()
 79 sb.prep_level()
 80 sb.prep_ships()
 81 
 82 #清空外星人和子彈
 83 aliens.empty()
 84 bullets.empty()
 85 
 86 create_fleet(ai_settings,screen,ship,aliens)
 87 ship.center_ship()
 88 
 89 
 90 
 91 
 92 def update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button):
 93 
 94 screen.fill(ai_settings.bg_color)
 95 for bullet in bullets.sprites():
 96 bullet.draw_bullet()
 97 ship.blitme()
 98 #alien.blitme
 99 aliens.draw(screen)
100 sb.show_score()
101 #如果處於非活動狀態,繪制Play按鈕
102 if not stats.game_active:
103 play_button.draw_button()
104 pygame.display.flip()
105 
106 def check_bullet_alien_collisions(ai_settings,screen,stats,sb,
107 ship,aliens,bullets):
108 collisions=pygame.sprite.groupcollide(bullets,aliens,True,True)
109 if collisions:
110 for aliens in collisions.values(): 
111 stats.score+=ai_settings.alien_points*len(aliens)
112 #每個值都是一個列表!!!
113 sb.prep_score()
114 check_high_score(stats,sb)
115 if len(aliens)==0:
116 
117 bullets.empty()
118 ai_settings.increase_speed()
119 stats.level+=1
120 sb.prep_level()
121 create_fleet(ai_settings,screen,ship,aliens)
122 
123 def update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets):
124 bullets.update()
125 
126 for bullet in bullets.copy():
127 if bullet.rect.bottom<=0:
128 bullets.remove(bullet)
129 #碰撞后返回一個字典
130 check_bullet_alien_collisions(ai_settings,screen,stats,sb,
131 ship,aliens,bullets)
132 
133 def get_number_aliens_x(ai_settings,alien_width):
134 available_space_x=ai_settings.screen_width-2*alien_width
135 number_aliens_x=int(available_space_x/(2*alien_width))
136 return number_aliens_x
137 
138 def get_number_rows(ai_settings,ship_height,alien_height):
139 ''''計算屏幕可容納行數'''
140 available_space_y=(ai_settings.screen_height-
141 (3*alien_height)-ship_height)
142 number_rows=int(available_space_y/(2*alien_height))
143 return number_rows
144 
145 
146 def create_alien(ai_settings,screen,aliens,alien_number,row_number):
147 alien=Alien(ai_settings,screen)
148 alien_width=alien.rect.width
149 alien.x=alien_width+2*alien_width*alien_number
150 alien.rect.x=alien.x
151 alien.rect.y=alien.rect.height+2*alien.rect.height*row_number
152 aliens.add(alien)
153 
154 def create_fleet(ai_settings,screen,ship,aliens):
155 '''創建外星人群'''
156 #外星人間距為外星人寬度
157 alien=Alien(ai_settings,screen)
158 number_aliens_x=get_number_aliens_x(ai_settings,alien.rect.width)
159 number_rows=get_number_rows(ai_settings,ship.rect.height,alien.rect.height)
160 total_alien_number=number_aliens_x*number_rows
161 for row_number in range(number_rows):
162 for alien_number in range(number_aliens_x):
163 #創建一個外星人並將其加入當前行
164 create_alien(ai_settings,screen,aliens,alien_number,
165 row_number)
166 
167 
168 
169 
170 def change_fleet_direction(ai_settings,aliens):
171 for alien in aliens.sprites():
172 alien.rect.y+=ai_settings.fleet_drop_speed
173 ai_settings.fleet_direction*=-1########
174 
175 
176 def ship_hit(ai_settings,stats,sb,screen,ship,aliens,bullets):
177 if stats.ships_left>0:
178 
179 stats.ships_left-=1
180 sb.prep_ships()
181 aliens.empty()
182 bullets.empty()
183 
184 create_fleet(ai_settings,screen,ship,aliens)
185 ship.center_ship()
186 
187 sleep(0.5)
188 else:
189 stats.game_active=False
190 pygame.mouse.set_visible(True)
191 
192 def check_aliens_bottom(ai_settings,stats,sb,screen,ship,aliens,bullets):
193 screen_rect=screen.get_rect()
194 for alien in aliens.sprites():
195 if alien.rect.bottom>=screen_rect.bottom:
196 ship_hit(ai_settings,stats,sb,screen,ship,aliens,bullets)
197 break
198 
199 def check_fleet_edges(ai_settings,aliens):
200 for alien in aliens.sprites():
201 if alien.check_edges():
202 #change_fleet_direction(ai_settings,aliens)
203 #break
204 alien.direction*=-1#random.choice([1,-1])
205 alien.rect.y+=ai_settings.fleet_drop_speed
206 
207 #def change_alien_direction()
208 
209 def check_time(ai_settings,aliens):
210 now=time.time()
211 running_time=int(now-start)
212 if running_time==1:
213 for alien in aliens.sprites():
214 alien.direction*=-1#random.choice([1,-1])
215 alien.rect.y+=ai_settings.fleet_drop_speed
216 
217 
218 def update_aliens(ai_settings,stats,sb,screen,ship,aliens,bullets):
219 #check_time(start,ai_settings,aliens)
220 check_fleet_edges(ai_settings,aliens)
221 #check_time(ai_settings,aliens)
222 aliens.update()
223 
224 if pygame.sprite.spritecollideany(ship,aliens):
225 ship_hit(ai_settings,stats,sb,screen,ship,aliens,bullets)
226 check_aliens_bottom(ai_settings,stats,sb,screen,ship,aliens,bullets)
227 
228 def check_high_score(stats,sb):
229 if stats.score>stats.high_score:
230 stats.high_score=stats.score
231 sb.prep_high_score()
232 
233 def renew_history_high_score(stats):##########
234 filename='highscore.txt'
235 with open(filename) as file_object:
236 lines=file_object.readlines()
237 temp_string=''
238 for line in lines:
239 temp_string+=line.rstrip()
240 if stats.high_score>eval(temp_string):
241 with open(filename,'w') as file:
242 file.write(str(stats.high_score))
View Code

 

最后給出程序的主要部分
主要部分中引入了pygame ,time以及Group
創建了 飛船對象,alien對象,子彈對象,游戲設置,游戲狀態,游戲控制按鈕,計分板。

 1 """
 2 待加入項目:
 3 1.引入歷史最高分 ### 已完成
 4 2.加入隨機飛行系統 ### 基本完成/衰
 5 """
 6 
 7 import pygame
 8 import time
 9 from pygame.sprite import Group
10 from game_stats import GameStats
11 
12 from settings import Settings
13 from ship import Ship
14 from alien import Alien
15 from button import Button
16 from scoreboard import Scoreboard
17 import game_functions as gf
18 
19 
20 def run_game():
21 #初始化對象並創建一個屏幕對象
22 pygame.init() #初始化
23 ai_settings=Settings()
24 screen=pygame.display.set_mode((
25 ai_settings.screen_width,ai_settings.screen_height))
26 pygame.display.set_caption("Alien Invasion")
27 #創建一個按鈕
28 play_button=Button(ai_settings,screen,'Play')
29 ship=Ship(ai_settings,screen)#創建一個飛船 
30 
31 #創建一個子彈編組
32 bullets=Group()
33 aliens=Group()
34 bg_color=(230,230,230)
35 alien=Alien(ai_settings,screen)
36 gf.create_fleet(ai_settings,screen,ship,aliens)
37 #創建存儲游戲統計信息的實例,並創建記分牌
38 stats=GameStats(ai_settings)
39 sb=Scoreboard(ai_settings,screen,stats)
40 #start=time.time()
41 while True:
42 
43 #監視鍵盤和鼠標事件
44 gf.check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,
45 bullets)
46 if stats.game_active:
47 ship.update()
48 gf.update_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets)
49 gf.update_aliens(ai_settings,stats,sb,screen,ship,aliens,bullets)
50 gf.update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,
51 play_button)
52 
53 
54 run_game()
55 chenk_events部分檢測了鼠標以及鍵盤按鍵
View Code


免責聲明!

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



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