Python專案實踐之二:外星人(1)
Python專案實踐之二:外星人
在本文中,我們將在遊戲《外星人入侵》中新增外星人。首先,我們在螢幕上邊緣附近新增一個外星人,然後生成一群外星人。我們讓這群外星人向兩邊和下面移動,並刪除被子彈擊中的外星人。最後,我們將顯示玩家擁有的飛船數量,並在玩家的飛船用完後結束遊戲。
一、回顧專案
開發較大的專案時,進入每個開發階段前回顧一下開發計劃,搞清楚接下來要通過編寫程式碼來完成哪些任務都是不錯的主意。
1、alien_invasion.py
主檔案alien_invasion.py建立一系列整個遊戲都要用到的物件:
1、ai_settings:設定遊戲相關的內容(遊戲介面尺寸、飛船速度、子彈尺寸及速度等等)
2、screen:顯示遊戲相關的內容(遊戲介面、飛船、子彈等)
3、ship:例項化了一個飛船
4、bullets:例項化了一個子彈的編組
5、while迴圈:提供了一個遊戲執行的主迴圈,用於動態更新遊戲狀態
2、settings.py
檔案settings.py包含 Settings 類,這個類只包含方法 init() ,它初始化控制遊戲外觀和飛船速度的屬性。
3、game_functions.py
檔案game_functions.py包含一系列函式:
1、check_keydown_events:監聽鍵盤某個鍵按下時需要提供的操作
2、check_keyup_events:監聽鍵盤某個按下的鍵鬆開後需要提供的操作
3、check_events:監聽全部鍵盤和滑鼠的行為操作
4、update_screen:實時重繪遊戲介面
5、update_bullets:對子彈數量進行控制
6、fire_bullet:根據實際情況,建立併發射子彈
4、ship.py
檔案ship.py包含 Ship 類,這個類包含方法 init() 、管理飛船位置的方法 update() 以及在螢幕上繪製飛船的方法 blitme() 。
5、bullet.py
檔案bullet.py包含 Bullet 類,這個類包含方法 init() 、管理子彈位置的方法 update() 以及在螢幕上繪製飛船的方法 draw_bullet() 。
二、建立第一個外星人
建立一個外星人的方式與建立一個飛船的方式基本是一樣的,我們需要先找到一個外星人的圖片,圖片最好是無背景或者背景顏色與遊戲介面顏色一致的,這樣可以大大提升遊戲的美觀和體驗,把它放入到images資料夾中,如下圖就是一個背景顏色與遊戲介面一致的圖片:
1、建立 Alien 類
alien.py:
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
"""表示單個外星人的類"""
def __init__(self, ai_settings, screen):
super(Alien, self).__init__()
self.screen = screen
self.ai_settings = ai_settings
# 載入外星人影像,並設定其rect屬性
self.image = pygame.image.load('images/alien.png')
self.rect = self.image.get_rect()
# 每個外星人最初都在螢幕左上角附近
self.rect.x = self.rect.width
self.rect.y = self.rect.height
# 儲存外星人的準確位置
self.x = float(self.rect.x)
def blitme(self):
"""在指定位置繪製外星人"""
self.screen.blit(self.image, self.rect)
解釋:Alien類與Ship類基本設定都是一樣的,只是位置設定不同而已,需要注意的是Alien類繼承了Sprite(精靈,不是雪碧哦),和子彈一樣,外星人也是多個不是一個,而Ship 只有一個。
2、建立Alien例項
在alien_invasion.py中例項化Alien:
1、在主迴圈外例項化Alien:
#建立一個外星人
alien = Alien(ai_settings, screen)
2、在主迴圈內顯示外星人:
#每次迴圈重繪螢幕
gf.update_screen(ai_settings, screen, ship, alien, bullets)
3、讓外星人出現在螢幕上
為讓外星人出現在螢幕上,我們在 game_functions.py的update_screen() 中呼叫其方法 blitme() :
def update_screen(ai_settings, screen, ship, alien, bullets):
"""更新螢幕上的影像,並切換到新螢幕"""
# 每次迴圈時都重繪螢幕
screen.fill(ai_settings.bg_color)
# 在飛船和外星人後面重繪所有子彈
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
alien.blitme()
# 讓最近繪製的螢幕可見
pygame.display.flip()
三、建立一群外星人
要繪製一群外星人,需要確定一行能容納多少個外星人以及要繪製多少行外星人。我們將首先計算外星人之間的水平間距,並建立一行外星人,再確定可用的垂直空間,並建立整群外星人。
確定一行可容納多少個外星人:
容納外星人寬度 = 遊戲介面寬度 - 2倍的外星人寬度(兩邊遊戲介面的空出來的寬度)
available_space_x = ai_settings.screen_width – (2 * alien_width)
容納外星人的個數 = 容納外星人的寬度 / 2倍的外星人寬度(一個寬度用於放置外星人,另一個寬度為外星人右邊的空白區域)
number_aliens_x = available_space_x / (2 * alien_width)
建立多行外星人:
為建立一行外星人,首先在alien_invasion.py中建立一個名為 aliens 的空編組(類似於建立子彈的編組),用於儲存全部外星人,再呼叫game_functions.py中建立外星人群的函式:
alien_invasion.py的run_game()函式中,主迴圈while之外新增:
#建立一個外星人編組
aliens = Group()
#建立一個外星人
# alien = Alien(ai_settings, screen) #替換為建立外星人群
# 建立外星人群
gf.create_fleet(ai_settings, screen, aliens)
game_functions.py中用於更新遊戲影像的update_screen()函式:
def update_screen(ai_settings, screen, ship, aliens, bullets):
"""更新螢幕上的影像,並切換到新螢幕"""
# 每次迴圈時都重繪螢幕
screen.fill(ai_settings.bg_color)
# 在飛船和外星人後面重繪所有子彈
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
# 讓最近繪製的螢幕可見
pygame.display.flip()
建立外星人群:
主程式中呼叫了game_functions.py中的建立外星人群的新函式 create_fleet(),但是我們還未定義此,函式,現在來定義此函式:
game_functions.py中新增新函式 create_fleet():
def create_fleet(ai_settings, screen, aliens):
"""建立外星人群"""
# 建立一個外星人,並計算一行可容納多少個外星人
# 外星人間距為外星人寬度
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))
# 建立第一行外星人
for alien_number in range(number_aliens_x):
# 建立一個外星人並將其加入當前行
alien = Alien(ai_settings, screen)
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
aliens.add(alien)
解釋:
1、首先,別忘記把Alien類匯入到game_functions.py中,要不然你再怎麼呼叫alien的屬性都會報錯。
2、計算遊戲介面每一行能放置幾個外星人,由於外星人的圖片素材是外部提供的,Alien類中並沒有它的長寬屬性,所以必須例項化一個外星人,通過rect對其確定大小,然後再計算個數。
3、通過for迴圈將允許建立的外星人的個數新增到外星人組中,當然,這裡要明確外星人組中每個外星人在遊戲介面的定位alien.x = alien_width + 2 * alien_width * alien_number(每個外星人都往右
推一個外星人的寬度)。
重構 create_fleet()
分析create_fleet()函式,我們發現函式內容結構複雜,而且不便於以後的使用,它在內部處理了一系列的問題而得到了很多結論性的結果,但是假設後面我們要使用它內部的結果,就不能直接呼叫了,這樣非常的不方便,因此,我們要對其進行重構,方便於後面的開發。
新增新函式 get_number_aliens_x() :用於計算每行可容納多少個外星人
def get_number_aliens_x(ai_settings, alien_width):
"""計算每行可容納多少個外星人"""
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))
return number_aliens_x
新增新函式 create_alien() :用於建立一個外星人,並設定其位置後放入外星人組
def create_alien(ai_settings, screen, aliens, alien_number):
"""建立一個外星人並將其放在當前行,新增到外星人組中"""
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
aliens.add(alien)
最後:重構 create_fleet()
def create_fleet(ai_settings, screen, aliens):
"""建立外星人群"""
# 建立一個外星人,並計算一行可容納多少個外星人
# 外星人間距為外星人寬度
alien = Alien(ai_settings, screen)
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
# 建立第一行外星人
for alien_number in range(number_aliens_x):
# 建立一個外星人並將其加入當前行
create_alien(ai_settings, screen, aliens, alien_number)
這樣做就舒服了,以後要是別的程式還用到每行可容納多少個外星人,直接來這裡呼叫就可以了
新增行
目前,已經完成了新增一行外星人的目的,但是遊戲設定需要新增多行外星人。接下來,我們就來計算一下,遊戲介面能新增多少行外星人。
容納外星人的高度 = 遊戲介面高度 - 外星人高度(外星人與遊戲介面頂部的區域)- 最初外星人群與飛船的距離(外星人高度的兩倍)- 飛船的高度
available_space_y = ai_settings.screen_height – 3 * alien_height – ship_height
容納外星人的行數 = 容納外星人的高度 / 2倍外星人的高度(每個外星人間距1個外星人高度的距離)
number_rows = available_height_y / (2 * alien_height)
接下來,我們在game_functions.py新增新函式get_number_rows()用於獲取一共可以新增多少行外星人:
def get_number_rows(ai_settings, ship_height, alien_height):
"""計算螢幕可容納多少行外星人"""
available_space_y = (ai_settings.screen_height - (3 * alien_height) - ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
我們修改外星人的y座標,並在第一行外星人上方留出與外星人等高的空白區域。相鄰外星人行的y座標相差外星人高度的兩倍,因此我們將外星人高度乘以2,再乘以行號。第一行的行號為0,因此第一行的垂直位置不變,而其他行都沿螢幕依次向下放置。
修改game_functions.py中的create_alien(),將建立:
def create_alien(ai_settings, screen, aliens, row_number, alien_number):
"""建立一個外星人並將其放在當前行,新增到外星人組中"""
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
aliens.add(alien)
好了,現在再把game_functions.py中的create_fleet()進行修改,把外星人群新增到遊戲介面中去:
def create_fleet(ai_settings, screen, ship, aliens):
"""建立外星人群"""
# 建立一個外星人,並計算一行可容納多少個外星人
# 外星人間距為外星人寬度
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)
# 建立一組外星人
for row_number in range(number_rows):
for alien_number in range(number_aliens_x):
create_alien(ai_settings, screen, aliens, row_number, alien_number)
解釋:
1、number_aliens_x:每行最多可以放多少個外星人
2、number_rows:遊戲介面一共可以放多少行外星人
3、通過雙層for迴圈實現外星人群體佈局
最後,修改alien_invasion.py主程式中“# 建立外星人群”的程式碼(需要新增一個ship引數,因為計算行數的時候用到了飛船的高度):
gf.create_fleet(ai_settings, screen, ship, aliens)
四、移動外星人群
需求:外星人撞到螢幕邊緣後下移一定的距離,再沿相反的方向移動。
1、向右移動外星人
首先,在settings.py中的__init__方法中新增一個控制外星人速度的設定,繫結到物件本身:
# 外星人設定
self.alien_speed_factor = 1
然後,使用這個設定來建立 alien.py 中的 update()方法,表示向右移動外星人 :
def update(self):
"""向右移動外星人"""
self.x += self.ai_settings.alien_speed_factor
self.rect.x = self.x
接下來,在game_functions.py末尾新增新函式 update_aliens(),表示更新外星人的位置 :
def update_aliens(aliens):
"""更新外星人群中所有外星人的位置"""
aliens.update()
最後,在主程式的主迴圈中新增game_functions.py的呼叫即可:
#呼叫外星人群移動顯示的函式
gf.update_aliens(aliens)
2、建立表示外星人移動方向的設定
目前,已經實現外星人群整體向右移動,直至全部移出遊戲介面,接下來,我們需要實現外星人群移動到遊戲介面邊界後向下移動,然後再反向移動的功能。
在settings.py中的外星人設定新增向下移動的速度屬性和移動方向的判斷標準:
# 外星人設定
self.alien_speed_factor = 1
self.fleet_drop_speed = 10 #表示向下移動的速度
# fleet_direction為1表示向右移,為-1表示向左移
self.fleet_direction = 1
3、檢查外星人是否撞到了螢幕邊緣
現在需要編寫一個方法來檢查是否有外星人撞到了螢幕邊緣,還需修改 alien.py 中的 update() ,以讓每個外星人都沿正確的方向移動。
首先,在alien.py中新增一個判斷外星人是否撞到了螢幕邊緣的函式check_edges():
def check_edges(self):
"""如果外星人位於螢幕邊緣,就返回True"""
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <= 0:
return True
其次,修改修改 alien.py 中的 update() :
def update(self):
"""向左或向右移動外星人"""
self.x += (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction)
self.rect.x = self.x
解釋:self.x(當前外星人的位置) = self.x + self.ai_settings.alien_speed_factor(移動速度)* self.ai_settings.fleet_directio(移動方向)
4、向下移動外星人群並改變移動方向
有外星人到達螢幕邊緣時,需要將整群外星人下移,並改變它們的移動方向。下面我們就對game_functions.py做修改,因為我們要在這裡檢查是否有外星人到達了左邊緣或右邊緣,game_functions.py是為遊戲提供邏輯處理的函式庫。
首先,要對外星人碰撞到螢幕邊界實現轉向向下的功能,所以在game_functions.py中新增一個change_fleet_direction函式:
def change_fleet_direction(ai_settings, aliens):
"""將整群外星人下移,並改變它們的方向"""
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1
其次,要對外星人碰撞到螢幕邊緣採取相應措施,因此,在game_functions.py中新增一個check_fleet_edges()函式:
def check_fleet_edges(ai_settings, aliens):
"""有外星人到達邊緣時採取相應的措施"""
for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
break
最後,就是要修改game_functions.py中用於更新外星人群位置的update_aliens()函式,使外星人群能正確的顯示自己在螢幕的位置:
def update_aliens(ai_settings, aliens):
"""檢查是否有外星人位於螢幕邊緣,並更新整群外星人的位置"""
check_fleet_edges(ai_settings, aliens)
aliens.update()
我們修改了函式 update_aliens() ,在其中通過呼叫 check_fleet_edges() 來確定是否有外星人位於螢幕邊緣。現在,函式 update_aliens() 包含形參 ai_settings ,因此我們在主程式alien_invasion.py呼叫它時也要指定與ai_settings 對應的實參:
#呼叫外星人群的函式
# gf.update_aliens(aliens)
gf.update_aliens(ai_settings, aliens)
如果你現在執行這個遊戲,外星人群將在螢幕上來回移動,並在抵達螢幕邊緣後向下移動。現在可以開始射殺外星人,檢查是否有外星人撞到飛船,或抵達了螢幕底端。
這是一篇讀書筆記,如有不妥之處,請各位指正!!!
相關文章
- 學習筆記專案實踐(python)筆記Python
- Python爬蟲開發與專案實踐(3)Python爬蟲
- mobx專案實踐
- vue實踐06-專案實踐Vue
- Python專案實戰(一)《Python程式設計 從入門到實踐》Python程式設計
- Yocto實踐(1): 基於Dunfell 構建Yocto專案
- 一本實踐的專案開發《Python專案開發實戰(第2版)》Python
- 微服務專案實踐之中建專案微服務
- maven 專案轉化成 gradle 專案實踐MavenGradle
- python互動式專案例項 外星人入侵Python
- 專案去O實踐
- Python爬蟲開發與專案實戰(1)Python爬蟲
- Python專案1“外星人入侵”遊戲(完整)及pyinstaller打包過程(含幾種報錯解決辦法)Python遊戲
- Python專案實踐有什麼好處?python用來做什麼Python
- python實戰專案Python
- kubernetes實踐之二十六:GlusterFS
- kubernetes實踐之二十七:Harbor
- kubernetes實踐之二十:網路原理
- kubernetes實踐之二十二:Pod
- kubernetes實踐之二十三:ReplicationControllerController
- kubernetes實踐之二十四:Service
- vue專案實踐思考003Vue
- React專案實踐系列二React
- React專案實踐系列一React
- go專案dockerfile最佳實踐GoDocker
- 實踐JavaWeb課程專案JavaWeb
- 敏捷思維-專案實踐敏捷
- 【Python學習實踐教程】10個Python經典專案實戰,練手必備Python
- Nodejs教程27:Node.js專案之二:實現路由NodeJSNode.js路由
- vue專案實踐004~~~一籃子的實踐技巧Vue
- Docker進階與實踐之二:NamespaceDockernamespace
- Flutter專案實戰(1):通用專案框架搭建Flutter框架
- 專案管理培訓實踐心得專案管理
- Dva+Antd-mobile專案實踐
- Android元件化實踐專案分享Android元件化
- CICD以及高可用專案實踐
- Vue專案骨架屏注入實踐Vue
- Golang專案的測試實踐Golang