TZ : 眼睛睜開的那一刻就會(huì)有不同發(fā)生,生活處處有驚喜
在評(píng)論處留下郵箱地址
即可獲得全注釋源碼
一 : 科普一分鐘
上大學(xué)時(shí)候我們利用上機(jī)課,玩了不少小游戲,比如接頭快打之類的,為了換回童年的歡樂和挖掘?qū)?code>python語言的了解和使用,我們用pygame
來制作一款簡單的小游戲
Pygame
是跨平臺(tái)Python
模塊秒际,專為電子游戲設(shè)計(jì)反惕,包含圖像、聲音。 我們來挖掘一下怎么用這個(gè)模塊做一小游戲,游戲的設(shè)計(jì),對(duì)各個(gè)函數(shù)的封裝,游戲從何開始,從何結(jié)束.
二 : pygame 模塊的安裝和配置
我們?cè)贛ac系統(tǒng)上配置pygame
模塊 和其他三方庫 需要用到pip
-python
的包管理管理工具,因?yàn)楝F(xiàn)在我們學(xué)習(xí)的多是python3
所以安裝的是pip3
pip3
的安裝方法:
1.點(diǎn)擊下面鏈接
https://pip.readthedocs.io/en/stable/installing/
2.復(fù)制粘貼另存為鏈接中的文本,可以保存為get-pip.py,等網(wǎng)頁加載完再復(fù)制
3.通過已經(jīng)安裝的python3解釋器解釋執(zhí)行另存為的文件
pip3
安裝完成后我們就要進(jìn)行pygame
模塊的安裝了,我用的編譯器是pycharm
,所以在工具包總搜索,下載就可以導(dǎo)入了.
三 : 游戲程序結(jié)構(gòu)分析
1. 構(gòu)建模塊文件
從運(yùn)行效果不難看出,游戲的主要對(duì)象結(jié)構(gòu)分別有:
(1) .僵尸群 -- alien
模塊
(2).飛機(jī)--ship
模塊
(3).子彈--Bullet
模塊
如果我們給其加上管理設(shè)置的類,用來封裝一些設(shè)置,如游戲背景顏色,子彈最大數(shù)量,子彈移動(dòng)速度,僵尸移動(dòng)速度等等細(xì)節(jié)的封裝類所以我們建立設(shè)置模塊:
(4).設(shè)置 -- settings
模塊
當(dāng)我們對(duì)游戲進(jìn)行操作的時(shí)候,pygame
模塊捕獲我們的動(dòng)作,鍵盤,鼠標(biāo),按下,抬起,屏幕的繪制等等,操作有關(guān)的東西,我們可以單獨(dú)再寫一個(gè)模塊,盡量減少程序的耦合是一個(gè)需要掌握的技能和聰明的做法.
(5)游戲使用函數(shù)--game_functions
模塊
游戲從何開始從何結(jié)束,怎么樣算是失敗,怎么樣算是通關(guān),一共有多少條生命,怎么樣式GAME OVER 所以我們要思考建立一個(gè)模塊來進(jìn)行封裝
(6)狀態(tài)--game_stats
模塊
分析:
程序的編寫,并不是一蹴而就,一氣呵成的.在編寫之前應(yīng)該做好結(jié)構(gòu)分析,更佳合理的解耦.做好草稿工作,但并不是意味著,寫程序的時(shí)候不能再添加或者更改,只是分析結(jié)構(gòu)能夠極大的提高開發(fā)效率,減低風(fēng)險(xiǎn)和成本.
四 : 模塊編寫與構(gòu)建聯(lián)系
分析好結(jié)構(gòu)以后我們就可以進(jìn)行各個(gè)模塊的編寫了.對(duì)于代碼展示只展示了核心代碼.
(1).入口模塊編寫,我們需要寫一個(gè)主程序的入口,之前建立的所有模塊都在入口進(jìn)行調(diào)用,循環(huán),和操作,相當(dāng)于一個(gè)主體,好比是一個(gè) main
函數(shù)
import pygame
from settings import settings
from ship import TZship
import game_functions as gf
from pygame.sprite import Group
from game_stats import GameStats
def TZrungame():
#初始化游戲并且創(chuàng)建一個(gè)屏幕對(duì)象,設(shè)置
pygame.init()
/ *創(chuàng)建設(shè)置實(shí)體*/
ai_setting = settings()
/*設(shè)置游戲顯示*/
screen = pygame.display.set_mode((ai_setting.screen_width,ai_setting.screen_height))
pygame.display.set_caption("飛機(jī)大戰(zhàn)僵尸")
#創(chuàng)建一艘飛船
ship = TZship(ai_setting,screen)
#創(chuàng)建一個(gè)與存儲(chǔ)子彈的編組
bullets = Group()
#創(chuàng)建僵尸群
aliens = Group()
gf.Creat_fleet(ai_setting,screen,ship,aliens)
#創(chuàng)建一個(gè)存儲(chǔ)游戲信息的實(shí)例
stats = GameStats(ai_setting)
# 游戲主循環(huán)
while True:
#響應(yīng)按鍵方法(捕獲操作)
gf.check_event(ai_setting,screen,ship,bullets)
#判斷:如果飛機(jī)還有生命次數(shù)
if stats.game_active:
#飛船位置更新
ship.update()
#子彈組更新位置
bullets.update()
#捕獲子彈和僵尸撞擊事件
gf.update_bullets(ai_setting,screen,ship,aliens,bullets)
#捕獲僵尸的撞擊事件(與飛船和)
gf.update_aliens(ai_setting,stats,screen,ship,aliens,bullets)
#更新屏幕繪制
gf.update_screen(ai_setting,screen,ship,bullets,aliens)
TZrungame()
分析:
入口模塊通過不斷的循環(huán),來判斷捕獲的事件,屏幕的繪制,把各個(gè)模塊聯(lián)系在一起,讓游戲正常的執(zhí)行,當(dāng)然,我們不可能開始就會(huì)完成在主接口方法的構(gòu)建,都是在各個(gè)模塊做一部分,放在入口調(diào)試執(zhí)行,添加或者修改.為了更好的分析入口做了哪些事,也讓我們對(duì)程序主體有一個(gè)明確的了解,進(jìn)而放在第一位說明.
(2).飛船模塊的移動(dòng)
如何來捕獲飛船的移動(dòng)呢,根據(jù)我們自己創(chuàng)建的標(biāo)識(shí)moving_right
與moving_left
進(jìn)行判斷
def update(self):
'''根據(jù)標(biāo)志調(diào)成飛船位置'''
if self.moving_right:
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed
if self.moving_left:
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed
#根據(jù)self.center更新rect對(duì)象
self.rect.centerx = self.center
(3).僵尸的模塊的移動(dòng)方法
如何來讓僵尸動(dòng)起來呢,通過判斷屏幕寬度和僵尸寬度和間距算出 僵尸個(gè)數(shù),同理算出僵尸的行數(shù),也可以進(jìn)行隨機(jī)的排布和隨機(jī)出現(xiàn)僵尸個(gè)數(shù).
通過當(dāng)位置碰到屏幕右側(cè)向左邊移動(dòng),碰到屏幕左邊向右側(cè)移動(dòng)
ai_settings.fleet_direction
是移動(dòng)方向標(biāo)識(shí)
ai_settings.aliens_speed
是移動(dòng)速度標(biāo)識(shí)
統(tǒng)一放在設(shè)置模塊里并引用.
def update(self, *args):
'''移動(dòng)'''
self.x += (self.ai_settings.aliens_speed*self.ai_settings.fleet_direction)
self.rect.x = self.x
(4)子彈模塊的移動(dòng)
隨著射擊,子彈向上移動(dòng),最終擊中目標(biāo),僵尸消失
def update(self, *args):
'''向上移動(dòng)子彈'''
# 更新子彈
self.y -= self.speed
#更新子彈rect位置
self.rect.y = self.y
(5).游戲核心函數(shù)模塊
為了盡量的增加程序的可移植性和封裝性,我們把各個(gè)部分之間的操作和方法放入一個(gè)函數(shù)模塊,我們?cè)诖文K里寫一些核心的業(yè)務(wù)邏輯分析.避免大量代碼暴露在各個(gè)角落,方便管理與更新.
- 更新視圖功能
def update_screen(ai_settings,screen,ship,bullets,aliens):
'''更新屏幕圖像,并切換到新屏幕'''
# 每次循環(huán)時(shí)都重繪屏幕
screen.fill(ai_settings.bg_color)
#在飛船和僵尸后面重繪所有子彈
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
# 讓最近繪制的屏幕可見
pygame.display.flip()
- 子彈的業(yè)務(wù)邏輯
def update_bullets(ai_settings,screen,ship,aliens,bullets):
'''更新子彈位置,并刪除已消失的子彈'''
#更新子彈位置
bullets.update()
#刪除已消失的子彈
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
#判斷子彈與僵尸撞擊
check_bullet_alien_colleisions(ai_settings,screen,ship,aliens,bullets)
- 僵尸的業(yè)務(wù)邏輯
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):
''''檢查是否有僵尸位于邊緣,更新僵尸位置'''
check_fleet_edges(ai_settings,aliens)
'''更新僵尸群中所有僵尸的位置'''
aliens.update()
#檢測(cè)僵尸和飛船之間的碰撞
if pygame.sprite.spritecollideany(ship,aliens):
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
#檢測(cè)僵尸是否到達(dá)屏幕底端
check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets)
五 : 總結(jié)
通過這款小游戲,可以看出所有的功能函數(shù)單獨(dú)都很簡單,放在一起組成了復(fù)雜的業(yè)務(wù)邏輯.
對(duì)于此我們做的就是盡可能簡單化復(fù)雜的業(yè)務(wù)邏輯,分離復(fù)雜的業(yè)務(wù)再進(jìn)行封裝.把各個(gè)實(shí)體對(duì)象通過分離的業(yè)務(wù)邏輯再次進(jìn)行組合.這樣就可以寫出調(diào)理清晰,思路清晰的代碼,假如在配合上高效的算法,那這就是一個(gè)非常棒的程序了.