接着上節的繼續學習,在本章中,我們將結束游戲《外星人入侵》的開發。我們將添加一個Play按鈕,用於根據需要啟動游戲以及在游戲結束后重啟游戲。我們還將修改這個游戲,使其在玩家的等級提高時加快節奏,並實現一個記分系統。
一 添加Play按鈕
由於Pygame沒有內置創建按鈕的方法,我們創建一個Button類,用於創建帶標簽的實心矩形。你可以在游戲中使用這些代碼來創建任何按鈕。下面是Button類的第一部分,請將這個類保存為button.py代碼如下:
import pygame.font
class Button() :
def __init__(self,ai_settings,screen,msg):
#初始化按鈕的屬性
self.screen=screen
self.screen_rect=screen.get_rect()
#設置按鈕的尺寸和其他屬性
self.width,self.height=200,50
self.button_color=(0,255,0)
self.text_color = (255,255,255)
self.font = pygame.font.SysFont(None,48)
#創建按鈕的rect對象,並使其居中
self.rect = pygame.Rect(0,0,self.width,self.height)
self.rect.center = self.screen_rect.center
#按鈕的標簽只需要創建一次
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.center
def draw_button(self):
#繪制一個用顏色填充的按鈕,再繪制文本
self.screen.fill(self.button_color,self.rect)
self.screen.blit(self.msg_image,self.msg_image_rect)
代碼中已經注釋的很清楚了,不再做過多的介紹,這里重點說一下幾個點:
(1)導入了模塊pygame.font,它讓Pygame能夠將文本渲染到屏幕上。
(2)pygame.font.SysFont(None,48)指定使用什么字體來渲染文本。實參None讓Pygame使用默認字體,而48指定了文本的字號。
(3)方法prep_msg()接受實參self以及要渲染為圖像的文本(msg)。調用font.render()將存儲在msg中的文本轉換為圖像,然后將該圖像存儲在msg_image中。
(4)方法font.render()還接受一個布爾實參,該實參指定開啟還是關閉反鋸齒功能(反鋸齒讓文本的邊緣更平滑)
(5)screen.fill()來繪制表示按鈕的矩形,再調用screen.blit(),並向它傳遞一幅圖像以及與該圖像相關聯的rect對象,從而在屏幕上繪制文本圖像。
二 在屏幕繪制按鈕
在alien_invasion.py中添加標亮的代碼:
import pygame from pygame.sprite import Group from settings import Settings from game_stats import GameStats from ship import Ship import game_functions as gf from button import Button def run_game(): # Initialize pygame, settings, and screen object. pygame.init() ai_settings = Settings() screen = pygame.display.set_mode( (ai_settings.screen_width, ai_settings.screen_height)) pygame.display.set_caption("Alien Invasion") #創建play按鈕 play_button = Button(ai_settings,screen,"Play") # Create an instance to store game statistics. stats = GameStats(ai_settings) # Set the background color. bg_color = (230, 230, 230) # Make a ship, a group of bullets, and a group of aliens. ship = Ship(ai_settings, screen) bullets = Group() aliens = Group() # Create the fleet of aliens. gf.create_fleet(ai_settings, screen, ship, aliens) # Start the main loop for the game. while True: gf.check_events(ai_settings, screen, ship, bullets) if stats.game_active: ship.update() gf.update_bullets(ai_settings, screen, ship, aliens, bullets) gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets) gf.update_screen(ai_settings, screen, stats, ship, aliens, bullets,play_button) run_game()
修改update_screen(),以便在游戲處於非活動狀態時顯示Play按鈕:
def update_screen(ai_settings, screen,stats, ship, aliens, bullets,play_button):
"""Update images on the screen, and flip to the new screen."""
# Redraw the screen, each pass through the loop.
screen.fill(ai_settings.bg_color)
# Redraw all bullets, behind ship and aliens.
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
if not stats.game_active :
play_button.draw_button()
# Make the most recently drawn screen visible.
pygame.display.flip()
運行效果如下:

三 開始游戲
為在玩家單擊Play按鈕時開始新游戲,需在game_functions.py中添加如下代碼,以監視與這個按鈕相關的鼠標事件:
def check_events(ai_settings, screen, stats,play_button,ship, bullets):
"""Respond to keypresses and mouse events."""
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(stats,play_button,mouse_x,mouse_y)
def check_play_button(stats,play_button,mouse_x,mouse_y) :
#在玩家點擊play按鈕時開始游戲
if play_button.rect.collidepoint(mouse_x,mouse_y) :
stats.game_active = True
注意一下幾點:
(1)無論玩家單擊屏幕的什么地方,Pygame都將檢測到一個MOUSEBUTTONDOWN事件,但我們只關心這個游戲在玩家用鼠標單擊Play按鈕時作出響應。
(2)使用了pygame.mouse.get_pos(),它返回一個元組,其中包含玩家單擊時鼠標的x和y坐標。
(3)使用collidepoint()檢查鼠標單擊位置是否在Play按鈕的rect內,如果是這樣的,我們就將game_active設置為True,讓游戲就此開始!
四 重置游戲,將按鈕切換到非活動狀態以及隱藏光標
前面編寫的代碼只處理了玩家第一次單擊Play按鈕的情況,而沒有處理游戲結束的情況,因為沒有重置導致游戲結束的條件。為在玩家每次單擊Play按鈕時都重置游戲,需要重置統計信息、刪除現有的外星人和子彈、創建一群新的外星人,並讓飛船居中。
def check_events(ai_settings, screen, stats,play_button,ship,aliens, bullets):
"""Respond to keypresses and mouse events."""
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,play_button,ship,aliens,bullets,mouse_x,mouse_y)
def check_play_button(ai_settings,screen,stats,play_button,ship,aliens,bullets,mouse_x,mouse_y) :
#在玩家點擊play按鈕時開始游戲
button_clicked=play_button.rect.collidepoint(mouse_x,mouse_y)
if button_clicked and not stats.game_active :
#隱藏光標
pygame.mouse.set_visible(False)
#重置游戲信息
stats.reset_stats()
stats.game_active = True
#清空外星人列表和子彈列表
aliens.empty()
bullets.empty()
#創建一群新的外星人,並讓飛船居中
create_fleet(ai_settings,screen,ship,aliens)
ship.center_ship()
注意一下幾點:
(1),Play按鈕存在一個問題,那就是即便Play按鈕不可見,玩家單擊其原來所在的區域時,游戲依然會作出響應。游戲開始后,如果玩家不小心單擊了Play按鈕原來所處的區域,游戲將重新開始!為修復這個問題,可讓游戲僅在game_active為False時才開始!
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y) if button_clicked and not stats.game_active:
(2)為讓玩家能夠開始游戲,我們要讓光標可見,但游戲開始后,光標只會添亂。在游戲處於活動狀態時讓光標不可見,游戲結束后,我們將重新顯示光標,讓玩家能夠單擊Play按鈕來開始新游戲。
def check_play_button(ai_settings, screen, stats, play_button, ship, aliens,bullets, mouse_x, mouse_y):
"""在玩家單擊Play按鈕時開始新游戲"""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
# 隱藏光標
pygame.mouse.set_visible(False)
還有好多要寫,但實在寫不下去了,明天再寫吧!休息休息!
