目錄
13.4.4 向下移動外星人群并改變移動方向
game_functions.py
alien_invasion.py
13.5 射殺外星人
13.5.1 檢測子彈與外星人的碰撞
game_functions.py
alien_invasion.py
13.5.2 為測試創(chuàng)建大子彈
13.5.3 生成新的外星人群
game_functions.py
alien_invasion.py
13.5.4 提高子彈的速度
settings.py
13.5.5 重構(gòu) update_bullets()
game_functions.py
13.6 結(jié)束游戲
13.6.1 檢測外星人和飛船碰撞
game_functions.py
alien_invasion.py
往期快速傳送門??(在文章最后):
感謝大家的支持!歡迎訂閱收藏!專欄將持續(xù)更新!
13.4.4 向下移動外星人群并改變移動方向
有外星人到達(dá)屏幕邊緣時,需要將整群外星人下移,并改變它們的移動方向。我們需要對 game_functions.py做重大修改,因為我們要在這里檢查是否有外星人到達(dá)了左邊緣或右邊緣。為此, 我們編寫函數(shù)check_fleet_edges()和change_fleet_direction(),并對update_aliens()進(jìn)行修改:
game_functions.py
def check_fleet_edges(ai_settings, aliens):
"""有外星人到達(dá)邊緣時采取相應(yīng)的措施"""
1 for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
break
def change_fleet_direction(ai_settings, aliens):
"""將整群外星人下移,并改變它們的方向"""
for alien in aliens.sprites():
2 alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1
def update_aliens(ai_settings, aliens):
"""
檢查是否有外星人位于屏幕邊緣,并更新整群外星人的位置
"""
3 check_fleet_edges(ai_settings, aliens)
aliens.update()
在check_fleet_edges()中,我們遍歷外星人群,并對其中的每個外星人調(diào)用check_edges() (見1)。如果check_edges()返回True,我們就知道相應(yīng)的外星人位于屏幕邊緣,需要改變外星人 群的方向,因此我們調(diào)用change_fleet_direction()并退出循環(huán)。在change_fleet_direction()中, 我們遍歷所有外星人,將每個外星人下移fleet_drop_speed設(shè)置的值(見2);然后,將fleet_ direction的值修改為其當(dāng)前值與?1的乘積。
我們修改了函數(shù)update_aliens(),在其中通過調(diào)用check_fleet_edges()來確定是否有外星人 位于屏幕邊緣?,F(xiàn)在,函數(shù)update_aliens()包含形參ai_settings,因此我們調(diào)用它時指定了與 ai_settings對應(yīng)的實參:
alien_invasion.py
# 開始游戲主循環(huán)
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)
如果你現(xiàn)在運行這個游戲,外星人群將在屏幕上來回移動,并在抵達(dá)屏幕邊緣后向下移動。 現(xiàn)在可以開始射殺外星人,檢查是否有外星人撞到飛船,或抵達(dá)了屏幕底端。
13.5 射殺外星人
我們創(chuàng)建了飛船和外星人群,但子彈擊中外星人時,將穿過外星人,因為我們還沒有檢查碰 撞。在游戲編程中,碰撞指的是游戲元素重疊在一起。要讓子彈能夠擊落外星人,我們將使用 sprite.groupcollide()檢測兩個編組的成員之間的碰撞。
13.5.1 檢測子彈與外星人的碰撞
子彈擊中外星人時,我們要馬上知道,以便碰撞發(fā)生后讓外星人立即消失。為此,我們將在 更新子彈的位置后立即檢測碰撞。 方法sprite.groupcollide()將每顆子彈的rect同每個外星人的rect進(jìn)行比較,并返回一個字 典,其中包含發(fā)生了碰撞的子彈和外星人。在這個字典中,每個鍵都是一顆子彈,而相應(yīng)的值都 是被擊中的外星人(第14章實現(xiàn)記分系統(tǒng)時,也會用到這個字典)。 在函數(shù)update_bullets()中,使用下面的代碼來檢查碰撞:
game_functions.py
def update_bullets(aliens, bullets):
"""更新子彈的位置,并刪除已消失的子彈"""
--snip--
# 檢查是否有子彈擊中了外星人
# 如果是這樣,就刪除相應(yīng)的子彈和外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
新增的這行代碼遍歷編組bullets中的每顆子彈,再遍歷編組aliens中的每個外星人。每當(dāng) 有子彈和外星人的rect重疊時,groupcollide()就在它返回的字典中添加一個鍵?值對。兩個實參True告訴Pygame刪除發(fā)生碰撞的子彈和外星人。(要模擬能夠穿行到屏幕頂端的高能子彈——消 滅它擊中的每個外星人,可將第一個布爾實參設(shè)置為False,并讓第二個布爾實參為True。這樣 被擊中的外星人將消失,但所有的子彈都始終有效,直到抵達(dá)屏幕頂端后消失。) 我們調(diào)用update_bullets()時,傳遞了實參aliens:
alien_invasion.py
# 開始游戲主循環(huán)
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(aliens, bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)
如果你此時運行這個游戲,被擊中的外星人將消失。如圖13-5所示,其中有一部分外星人被 擊落。
13.5.2 為測試創(chuàng)建大子彈
只需通過運行這個游戲就可以測試其很多功能,但有些功能在正常情況下測試起來比較煩 瑣。例如,要測試代碼能否正確地處理外星人編組為空的情形,需要花很長時間將屏幕上的外星 人都擊落。測試有些功能時,可以修改游戲的某些設(shè)置,以便專注于游戲的特定方面。例如,可以縮小屏 幕以減少需要擊落的外星人數(shù)量,也可以提高子彈的速度,以便能夠在單位時間內(nèi)發(fā)射大量子彈。
測試這個游戲時,我喜歡做的一項修改是增大子彈的尺寸,使其在擊中外星人后依然有效, 如圖13-6所示。請嘗試將bullet_width設(shè)置為300,看看將所有外星人都射殺有多快! 類似這樣的修改可提高測試效率,還可能激發(fā)出如何賦予玩家更大威力的思想火花。(完成 測試后,別忘了將設(shè)置恢復(fù)正常。)
13.5.3 生成新的外星人群
這個游戲的一個重要特點是外星人無窮無盡,一個外星人群被消滅后,又會出現(xiàn)一群外星人。 要在外星人群被消滅后又顯示一群外星人,首先需要檢查編組aliens是否為空。如果為空, 就調(diào)用create_fleet()。我們將在update_bullets()中執(zhí)行這種檢查,因為外星人都是在這里被 消滅的:
game_functions.py
def update_bullets(ai_settings, screen, ship, aliens, bullets):
--snip--
# 檢查是否有子彈擊中了外星人
# 如果是,就刪除相應(yīng)的子彈和外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
1 if len(aliens) == 0:
# 刪除現(xiàn)有的子彈并新建一群外星人
2 bullets.empty()
create_fleet(ai_settings, screen, ship, aliens)
在1處,我們檢查編組aliens是否為空。如果是,就使用方法empty()刪除編組中余下的所 有精靈,從而刪除現(xiàn)有的所有子彈。我們還調(diào)用了create_fleet(),再次在屏幕上顯示一群外 星人。 現(xiàn)在,update_bullets()的定義包含額外的形參ai_settings、screen和ship,因此我們需要 更新alien_invasion.py中對update_bullets()的調(diào)用:
alien_invasion.py
# 開始游戲主循環(huán)
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)
現(xiàn)在,當(dāng)前外星人群消滅干凈后,將立刻出現(xiàn)一個新的外星人群.
13.5.4 提高子彈的速度
如果你現(xiàn)在嘗試在這個游戲中射殺外星人,可能發(fā)現(xiàn)子彈的速度比以前慢,這是因為在每次 循環(huán)中, Pygame 需要做的工作更多了。為提高子彈的速度,可調(diào)整 settings.py 中 bullet_speed_factor的值。例如,如果將這個值增大到3,子彈在屏幕上向上穿行的速度將變得 相當(dāng)快:
settings.py
# 子彈設(shè)置
self.bullet_speed_factor = 3
self.bullet_width = 3
--snip--
這項設(shè)置的最佳值取決于你的系統(tǒng)速度,請找出適合你的值吧。
13.5.5 重構(gòu) update_bullets()
下面來重構(gòu)update_bullets(),使其不再完成那么多任務(wù)。我們將把處理子彈和外星人碰撞 的代碼移到一個獨立的函數(shù)中:
game_functions.py
def update_bullets(ai_settings, screen, ship, aliens, bullets):
--snip
# 刪除已消失的子彈
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets)
def check_bullet_alien_collisions(ai_settings, screen, ship, aliens, bullets):
"""響應(yīng)子彈和外星人的碰撞"""
# 刪除發(fā)生碰撞的子彈和外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if len(aliens) == 0:
# 刪除現(xiàn)有的所有子彈,并創(chuàng)建一個新的外星人群
bullets.empty()
create_fleet(ai_settings, screen, ship, aliens)
我們創(chuàng)建了一個新函數(shù)——check_bullet_alien_collisions(),以檢測子彈和外星人之間的 碰撞,以及在整群外星人都被消滅干凈時采取相應(yīng)的措施。這避免了update_bullets()太長,簡 化了后續(xù)的開發(fā)工作。
13.6 結(jié)束游戲
如果玩家根本不會輸,游戲還有什么趣味和挑戰(zhàn)性可言?如果玩家沒能在足夠短的時間內(nèi)將 整群外星人都消滅干凈,且有外星人撞到了飛船,飛船將被摧毀。與此同時,我們還限制了可供 玩家使用的飛船數(shù),而有外星人抵達(dá)屏幕底端時,飛船也將被摧毀。玩家用光了飛船后,游戲便 結(jié)束。
13.6.1 檢測外星人和飛船碰撞
我們首先檢查外星人和飛船之間的碰撞,以便外星人撞上飛船時我們能夠作出合適的響應(yīng)。 我們在更新每個外星人的位置后立即檢測外星人和飛船之間的碰撞。
game_functions.py
def update_aliens(ai_settings, ship, aliens):
"""
檢查是否有外星人到達(dá)屏幕邊緣
然后更新所有外星人的位置
"""
check_fleet_edges(ai_settings, aliens)
aliens.update()
# 檢測外星人和飛船之間的碰撞
1 if pygame.sprite.spritecollideany(ship, aliens):
2 print("Ship hit!!!")
方法spritecollideany()接受兩個實參:一個精靈和一個編組。它檢查編組是否有成員與精 靈發(fā)生了碰撞,并在找到與精靈發(fā)生了碰撞的成員后就停止遍歷編組。在這里,它遍歷編組 aliens,并返回它找到的第一個與飛船發(fā)生了碰撞的外星人。 如果沒有發(fā)生碰撞,spritecollideany()將返回None,因此?處的if代碼塊不會執(zhí)行。如果 找到了與飛船發(fā)生碰撞的外星人,它就返回這個外星人,因此if代碼塊將執(zhí)行:打印“Ship hit!!!” (見?)。(有外星人撞到飛船時,需要執(zhí)行的任務(wù)很多:需要刪除余下的所有外星人和子彈,讓 飛船重新居中,以及創(chuàng)建一群新的外星人。編寫完成這些任務(wù)的代碼前,需要確定檢測外星人和 飛船碰撞的方法是否可行。而為確定這一點,最簡單的方式是編寫一條print語句。) 現(xiàn)在,我們需要將ship傳遞給update_aliens():
alien_invasion.py
# 開始游戲主循環(huán)
while True:
gf.check_events(ai_settings, screen, ship, bullets)
ship.update()
gf.update_bullets(ai_settings, screen, ship, aliens, bullets)
gf.update_aliens(ai_settings, ship, aliens)
gf.update_screen(ai_settings, screen, ship, aliens, bullets)
現(xiàn)在如果你運行這個游戲,則每當(dāng)有外星人撞到飛船時,終端窗口都將顯示“Ship hit!!!”。 測試這項功能時,請將alien_drop_speed設(shè)置為較大的值,如50或100,這樣外星人將更快地撞到 飛船。文章來源:http://www.zghlxwxcb.cn/news/detail-772978.html
關(guān)于“Python”的核心知識點整理大全25-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-772978.html
往期快速傳送門??(在文章最后):
感謝大家的支持!歡迎訂閱收藏!專欄將持續(xù)更新!
到了這里,關(guān)于關(guān)于“Python”的核心知識點整理大全36的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!