外星人大戰----------------------遊戲開發(四)
前面已經實現外星人的移動,現在開始完成射殺外星人。我們將要使用sprite.groupcollide()檢測兩個編組的碰撞。我們要在碰撞的時候立馬就讓外星人消失,所以在更新位置的時候就檢測有無碰撞。
在功能模組檢測子彈與外星人,方法sprite.groupcollide()將每顆子彈的rect同外星人的rect比較,返回一個字典,其中包含發生碰撞的子彈與外星人,在這個字典裡每個鍵都是一顆子彈,而相應的值都是被擊中的外星人。這樣兩者就相互對應起來了。
#-*-coding:GBK-*- #-*-coding:utf-8-*- #遊戲的功能模組,包括響應鍵盤滑鼠事件,移動飛船等 import sys import pygame from bullet import Bullet from alien import Alien def check_keydown_events(event,ai_settings,screen,ship,bullets): #響應按鍵 if event.key==pygame.K_RIGHT: ship.moving_right=True #改變標誌位 elif event.key==pygame.K_LEFT: ship.moving_left=True elif event.key==pygame.K_SPACE: #響應按空格鍵 fire_bullet(ai_settings,screen,ship,bullets) def fire_bullet(ai_settings,screen,ship,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): #響應按鍵鬆開 if event.key==pygame.K_RIGHT: ship.moving_right=False elif event.key==pygame.K_LEFT: ship.moving_left=False def check_events(ai_settings,screen,ship,bullets): #響應鍵盤和滑鼠事件 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) 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() def update_bullets(aliens,bullets): #更新子彈的位置,並刪除已消失的子彈 bullets.update() for bullet in bullets.copy(): if bullet.rect.bottom<=0: bullets.remove(bullet) #檢查是否兩者碰撞,是的話,刪除相應的子彈與外星人 collisions=pygame.sprite.groupcollide(bullets,aliens,True,True) #建立外星人群 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 def creat_alien(ai_settings,screen,aliens,alien_number,row_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) #計算螢幕可以放入多少行 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 def creat_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): creat_alien(ai_settings,screen,aliens,alien_number,row_number) #更新外星人的位置 def update_aliens(ai_settings,aliens): check_fleet_edges(ai_settings,aliens) aliens.update() #對於外星人到達邊緣採取的措施: def check_fleet_edges(ai_settings,aliens): 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(): alien.rect.y+=ai_settings.fleet_drop_speed ai_settings.fleet_direction*=-1
在函式update_bullets()新增一行程式碼,這行程式碼遍歷編組裡bullets的所有子彈,再遍歷aliens的每個外星人,當有兩者重疊的時候,groupcollide()就在它返回的字典中新增鍵-值。兩個實參true告知pygame刪除發生碰撞的子彈與外星人。(第一個實參true是代表的是刪除子彈,第二個實參true是外星人。我們也可以設定子彈不刪除,外星人刪除,只要子彈與外星人碰撞,就會外星人消失,子彈可以一直移動到頂端,就把第一個布林實參設為False,第二個布林實參設為true)
主程式:
#-*-coding:GBK-*- #-*-coding:utf-8-*- import pygame from setting import Setting from ship import Ship import game_functions as gf from pygame.sprite import Group def run_game(): pygame.init() #初始化,建立螢幕物件 ai_settings=Setting() #建立一個800*800的螢幕 screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height)) pygame.display.set_caption("Alien Invasion") #對於這個視窗的命名為Alien Invasion ship=Ship(ai_settings,screen) #建立飛船 bullets=Group() aliens=Group() gf.creat_fleet(ai_settings,screen,ship,aliens) 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) run_game()
執行程式,看看驗證結果:
生成新的外星人:
當射擊的外星人都沒有了,就要產生新的外星人,首先,我們要去確定外星人都被殺死,就要檢查aliens編組是否為空,如果為空,就要呼叫creat_fleet().我們要在update_bullets()裡執行檢查,因為外星人在這裡被擊殺,
#-*-coding:GBK-*- #-*-coding:utf-8-*- #遊戲的功能模組,包括響應鍵盤滑鼠事件,移動飛船等 import sys import pygame from bullet import Bullet from alien import Alien def check_keydown_events(event,ai_settings,screen,ship,bullets): #響應按鍵 if event.key==pygame.K_RIGHT: ship.moving_right=True #改變標誌位 elif event.key==pygame.K_LEFT: ship.moving_left=True elif event.key==pygame.K_SPACE: #響應按空格鍵 fire_bullet(ai_settings,screen,ship,bullets) def fire_bullet(ai_settings,screen,ship,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): #響應按鍵鬆開 if event.key==pygame.K_RIGHT: ship.moving_right=False elif event.key==pygame.K_LEFT: ship.moving_left=False def check_events(ai_settings,screen,ship,bullets): #響應鍵盤和滑鼠事件 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) 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() def update_bullets(ai_settings,screen,ship,aliens,bullets): #更新子彈的位置,並刪除已消失的子彈 bullets.update() for bullet in bullets.copy(): if bullet.rect.bottom<=0: bullets.remove(bullet) #檢查是否兩者碰撞,是的話,刪除相應的子彈與外星人 collisions=pygame.sprite.groupcollide(bullets,aliens,True,True) if len(aliens)==0: bullets.empty() #刪除現有的子彈並新建新的外星人群 creat_fleet(ai_settings,screen,ship,aliens) #建立外星人群 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 def creat_alien(ai_settings,screen,aliens,alien_number,row_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) #計算螢幕可以放入多少行 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 def creat_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): creat_alien(ai_settings,screen,aliens,alien_number,row_number) #更新外星人的位置 def update_aliens(ai_settings,aliens): check_fleet_edges(ai_settings,aliens) aliens.update() #對於外星人到達邊緣採取的措施: def check_fleet_edges(ai_settings,aliens): 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(): alien.rect.y+=ai_settings.fleet_drop_speed ai_settings.fleet_direction*=-1
主程式:
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame
from setting import Setting
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
def run_game():
pygame.init() #初始化,建立螢幕物件
ai_settings=Setting() #建立一個800*800的螢幕
screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion") #對於這個視窗的命名為Alien Invasion
ship=Ship(ai_settings,screen) #建立飛船
bullets=Group()
aliens=Group()
gf.creat_fleet(ai_settings,screen,ship,aliens)
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)
run_game()
執行程式,驗證結果:
當我射殺完外星人後,就會出現新的外星人群。
重構功能模組裡的update_bullets():
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#遊戲的功能模組,包括響應鍵盤滑鼠事件,移動飛船等
import sys
import pygame
from bullet import Bullet
from alien import Alien
def check_keydown_events(event,ai_settings,screen,ship,bullets): #響應按鍵
if event.key==pygame.K_RIGHT:
ship.moving_right=True #改變標誌位
elif event.key==pygame.K_LEFT:
ship.moving_left=True
elif event.key==pygame.K_SPACE: #響應按空格鍵
fire_bullet(ai_settings,screen,ship,bullets)
def fire_bullet(ai_settings,screen,ship,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): #響應按鍵鬆開
if event.key==pygame.K_RIGHT:
ship.moving_right=False
elif event.key==pygame.K_LEFT:
ship.moving_left=False
def check_events(ai_settings,screen,ship,bullets): #響應鍵盤和滑鼠事件
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)
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()
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_collisions(ai_settings,screen,ship,aliens,bullets)
def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets):
#檢查是否兩者碰撞,是的話,刪除相應的子彈與外星人
collisions=pygame.sprite.groupcollide(bullets,aliens,True,True)
if len(aliens)==0:
bullets.empty() #刪除現有的子彈並新建新的外星人群
creat_fleet(ai_settings,screen,ship,aliens)
#建立外星人群
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
def creat_alien(ai_settings,screen,aliens,alien_number,row_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)
#計算螢幕可以放入多少行
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
def creat_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):
creat_alien(ai_settings,screen,aliens,alien_number,row_number)
#更新外星人的位置
def update_aliens(ai_settings,aliens):
check_fleet_edges(ai_settings,aliens)
aliens.update()
#對於外星人到達邊緣採取的措施:
def check_fleet_edges(ai_settings,aliens):
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():
alien.rect.y+=ai_settings.fleet_drop_speed
ai_settings.fleet_direction*=-1
驗證結果:沒有問題
現在看來整個遊戲開發的大體框架都已經完成了,現在可以實現移動飛船,發射子彈,子彈射殺外星人,外星人會重新補全等大概的功能,但是這個遊戲會一直繼續下去,除非你點選退出,但一個沒有輸贏的遊戲大概會很無聊,所以接下來就來設定如何結束遊戲,結束遊戲有以下幾種情況,1.不想玩了,直接點選退出鍵就結束遊戲。2.如果玩家在限制的時間內未射殺完外星人,或者外星人撞到飛船以及外星人到達螢幕底端,飛船會被摧毀,最多可提供三架飛船,飛船摧毀完遊戲自動結束。
1.監測外星人和飛船相撞的情況,就像子彈和外星人的相撞一樣,在更新外星人的位置後就檢測有無相撞。現在就是簡單檢查有沒有撞到,對於後續的行為先不設定。
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#遊戲的功能模組,包括響應鍵盤滑鼠事件,移動飛船等
import sys
import pygame
from bullet import Bullet
from alien import Alien
def check_keydown_events(event,ai_settings,screen,ship,bullets): #響應按鍵
if event.key==pygame.K_RIGHT:
ship.moving_right=True #改變標誌位
elif event.key==pygame.K_LEFT:
ship.moving_left=True
elif event.key==pygame.K_SPACE: #響應按空格鍵
fire_bullet(ai_settings,screen,ship,bullets)
def fire_bullet(ai_settings,screen,ship,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): #響應按鍵鬆開
if event.key==pygame.K_RIGHT:
ship.moving_right=False
elif event.key==pygame.K_LEFT:
ship.moving_left=False
def check_events(ai_settings,screen,ship,bullets): #響應鍵盤和滑鼠事件
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)
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()
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_collisions(ai_settings,screen,ship,aliens,bullets)
def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets):
#檢查是否兩者碰撞,是的話,刪除相應的子彈與外星人
collisions=pygame.sprite.groupcollide(bullets,aliens,True,True)
if len(aliens)==0:
bullets.empty() #刪除現有的子彈並新建新的外星人群
creat_fleet(ai_settings,screen,ship,aliens)
#建立外星人群
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
def creat_alien(ai_settings,screen,aliens,alien_number,row_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)
#計算螢幕可以放入多少行
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
def creat_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):
creat_alien(ai_settings,screen,aliens,alien_number,row_number)
#更新外星人的位置
def update_aliens(ai_settings,ship,aliens):
check_fleet_edges(ai_settings,aliens)
aliens.update()
#監測外星人和飛船的相撞
if pygame.sprite.spritecollideany(ship,aliens):
print("ship hit!!!")
#對於外星人到達邊緣採取的措施:
def check_fleet_edges(ai_settings,aliens):
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():
alien.rect.y+=ai_settings.fleet_drop_speed
ai_settings.fleet_direction*=-1
方法sprite.spritecollideany()接受兩個實參,一個精靈和一個編組,它檢查編組是否有成員與精靈發生了碰撞,找到與精靈發生碰撞的成員後就停止遍歷編組。如果沒有發生碰撞,返回none。
主程式:
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame
from setting import Setting
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
def run_game():
pygame.init() #初始化,建立螢幕物件
ai_settings=Setting() #建立一個800*800的螢幕
screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion") #對於這個視窗的命名為Alien Invasion
ship=Ship(ai_settings,screen) #建立飛船
bullets=Group()
aliens=Group()
gf.creat_fleet(ai_settings,screen,ship,aliens)
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)
run_game()
執行程式。看看驗證結果:
按上面的程式碼現在已經檢測到相撞了,現在就在來響應下相撞後該有什麼行為;現在建立一個新的飛船例項 ,記錄遊戲飛船被撞毀幾次
建立一個用於記錄跟蹤遊戲資訊的新類Gamestats
#跟蹤遊戲統計資訊的類
class GameStats():
def __init__(self,ai_settings):
self.ai_settings=ai_settings
self.reset_stats()
self.game_active=True #遊戲活動標誌
def reset_stats(self): #初始化在遊戲裡可能會變化的統計資訊
self.ships_left=self.ai_settings.ship_limit
建立一個GameStats的例項,每當開始新遊戲的時候,重置設定一些統計資訊,當前只有一項統計資訊ships_left。
修改設定類;
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#儲存外星人遊戲開發的設定
class Setting():
def __init__(self):
self.screen_width=800 #設定螢幕高度寬度,背景顏色
self.screen_height=600
self.bg_color=(230,230,230)
#飛船設定
self.ship_speed_factor=1.5 #設定飛船移動
self.ship_limit=3 #設定飛船數量
#子彈設定
self.bullet_speed_factor=1
self.bullet_width=3
self.bullet_height=15
self.bullet_color=(0,0,255)
self.bullets_allowed=3
#外星人設定
self.alien_speed_factor=1
self.fleet_drop_speed=5
self.fleet_direction=1 #fleet_direction 為1表示右移,為-1表示左移
修改功能模組:當外星人撞到飛船,將飛船的數量減一,建立一群新的外星人,並將飛船放置到初始位置。
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#遊戲的功能模組,包括響應鍵盤滑鼠事件,移動飛船等
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep
def check_keydown_events(event,ai_settings,screen,ship,bullets): #響應按鍵
if event.key==pygame.K_RIGHT:
ship.moving_right=True #改變標誌位
elif event.key==pygame.K_LEFT:
ship.moving_left=True
elif event.key==pygame.K_SPACE: #響應按空格鍵
fire_bullet(ai_settings,screen,ship,bullets)
def fire_bullet(ai_settings,screen,ship,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): #響應按鍵鬆開
if event.key==pygame.K_RIGHT:
ship.moving_right=False
elif event.key==pygame.K_LEFT:
ship.moving_left=False
def check_events(ai_settings,screen,ship,bullets): #響應鍵盤和滑鼠事件
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)
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()
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_collisions(ai_settings,screen,ship,aliens,bullets)
def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets):
#檢查是否兩者碰撞,是的話,刪除相應的子彈與外星人
collisions=pygame.sprite.groupcollide(bullets,aliens,True,True)
if len(aliens)==0:
bullets.empty() #刪除現有的子彈並新建新的外星人群
creat_fleet(ai_settings,screen,ship,aliens)
#建立外星人群
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
def creat_alien(ai_settings,screen,aliens,alien_number,row_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)
#計算螢幕可以放入多少行
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
def creat_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):
creat_alien(ai_settings,screen,aliens,alien_number,row_number)
#更新外星人的位置
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):
check_fleet_edges(ai_settings,aliens)
aliens.update()
#監測外星人和飛船的相撞
if pygame.sprite.spritecollideany(ship,aliens):
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
#響應被外星人撞到的飛船
def ship_hit(ai_settings,stats,screen,ship,aliens,bullets):
stats.ships_left-=1
aliens.empty() #清空外星人列表
bullets.empty() #清空子彈列表
#建立新的外星人,飛船放入中間
creat_fleet(ai_settings,screen,ship,aliens)
ship.center_ship()
sleep(0.5) #暫停
#對於外星人到達邊緣採取的措施:
def check_fleet_edges(ai_settings,aliens):
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():
alien.rect.y+=ai_settings.fleet_drop_speed
ai_settings.fleet_direction*=-1
從模組time匯入sleep,用於讓遊戲暫停;
修改ship類:
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#建立飛船類
import pygame
class Ship():
def __init__(self,ai_settings,screen):
self.screen=screen
self.ai_settings=ai_settings
#圖片存在images資料夾下,名字是ship.bmp
self.image=pygame.image.load('images/ship.bmp')
self.rect=self.image.get_rect()
self.screen_rect=screen.get_rect()
self.rect.centerx=self.screen_rect.centerx
self.rect.bottom=self.screen_rect.bottom
self.center=float(self.rect.centerx) #因為rect的centerx只能儲存整數值,在飛船的center儲存小數值
self.moving_right=False #設定移動標誌
self.moving_left=False
def update(self):
if self.moving_right and self.rect.right <self.screen_rect.right: #根據移動標誌,來調整位置
self.center+=self.ai_settings.ship_speed_factor #更新飛船的center的值,不是rect
if self.moving_left and self.rect.left>0:
self.center-=self.ai_settings.ship_speed_factor
self.rect.centerx=self.center #來更新rect物件
def blitme(self):
self.screen.blit(self.image,self.rect)
def center_ship(self):
self.center=self.screen_rect.centerx
修改主程式:
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame
from setting import Setting
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
from game_stats import GameStats
def run_game():
pygame.init() #初始化,建立螢幕物件
ai_settings=Setting() #建立一個800*800的螢幕
screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion") #對於這個視窗的命名為Alien Invasion
stats=GameStats(ai_settings) #建立一個用於儲存統計資訊的例項
ship=Ship(ai_settings,screen) #建立飛船
bullets=Group()
aliens=Group()
gf.creat_fleet(ai_settings,screen,ship,aliens)
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,stats,screen,ship,aliens,bullets)
gf.update_screen(ai_settings,screen,ship,aliens,bullets)
run_game()
執行程式,驗證結果如下:
當相撞後,飛船與外星人重新出現,飛船在初始位置
2.有外星人到達螢幕底端:
上面已經處理相撞的情況,現在來處理到達底端的時候,
修改功能模組,新增一個檢查函式,來檢查是否到達底部
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
#遊戲的功能模組,包括響應鍵盤滑鼠事件,移動飛船等
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep
def check_keydown_events(event,ai_settings,screen,ship,bullets): #響應按鍵
if event.key==pygame.K_RIGHT:
ship.moving_right=True #改變標誌位
elif event.key==pygame.K_LEFT:
ship.moving_left=True
elif event.key==pygame.K_SPACE: #響應按空格鍵
fire_bullet(ai_settings,screen,ship,bullets)
def fire_bullet(ai_settings,screen,ship,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): #響應按鍵鬆開
if event.key==pygame.K_RIGHT:
ship.moving_right=False
elif event.key==pygame.K_LEFT:
ship.moving_left=False
def check_events(ai_settings,screen,ship,bullets): #響應鍵盤和滑鼠事件
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)
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()
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_collisions(ai_settings,screen,ship,aliens,bullets)
def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets):
#檢查是否兩者碰撞,是的話,刪除相應的子彈與外星人
collisions=pygame.sprite.groupcollide(bullets,aliens,True,True)
if len(aliens)==0:
bullets.empty() #刪除現有的子彈並新建新的外星人群
creat_fleet(ai_settings,screen,ship,aliens)
#建立外星人群
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
def creat_alien(ai_settings,screen,aliens,alien_number,row_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)
#計算螢幕可以放入多少行
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
def creat_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):
creat_alien(ai_settings,screen,aliens,alien_number,row_number)
#更新外星人的位置
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):
check_fleet_edges(ai_settings,aliens)
aliens.update()
check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets)
#監測外星人和飛船的相撞
if pygame.sprite.spritecollideany(ship,aliens):
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
#響應被外星人撞到的飛船
def ship_hit(ai_settings,stats,screen,ship,aliens,bullets):
if stats.ships_left>0:
stats.ships_left-=1
aliens.empty() #清空外星人列表
bullets.empty() #清空子彈列表
#建立新的外星人,飛船放入中間
creat_fleet(ai_settings,screen,ship,aliens)
ship.center_ship()
sleep(0.5) #暫停
else:
stats.game_active=False
#檢查是否有外星人到達螢幕底端
def check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets):
screen_rect=screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom>=screen_rect.bottom:
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
break
#對於外星人到達左右邊緣採取的措施:
def check_fleet_edges(ai_settings,aliens):
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():
alien.rect.y+=ai_settings.fleet_drop_speed
ai_settings.fleet_direction*=-1
主程式如下:
#-*-coding:GBK-*-
#-*-coding:utf-8-*-
import pygame
from setting import Setting
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
from game_stats import GameStats
def run_game():
pygame.init() #初始化,建立螢幕物件
ai_settings=Setting() #建立一個800*800的螢幕
screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion") #對於這個視窗的命名為Alien Invasion
stats=GameStats(ai_settings) #建立一個用於儲存統計資訊的例項
ship=Ship(ai_settings,screen) #建立飛船
bullets=Group()
aliens=Group()
gf.creat_fleet(ai_settings,screen,ship,aliens)
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,ship,aliens,bullets)
run_game()
當把飛船次數用完後,螢幕到停止不動了: