飛船游戲
這雖然只是個(gè)小游戲,但是代碼也不少,為了避免出錯(cuò)并且讓代碼清楚整潔我們把代碼分為9個(gè)模塊,同時(shí)還有一個(gè)image文件夾儲(chǔ)存圖像還有編輯過程中Python自己生成的一個(gè)文件夾。9個(gè)模塊中,每個(gè)模塊都有自己的功能,來為我們最終的游戲服務(wù)。我們看一下做出來游戲的效果。
1.主函數(shù)模塊alien_invasion
這是主函數(shù)模塊,也是啟動(dòng)游戲的模塊,啟動(dòng)游戲只需要點(diǎn)擊此模塊即可。
代碼:
import pygamefrom pygame
.sprite import Group
from settings import Settings
from ship import Ship
from alien import Alien
from game_stats import GameStats
from button import Button
from scoreboard import Scoreboard
import game_functions as gfdef
run_game():#初始化pygame、設(shè)置和屏幕對(duì)象pygame
.init()ai_settings
= Settings()screen
= pygame
.display
.set_mode((ai_settings
.screen_width
,ai_settings
.screen_height
))pygame
.display
.set_caption("Alien Invasion")#創(chuàng)建Play按鈕play_button
= Button(ai_settings
,screen
,"Play")#創(chuàng)建一艘飛船、一個(gè)子彈的編組和一個(gè)外星人編組ship
= Ship(ai_settings
,screen
)bullets
= Group()aliens
= Group()#創(chuàng)建外星人群gf
.create_fleet(ai_settings
,screen
,ship
,aliens
)#創(chuàng)建一個(gè)用于儲(chǔ)存游戲統(tǒng)計(jì)信息的實(shí)例
,并創(chuàng)建記分牌stats
= GameStats(ai_settings
)sb
= Scoreboard(ai_settings
,screen
,stats
)#開始游戲的主循環(huán)
while True
:gf
.check_events(ai_settings
,screen
,stats
,sb
,play_button
,ship
,aliens
,bullets
)if stats
.game_active
: ship
.update()gf
.update_bullets(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
)gf
.update_aliens(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
)gf
.update_screen(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
,play_button
)run_game()
2.游戲配置的settings模塊
此模塊實(shí)現(xiàn)游戲相關(guān)信息的配置和初始化
代碼:
class
Settings():"""儲(chǔ)存《外星人入侵》的所有設(shè)置的類"""def
__init__(self
):"""初始化游戲的靜態(tài)設(shè)置"""#屏幕設(shè)置self
.screen_width
= 1200self
.screen_height
= 700self
.bg_color
= (230,230,230)#飛船的設(shè)置self
.ship_limit
= 3#子彈設(shè)置self
.bullet_width
= 3self
.bullet_height
= 15self
.bullet_color
= 60,60,60self
.bullets_allowed
= 3#外星人設(shè)置self
.fleet_drop_speed
= 10#以什么樣的速度加快游戲節(jié)奏self
.speedup_scale
= 1.1#外星人點(diǎn)數(shù)的提高self
.score_scale
= 1.5self
.initialize_dynamic_settings()def
initialize_dynamic_settings(self
):"""初始化隨游戲進(jìn)行而變化的設(shè)置"""self
.ship_speed_factor
= 1.5self
.bullet_speed_factor
= 3self
.alien_speed_factor
= 1#fleet_direction為1表示向右;為-1表示向左self
.fleet_direction
= 1#記分self
.alien_points
= 50def
increase_speed(self
):"""提高速度設(shè)置和外星人點(diǎn)數(shù)"""self
.ship_speed_factor
*= self
.speedup_scaleself
.bullet_speed_factor
*= self
.speedup_scaleself
.alien_speed_factor
*= self
.speedup_scaleself
.alien_points
= int(self
.alien_points
* self
.score_scale
)
3.game_stats模塊
用于游戲信息的統(tǒng)計(jì)
代碼:
class
GameStats():"""跟蹤游戲的統(tǒng)計(jì)信息"""def
__init__(self
,ai_settings
):"""初始化統(tǒng)計(jì)信息"""self
.ai_settings
= ai_settingsself
.reset_stats()#讓游戲一開始處于非活動(dòng)狀態(tài)self
.game_active
= False#任何情況都不應(yīng)該清除最高分self
.high_score
= 0def
reset_stats(self
):"""初始化在游戲運(yùn)行期間可能變化的統(tǒng)計(jì)信息"""self
.ships_left
= self
.ai_settings
.ship_limitself
.score
= 0self
.level
= 1
4.用于儲(chǔ)存函數(shù)的game_functions模塊
此模塊用于儲(chǔ)存讓游戲運(yùn)行的函數(shù),可避免主函數(shù)太長(zhǎng),并讓其代碼更易理解。
具體代碼:
import sys
from time import sleepimport pygame
from bullet import Bullet
from alien import Aliendef
check_keydown_events(event
,ai_settings
,screen
,ship
,bullets
):"""響應(yīng)按鍵"""if event
.key
== pygame
.K_RIGHT
:ship
.moving_right
= Trueelif event
.key
== pygame
.K_LEFT
:ship
.moving_left
= Trueelif event
.key
== pygame
.K_SPACE
:fire_bullet(ai_settings
,screen
,ship
,bullets
)elif event
.key
== pygame
.K_q
:sys
.exit()def
fire_bullet(ai_settings
,screen
,ship
,bullets
):"""如果沒有到達(dá)限制,就發(fā)射一顆子彈"""#創(chuàng)建一顆子彈,并將其加入到編組bullets中
if len(bullets
) < ai_settings
.bullets_allowed
: new_bullet
= Bullet(ai_settings
,screen
,ship
)bullets
.add(new_bullet
)def
check_keyup_events(event
,ship
):"""松開響應(yīng)"""if event
.key
== pygame
.K_RIGHT
:ship
.moving_right
= Falseelif event
.key
== pygame
.K_LEFT
:ship
.moving_left
= Falsedef
check_events(ai_settings
,screen
,stats
,sb
,play_button
,ship
,aliens
,bullets
):#監(jiān)視鍵盤和鼠標(biāo)事件
for event in pygame
.event
.get():if event
.type
== pygame
.QUIT
:sys
.exit()elif event
.type
== pygame
.KEYDOWN
:check_keydown_events(event
,ai_settings
,screen
,ship
,bullets
)elif event
.type
== pygame
.KEYUP
:check_keyup_events(event
,ship
)elif event
.type
== pygame
.MOUSEBUTTONDOWN
:mouse_x
,mouse_y
= pygame
.mouse
.get_pos()check_play_button(ai_settings
,screen
,stats
,sb
,play_button
,ship
,aliens
,bullets
,mouse_x
,mouse_y
)def
check_play_button(ai_settings
,screen
,stats
,sb
,play_button
,ship
,aliens
,bullets
,mouse_x
,mouse_y
):"""在玩家單機(jī)Play按鈕時(shí)開始游戲"""button_clicked
= play_button
.rect
.collidepoint(mouse_x
,mouse_y
)if button_clicked and not stats
.game_active
:#重置游戲設(shè)置ai_settings
.initialize_dynamic_settings()#隱藏光標(biāo)pygame
.mouse
.set_visible(False
)#重置游戲統(tǒng)計(jì)信息stats
.reset_stats()stats
.game_active
= True#重置記分牌圖像sb
.prep_score()sb
.prep_high_score()sb
.prep_level()sb
.prep_ships()#清空外星人列表aliens
.empty()bullets
.empty()#創(chuàng)建一群新的外星人,并讓飛船居中
create_fleet(ai_settings
,screen
,ship
,aliens
)ship
.center_ship()def
update_screen(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
,play_button
):"""更新屏幕上的圖像,并切換到新屏幕"""#每次循環(huán)時(shí)都重繪屏幕screen
.fill(ai_settings
.bg_color
)#在飛船和外星人后面重繪所有子彈
for bullet in bullets
.sprites():bullet
.draw_bullet()ship
.blitme()aliens
.draw(screen
)#顯示得分sb
.show_score()#如果游戲處于非活動(dòng)狀態(tài),就繪制Play按鈕
if not stats
.game_active
:play_button
.draw_button()#讓最近繪制的屏幕可見pygame
.display
.flip()def
update_bullets(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
):"""更新子彈的位置,并刪除已消失的子彈"""#更新子彈的位置bullets
.update()#刪除已消失的子彈
for bullet in bullets
.copy():if bullet
.rect
.bottom
<= 0:bullets
.remove(bullet
)check_bullet_alien_collisions(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
)def
check_high_score(stats
,sb
):"""檢查是否需要建立最高分"""if stats
.score
> stats
.high_score
:stats
.high_score
= stats
.scoresb
.prep_high_score()def
check_bullet_alien_collisions(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
):"""響應(yīng)子彈和外星人的碰撞"""#刪除發(fā)生碰撞的子彈和外星人collisions
= pygame
.sprite
.groupcollide(bullets
,aliens
,True
,True
)if collisions
:for aliens in collisions
.values():stats
.score
+= ai_settings
.alien_points
* len(aliens
)sb
.prep_score()check_high_score(stats
,sb
)if len(aliens
) ==0:#刪除現(xiàn)有的子彈
,加快游戲節(jié)奏,并創(chuàng)建一群外星人bullets
.empty()ai_settings
.increase_speed()#加快游戲節(jié)奏stats
.level
+= 1sb
.prep_level()create_fleet(ai_settings
,screen
,ship
,aliens
)def
get_number_aliens_x(ai_settings
,alien_width
):"""計(jì)算一行可容納多少個(gè)外星人"""available_space_x
= ai_settings
.screen_width
- 2 * alien_widthnumber_aliens_x
= int(available_space_x
/ (2 * alien_width
))return number_aliens_xdef
get_number_rows(ai_settings
,ship_height
,alien_height
):"""計(jì)算屏幕可容納多少人"""available_space_y
= (ai_settings
.screen_height
-(3 * alien_height
) - ship_height
)number_rows
= int(available_space_y
/ (2 * alien_height
))return number_rowsdef
create_alien(ai_settings
,screen
,aliens
,alien_number
,row_number
):"""創(chuàng)建一個(gè)外星人并將其放在當(dāng)前行"""alien
= Alien(ai_settings
,screen
)alien_width
= alien
.rect
.widthalien
.x
= alien_width
+ 2 * alien_width
* alien_numberalien
.rect
.x
= alien
.xalien
.rect
.y
= alien
.rect
.height
+ 2 * alien
.rect
.height
* row_numberaliens
.add(alien
)def
create_fleet(ai_settings
,screen
,ship
,aliens
):"""創(chuàng)建一個(gè)外星人群"""#創(chuàng)建一個(gè)外星人,并計(jì)算一行可容納多少個(gè)外星人#外星人間距為外星人寬度alien
= Alien(ai_settings
,screen
)number_aliens_x
= get_number_aliens_x(ai_settings
,alien
.rect
.width
)number_rows
= get_number_rows(ai_settings
,ship
.rect
.height
,alien
.rect
.height
)#創(chuàng)建外星人群
for row_number in
range(number_rows
):for alien_number in
range(number_aliens_x
):create_alien(ai_settings
,screen
,aliens
,alien_number
,row_number
)def
check_fleet_edges(ai_settings
,aliens
):"""有外星人到達(dá)邊緣時(shí)采取相應(yīng)的措施"""for alien in aliens
.sprites():if alien
.check_edges():change_fleet_direction(ai_settings
,aliens
)breakdef
change_fleet_direction(ai_settings
,aliens
):"""將整群外星人下移,并改變它們的方向"""for alien in aliens
.sprites():alien
.rect
.y
+= ai_settings
.fleet_drop_speedai_settings
.fleet_direction
*= -1def
ship_hit(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
):if stats
.ships_left
> 0:"""響應(yīng)被外星人撞到的飛船"""#將ships_left減
1stats
.ships_left
-= 1#更新分?jǐn)?shù)sb
.prep_ships()else:stats
.game_active
= Falsepygame
.mouse
.set_visible(True
)#清空外星人列表和子彈列表aliens
.empty()bullets
.empty()#創(chuàng)建一群新的外星人,并將飛船放到屏幕底端中央
create_fleet(ai_settings
,screen
,ship
,aliens
)ship
.center_ship()#暫停
sleep(0.5)def
check_aliens_bottom(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
):"""檢查是否有外星人到達(dá)了屏幕底端"""screen_rect
= screen
.get_rect()for alien in aliens
.sprites():if alien
.rect
.bottom
>= screen_rect
.bottom
:#像飛船被撞到一樣進(jìn)行處理
ship_hit(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
)breakdef
update_aliens(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
):"""檢查是否有外星人位于屏幕邊緣,并更新整群外星人的位置"""check_fleet_edges(ai_settings
,aliens
)aliens
.update()#檢測(cè)外星人和飛船之間的碰撞
if pygame
.sprite
.spritecollideany(ship
,aliens
):ship_hit(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
)#檢查是否有外星人到達(dá)屏幕底端
check_aliens_bottom(ai_settings
,screen
,stats
,sb
,ship
,aliens
,bullets
)
5.外星人的alien模塊
此模塊用于儲(chǔ)存外星人的屬性和行為
代碼:
import pygame
from pygame
.sprite import Spriteclass
Alien(Sprite
):"""表示單個(gè)外星人"""def
__init__(self
,ai_settings
,screen
):"""初始化外星人并設(shè)置其起始位置"""super(Alien
,self
).__init__()self
.screen
= screenself
.ai_settings
= ai_settings#加載外星人圖像,并設(shè)置其rect屬性self
.image
= pygame
.image
.load('image/alien.bmp')self
.rect
= self
.image
.get_rect()#每個(gè)外星人最初都在屏幕左上角附近self
.rect
.x
= self
.rect
.widthself
.rect
.y
= self
.rect
.height#儲(chǔ)存外星人的準(zhǔn)確位置self
.x
= float(self
.rect
.x
)def
blitme(self
):"""在指定位置繪制外星人"""self
.screen
.blit(self
.image
,self
.rect
)def
check_edges(self
):"""如果外星人位于屏幕邊緣,就返回True"""screen_rect
= self
.screen
.get_rect()if self
.rect
.right
>= screen_rect
.right
:return Trueelif self
.rect
.left
<= 0:return Truedef
update(self
):"""向右或向左移動(dòng)外星人"""self
.x
+= (self
.ai_settings
.alien_speed_factor
*self
.ai_settings
.fleet_direction
)self
.rect
.x
= self
.x
6.ship模塊
此模塊用于儲(chǔ)存飛船的屬性和行為
代碼:
import pygame
from pygame
.sprite import Spriteclass
Ship(Sprite
):def
__init__(self
,ai_settings
,screen
):"""初始化飛船并設(shè)置其初始位置"""super(Ship
,self
).__init__()self
.screen
= screenself
.ai_settings
= ai_settings#加載飛船圖像并獲取其外接矩陣self
.image
= pygame
.image
.load('image/ship.bmp')self
.rect
= self
.image
.get_rect()self
.screen_rect
= screen
.get_rect()#將每艘新飛船放在屏幕底部中央self
.rect
.centerx
= self
.screen_rect
.centerxself
.rect
.bottom
= self
.screen_rect
.bottom#在飛船的屬性center中儲(chǔ)存小數(shù)值self
.center
= float(self
.rect
.centerx
)#移動(dòng)標(biāo)志self
.moving_right
= Falseself
.moving_left
= Falsedef
update(self
):"""根據(jù)移動(dòng)標(biāo)志調(diào)整飛船的位置"""#更新飛船的center值,而不是rect
if self
.moving_right and self
.rect
.right
< self
.screen_rect
.right
:self
.center
+= self
.ai_settings
.ship_speed_factor
if self
.moving_left and self
.rect
.left
> 0:self
.center
-= self
.ai_settings
.ship_speed_factor#根據(jù)self
.center更新rect對(duì)象self
.rect
.centerx
= self
.centerdef
blitme(self
):"""在指定位置繪制飛船"""self
.screen
.blit(self
.image
,self
.rect
)def
center_ship(self
):"""讓飛船在屏幕居中"""self
.center
= self
.screen_rect
.centerx
7.bullet模塊
此模塊用于儲(chǔ)存子彈的屬性和行為
代碼:
import pygame
from pygame
.sprite import Spriteclass
Bullet(Sprite
):"""一個(gè)對(duì)飛船發(fā)射的子彈進(jìn)行管理的類"""def
__init__(self
,ai_settings
,screen
,ship
):"""在飛船所處的位置創(chuàng)建一個(gè)子彈對(duì)象"""super(Bullet
,self
).__init__()self
.screen
= screen#在
(0,0)處創(chuàng)建一個(gè)表示子彈的矩形,再設(shè)置正確的位置self
.rect
= pygame
.Rect(0,0,ai_settings
.bullet_width
,ai_settings
.bullet_height
)self
.rect
.centerx
= ship
.rect
.centerxself
.rect
.top
= ship
.rect
.top#儲(chǔ)存用小數(shù)表示的子彈位置self
.y
= float(self
.rect
.y
)self
.color
= ai_settings
.bullet_colorself
.speed_factor
= ai_settings
.bullet_speed_factordef
update(self
):"""向上移動(dòng)子彈"""#更新表示子彈位置的小數(shù)值self
.y
-= self
.speed_factor#更新表示子彈的rect
.yself
.rect
.y
= self
.ydef
draw_bullet(self
):"""在屏幕上繪制子彈"""pygame
.draw
.rect(self
.screen
,self
.color
,self
.rect
)
8.button模塊
此模塊用于儲(chǔ)存按鈕的屬性和行為
代碼:
import pygame
.fontclass
Button():def
__init__(self
,ai_settings
,screen
,msg
):"""初始化按鈕的屬性"""self
.screen
= screenself
.screen_rect
= screen
.get_rect()#設(shè)置按鈕的尺寸和其他屬性self
.width
,self
.height
= 200,50self
.button_color
= (0,255,0)self
.text_color
= (255,255,255)self
.font
= pygame
.font
.SysFont(None
,48)#創(chuàng)建按鈕的rect對(duì)象
,并使其居中self
.rect
= pygame
.Rect(0,0,self
.width
,self
.height
)self
.rect
.center
= self
.screen_rect
.center#按鈕的標(biāo)簽只需創(chuàng)建一次self
.prep_msg(msg
)def
prep_msg(self
,msg
):"""將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
.centerdef
draw_button(self
):#繪制一個(gè)用顏色填充的按鈕,再繪制文本self
.screen
.fill(self
.button_color
,self
.rect
)self
.screen
.blit(self
.msg_image
,self
.msg_image_rect
)
9.scoreboard模塊
此模塊用于儲(chǔ)存計(jì)分板的屬性和行為
代碼:
import pygame
.font
from pygame
.sprite import Groupfrom ship import Shipclass
Scoreboard():"""顯示得分信息的類"""def
__init__(self
,ai_settings
,screen
,stats
):"""初始化得分信息"""self
.screen
= screenself
.screen_rect
= screen
.get_rect()self
.ai_settings
= ai_settingsself
.stats
= stats#顯示得分信息時(shí)使用的字體設(shè)置self
.text_color
= (30,30,30)self
.font
= pygame
.font
.SysFont(None
,48)#準(zhǔn)備初始得分圖像self
.prep_score()self
.prep_high_score()self
.prep_level()self
.prep_ships()def
prep_score(self
):"""將得分轉(zhuǎn)換為一幅渲染的圖像"""rounded_score
= int(round(self
.stats
.score
,-1))score_str
= "{:,}".format(rounded_score
)self
.score_image
= self
.font
.render(score_str
,True
,self
.text_color
,self
.ai_settings
.bg_color
)#將得分板放在屏幕右上角self
.score_rect
= self
.score_image
.get_rect()self
.score_rect
.right
= self
.screen_rect
.right
- 20self
.score_rect
.top
= 20def
prep_high_score(self
):"""將最高分轉(zhuǎn)化為渲染的圖像"""high_score
= int(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
.ai_settings
.bg_color
)#將最高分放在屏幕頂部中央self
.high_score_rect
= self
.high_score_image
.get_rect()self
.high_score_rect
.centerx
= self
.screen_rect
.centerxself
.high_score_rect
.top
= self
.score_rect
.topdef
prep_level(self
):"""將等級(jí)轉(zhuǎn)換為渲染的圖像"""self
.level_image
= self
.font
.render(str(self
.stats
.level
),True
,self
.text_color
,self
.ai_settings
.bg_color
)#將等級(jí)放在得分下方self
.level_rect
= self
.level_image
.get_rect()self
.level_rect
.right
= self
.score_rect
.rightself
.level_rect
.top
= self
.score_rect
.bottom
+ 10def
prep_ships(self
):"""顯示余下多少艘飛船"""self
.ships
= Group()for ship_number in
range(self
.stats
.ships_left
):ship
= Ship(self
.ai_settings
,self
.screen
)ship
.rect
.x
= 10 + ship_number
* ship
.rect
.widthship
.rect
.y
= 10self
.ships
.add(ship
)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
)
這是我所有的模塊。如果你需要這個(gè)完整文件可以訪問網(wǎng)盤
鏈接:https://pan.baidu.com/s/1BHM52w7-yNWPCFL8aPI-Qw
提取碼:sjpb
(參考資料《Python編程從入門到實(shí)踐》)
總結(jié)
以上是生活随笔為你收集整理的Python实战小项目-飞船游戏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。