用pygame写一款飞船游戏(笔记)
pygame為創(chuàng)建一款游戲提供了很多方便地操作,下面將會用此寫一款打飛機游戲。使用的版本為python3。筆記可能有些許錯誤,請見諒。
最后游戲界面如下:
游戲大致想法:外星人水平移動,碰到左右邊緣x軸的速度方向改變,同時y軸會運動。當外星人碰到飛船或到達邊緣時,扣除生命值,重置外星人和飛船位置。每清除完一波外星人,游戲難度提升。
1.整體模塊大致介紹
一共有9個模塊,如下圖
設置類模塊:我們可以將游戲基本設置屬性放在里面,例如窗口的寬和長,背景顏色,又例如飛船速度,外星人運動速度等游戲難度相關的屬性
功能函數(shù)模塊:里面裝著顯示窗口,更新飛船位置等等函數(shù),在主模塊中通過調(diào)用功能函數(shù)模塊便基本實現(xiàn)游戲
飛船類模塊:定義了一個飛船類,在這里存儲著飛船的圖片,以及通過飛船圖片獲取得來的飛船矩形。還有更新飛船位置的函數(shù),在pygame中,可以通過更新矩形位置,來實現(xiàn)物體的移動
子彈類模塊:我們用創(chuàng)建有色矩形的方式來創(chuàng)建子彈,類中存儲著子彈顏色,子彈速度,子彈寬度,其中一部分可以從設置類對象中獲取。還有更新子彈位置的函數(shù),繪制子彈的函數(shù)
外星人類模塊:定義一個外星人類,里面包含著外星人的圖片,代表外星人的矩形,更新外星人位置的函數(shù)等
游戲統(tǒng)計類模塊:存儲著游戲進程中,玩家得分,歷史高分記錄,當前生命值等
按鈕類模塊:可用于生成開始按鈕的類,類中存儲著顯示的字體,將文字渲染后的圖片等
顯示板類:可用于生成顯示的分數(shù),生命條,歷史高分條
2.模塊詳細介紹
游戲功能函數(shù)模塊幾乎包含運行整個游戲所需的函數(shù),我們可以先完善其他模塊的內(nèi)容,最后再完善游戲功能模塊。
2.1游戲設置類模塊
class Settings():def __init__(self):self.bgc = (230,230,230) #背景顏色self.screen_width = 1200self.screen_height = 700 #屏幕大小self.ship_hp = 3 #飛船血條self.bullet_width = 20self.bullet_height = 3self.bullet_color = (0x66,0xcc,0xff) #子彈大小顏色self.bullet_max = 5 #允許射出的子彈最大數(shù)目self.alien_yspeed = 10 #外星人y軸移動速度self.alien_xdirection = 1 #外星人x軸移動方向self.speedup_scale = 1.1 #速度提升倍率和分數(shù)提升倍率self.initial_speed()#初始化飛船,子彈,外星人水平速度。def speed_up(self):self.alien_xspeed *= self.speedup_scaleself.ship_speed *= self.speedup_scaleself.bullet_speed *= self.speedup_scaleself.alien_score += 20def initial_speed(self):'''初始化設置'''self.alien_xspeed = 1self.ship_speed = 3self.bullet_speed = 1.5self.alien_score = 50 #射殺一個外星人后有50分def initial_ship_life(self):self.ship_hp = 3 #重置飛船生命值在游戲設置類模塊中,我們編寫了游戲很多的參數(shù)。如果想改變窗口大小,游戲難度可以通過游戲設置類來改變。
考慮玩法,因為會有難度提升的元素,所以我們需要有一個速度提升速率,然后在一個函數(shù)中調(diào)節(jié)游戲難度相關元素,在清除一波外星人后調(diào)用。同時如果生命值全用掉,需要重來,我們需要初始化這些設置,于是便有初始速率的函數(shù)。
2.2飛船類模塊
import pygame from pygame.sprite import Sprite class Ship(Sprite):def __init__(self,screen,ai_settings):super().__init__()self.image = pygame.image.load('bship.png') #加載圖形self.screen = screen #獲取屏幕的surfaceself.screen_rect = self.screen.get_rect() #獲取屏幕矩形邊框self.ship_rect = self.image.get_rect() #獲取飛船初始邊框self.ship_rect.centerx = self.screen_rect.centerxself.ship_rect.bottom = self.screen_rect.bottom #將飛船位置移動到屏幕底部終點self.rect = self.ship_rectself.ship_width = self.rect.widthself.left_flag = Falseself.right_flag = False #飛船的移動標志self.settings = ai_settings #引入系統(tǒng)設置def blitme(self):'''繪制飛船的函數(shù)'''self.screen.blit(self.image,self.ship_rect) #繪制飛船def update(self):'''更新飛船移動標志的函數(shù)'''if self.left_flag and self.ship_rect.left > 0:self.rect.centerx -= self.settings.ship_speedif self.right_flag and self.ship_rect.right < self.screen_rect.right:self.rect.centerx += self.settings.ship_speeddef reset_ship(self):self.ship_rect.centerx = self.screen_rect.centerx #重新放置飛船游戲的一幀就是一幅圖像,我們繪制一幅圖像會有圖層疊放順序,而一個圖層在pygame里面就是一個surface
| pygame.image.load(圖片路徑) | 返回一個對應的surface |
| surface.get_rect() | 返回surface對應的矩形 |
rect的相關參數(shù)
| rect.center | rect的中心 |
| rect.centerx | rect的中心x坐標 |
| rect.centery | rect的中心y坐標 |
| rect.bottom/top/left/right | rect的各邊界 |
| rect.width | 矩形的寬度 |
| rect.height | 矩形的高度 |
| rect.x | 矩形左上角x坐標 |
| rect.y | 矩形左上角y坐標 |
在上面的飛船類模塊中,有兩個移動標志,是為了在游戲功能函數(shù)模塊中檢測按鈕事件,改變移動標志,讓飛船移動的。
Sprite是從pygame.sprite引入的一個類,主要方便對繼承該類的類對象進行編組,進行多元素管理。飛船類繼承Sprite類是為了制作左上方的血條。
2.3子彈類模塊
import pygame from pygame.sprite import Spriteclass Bullet(Sprite):def __init__(self,ai_setting,screen,ship):super().__init__()self.screen = screen #獲取當前屏幕self.rect = pygame.Rect(0,0,ai_setting.bullet_width,ai_setting.bullet_height) #新建代表子彈的矩形self.rect.centerx = ship.ship_rect.centerxself.rect.top = ship.ship_rect.top #將位置調(diào)整至飛船頂部self.color = ai_setting.bullet_color #設置子彈顏色self.speed = ai_setting.bullet_speed #設置子彈速度def update(self):self.rect.y -= self.speeddef draw_bullet(self):pygame.draw.rect(self.screen,self.color,self.rect) #繪制子彈| pygame.Rect(x,y,width,height) | 以(x,y)作為將創(chuàng)作矩形的左上角坐標,創(chuàng)建一個寬為width,高為height的矩形 |
| pygame.draw.rect(surface,顏色,rect) | 在surface中繪制指定顏色的矩形 |
子彈類模塊中,用pygame繪制一個簡單的矩形來代表子彈。
在update()函數(shù)中,通過更改子彈代表矩形的左上角y坐標來讓其移動。另外,子彈類要繼承Sprite類,是為了對其進行編組,其必要性比飛船類繼承Sprite類更大。后面通過向編組中添加元素,調(diào)用編組.update()就能對里面的元素全部調(diào)用update函數(shù)。以及檢測碰撞可以使用。update()函數(shù)有點類似C++中的虛函數(shù),名字不能變。
2.4外星人類模塊
import pygame from pygame.sprite import Spriteclass Alien(Sprite):def __init__(self,ai_settings,screen):super().__init__()self.ai_settings = ai_settingsself.screen = screenself.image = pygame.image.load("aship.png") #加載敵人圖片self.rect = self.image.get_rect() #獲取矩形self.rect.x = self.rect.widthself.rect.y = self.rect.height #開始矩形默認坐標位左上角,移動一個身位def check_edge(self):screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right or self.rect.left <=0:return True #檢測是否到達邊界def update(self):'''向左或向右移動外星人'''self.rect.x += (self.ai_settings.alien_xspeed * self.ai_settings.alien_xdirection)外星人類同樣要繼承Sprite類,方便后面編組。
update()函數(shù)用來更新其x坐標,因為update()函數(shù)幾乎每一幀都會調(diào)用,而y軸的移動只有外星人碰到邊緣后才會調(diào)用。
類中還有一個檢查是否碰到窗口左右兩邊的函數(shù),返回bool型值。從而在游戲功能函數(shù)模塊中的函數(shù)調(diào)用檢測是否到達邊緣并改變alien_xdirection即外星人的x軸移動方向。
2.5游戲統(tǒng)計類模塊
import json class Game_stats():'''跟蹤游戲的統(tǒng)計信息'''def __init__(self,ai_settings):self.ai_settings = ai_settingsself.ship_hp = ai_settings.ship_hp #獲取飛船血條個數(shù)self.score = 0 #統(tǒng)計得分self.game_active = Falseself.level = 1 #統(tǒng)計等級 with open("high_score.json",'r') as score_file:self.high_score = json.load(score_file)def reset_ship_hp(self):self.ship_hp = self.ai_settings.ship_hp #重新設置生命self.score = 0 #重新設置得分def update_high_score(self):if self.score > self.high_score:self.high_score = self.score #更新最高分with open("high_score.json",'w') as score_file:json.dump(self.high_score,score_file)該類的主要操作就是統(tǒng)計生命值,分數(shù)等等。
有個重置生命值的函數(shù),在生命值耗盡重新開始游戲時調(diào)用,更新最高分函數(shù),可以在每擊殺一個外星人時調(diào)用一次,里面還會判斷是否更新。
這里用了json文件來存儲高分記錄。我們可以先在當前文件夾創(chuàng)建一個json文件,并寫入0值,什么都不寫會報錯。
2.6游戲按鈕類模塊
import pygame.fontclass Button():def __init__(self,ai_settings,screen,msg):'''創(chuàng)建對應文本msg的按鈕'''self.screen = screenself.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)#設定按鈕字體字號self.rect = pygame.Rect(0,0,self.width,self.height)self.rect.center = self.screen_rect.center#設定按鈕矩形,并移動到屏幕中心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)| pygame.font.SysFont(字體,字號,bool1,bool2) | 創(chuàng)建字體,bool1為是否粗體,bool2為是否斜體,默認False。字體None為默認字體。 |
| Font對象.render(文本,bool,c1,c2) | 將文本以對應字體渲染成圖片,bool型值為是否開啟抗鋸齒功能,c1為文本顏色,c2為背景顏色。返回surface |
| surface1.fill(color,rect) | 在surface1上的rect填充顏色 |
| surface1.blit(surface2,rect) | 在surface1上對應矩形處繪制surface2 |
font模塊詳細:https://blog.csdn.net/qq_41556318/article/details/86303502
在這里我們主要是對play按鈕的新建,先用pygame.font.SysFont(None,48)創(chuàng)建字體,然后用font.render(...)來得到文本的surface。最后繪制時先繪制背景矩形,在背景surface上繪制文本的surface。繪制背景矩形也可以用子彈類用的pygame.draw.rect()。這里要先繪制背景矩形是因為,文本surface的矩形往往事前較難知道多大。可能偏大,可能偏小。
下面第一幅圖為不繪制按鈕背景矩形,第二幅為繪制后。
2.7 顯示板類模塊
from Ship import Ship import pygame from pygame.sprite import Groupclass Show_board():def __init__(self,ai_settings,screen,stats):self.screen = screenself.screen_rect = screen.get_rect()self.ai_settings = ai_settingsself.text_color = (30,30,30)self.font = pygame.font.SysFont(None,48) #設置字體字號self.prep(stats)def prep_score(self,stats):'''準備當前得分文本surface'''self.score = int(round(stats.score,-1)) #精確分數(shù)到十位self.total_score = "{:,}".format(self.score)#數(shù)字格式化,每隔三位加一個逗號self.total_score_image = self.font.render(self.total_score,True,self.text_color,self.ai_settings.bgc) #將分數(shù)渲染成圖片self.total_score_image_rect = self.total_score_image.get_rect() #獲取圖片矩形self.total_score_image_rect.right = self.screen_rect.right -20 self.total_score_image_rect.top = self.screen_rect.top #設置矩形位置def prep_high_score(self,stats):'''準備最高得分文本surface'''self.high_score = int(round(stats.high_score,-1))self._high_score = "{:,}".format(self.high_score)self.high_score_image = self.font.render(self._high_score,True,self.text_color,self.ai_settings.bgc)self.high_score_image_rect = self.high_score_image.get_rect() #獲取矩形self.high_score_image_rect.centerx = self.screen_rect.centerx self.high_score_image_rect.top = self.screen_rect.top #設置矩形位置def prep_level(self,stats):'''準備當前難度文本surface'''self.level = stats.levelself.level_str = "level:" + str(self.level)self.level_image = self.font.render(self.level_str,True,self.text_color,self.ai_settings.bgc) self.level_image_rect = self.level_image.get_rect() #獲取矩形self.level_image_rect.right = self.screen_rect.right-20self.level_image_rect.top = self.screen_rect.top + 32 #設置矩形位置def prep_hp(self,stats):'''準備生命值的圖像'''self.hp = stats.ship_hpself.ships = Group()for number in range(self.hp):ship = Ship(self.screen,self.ai_settings) #新建一個飛船圖標ship.rect.x = 10 + number * ship.ship_widthship.rect.y = 10 #設置圖標位置self.ships.add(ship)def prep(self,stats):self.prep_score(stats)self.prep_high_score(stats)self.prep_level(stats)self.prep_hp(stats)def draw_board(self):'''繪制文本的函數(shù)'''self.screen.blit(self.total_score_image,self.total_score_image_rect)self.screen.blit(self.high_score_image,self.high_score_image_rect)self.screen.blit(self.level_image,self.level_image_rect)self.ships.draw(self.screen)| round(number,精確位數(shù)) | 返回number對應精確位數(shù)的float型數(shù),1位小數(shù)點后一位,-1為精確到十位,-2為百位,以此類推。 |
| “:,”.format(number) | 返回字符串,內(nèi)容為number每隔3位加逗號。如1000000會變成1,000,000 |
顯示板類只要是在屏幕上顯示生命值,當前分數(shù),最高分數(shù),當前游戲難度。做法都是得到渲染文本后的surface,然后進行繪制,這里文本背景顏色用一開始設置類中的窗口背景顏色就可以了。
很多模塊都需要讀取窗口的surface,來根據(jù)surface的某些參數(shù)確定自己的位置。
2.8主模塊
import pygamefrom Settings import Settings from Ship import Ship import GameFunction as gf from pygame.sprite import Group from Alien import Alien from Game_stats import Game_stats from button import Button from Show_board import Show_boarddef run_game():'''運行游戲'''settings = Settings() #新建設置類對象pygame.init() #初始化screen = pygame.display.set_mode((settings.screen_width,settings.screen_height)) #新建一個屏幕并設置屏幕寬和高度pygame.display.set_caption("打飛機") #設置窗口標題ship = Ship(screen,settings) #新建飛船對象bullets = Group() #創(chuàng)建存儲子彈的編組aliens = Group() #創(chuàng)建存儲外星人的編組gf.create_aliens(settings,screen,ship,aliens) #添加元素stats = Game_stats(settings) #新建統(tǒng)計類play_button = Button(settings,screen,"PLAY") #新建play按鈕show_board = Show_board(settings,screen,stats) #新建顯示面板while True:gf.check_event(settings,screen,ship,bullets,stats,play_button)#檢查按鍵事件if stats.game_active == True:ship.update() #更新飛船位置gf.update_bullets(bullets,aliens,settings,screen,ship,stats,show_board)#更新和繪畫子彈的函數(shù)gf.update_aliens(settings,screen,bullets,aliens,ship,stats,show_board)#更新外星人位置并檢查碰撞gf.update_Screen(settings,screen,ship,bullets,aliens,stats,play_button,show_board)#更新屏幕run_game()| pygame.display.set_mode((width,height)) | 設置主窗口大小,返回surface |
| pygame.display.set_caption(標題) | 設置標題 |
Group()為新建一個編組,可以往編組里面添加元素
| group.update() | 對里面的每個精靈調(diào)用update(),精靈的update()需要自己定義 |
| group.draw(surface) | 在surface中自動調(diào)用surface.blit(…)函數(shù) |
| group.add(a) | 添加元素a |
| group.remove(a) | 刪除元素a |
| group.sprites() | 以列表形式返回編組中的精靈 |
| group.empty() | 判斷編組中是否含有元素 |
update(),draw()相關定義:https://www.cnblogs.com/huwt/p/10333500.html
在主模塊中我們會做一下事情:
1.創(chuàng)建主窗口
2.創(chuàng)建飛船對象
3.創(chuàng)建子彈空編組
4. 創(chuàng)建外星人空編組
5. 調(diào)用創(chuàng)建一波外星人函數(shù)
6. 創(chuàng)建統(tǒng)計類對象
7. 創(chuàng)建play按鈕
8. 創(chuàng)建顯示板類對象
9. 主循環(huán):
1.檢查事件按鈕函數(shù)
2.如果游戲狀態(tài)活躍,執(zhí)行更新飛船,子彈,外星人的函數(shù)
3.更新屏幕內(nèi)容函數(shù)
創(chuàng)建一波外星人的函數(shù),及主循環(huán)的函數(shù)都存儲在游戲功能函數(shù)模塊中。
我們在游戲設置類會有個游戲狀態(tài)的變量,開始時為False,要允許窗口有內(nèi)容顯示及點擊退出,檢查事件按鈕函數(shù)和更新屏幕內(nèi)容函數(shù)不檢測游戲狀態(tài)。其他則未點擊play時不執(zhí)行。
3.游戲功能類模塊
引入模塊:
import pygame
import sys
from Bullets import Bullet
from Alien import Alien
from time import sleep
3.1 檢查事件按鈕函數(shù)
def check_event(ai_setting,screen,ship,bullets,stats,play_button):'''按鈕事件檢查'''for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit() #檢測是否退出elif event.type == pygame.KEYDOWN:if event.key == pygame.K_RIGHT:ship.right_flag = Trueelif event.key == pygame.K_LEFT:ship.left_flag = True #按鈕按下相關操作elif event.key == pygame.K_SPACE:new_bullet = Bullet(ai_setting,screen,ship)if len(bullets) < ai_setting.bullet_max:bullets.add(new_bullet) #按下空格添加子彈elif not stats.game_active and event.type == pygame.MOUSEBUTTONDOWN:mouse_x,mouse_y = pygame.mouse.get_pos() #獲取鼠標位置flag = play_button.rect.collidepoint(mouse_x,mouse_y) #檢測鼠標是否在矩形中if not stats.game_active and flag:stats.game_active = True #將游戲狀態(tài)設置為可以開始pygame.mouse.set_visible(False) #隱藏鼠標elif event.type == pygame.KEYUP:if event.key == pygame.K_RIGHT:ship.right_flag = Falseif event.key == pygame.K_LEFT:ship.left_flag = False #松開按鈕相關操作| pygame.event.get() | 獲取鍵盤和鼠標的所有事件 |
| sys.exit() | 程序終止 |
| rect.collidepoint(x,y) | 檢查(x,y)點是否在rect中 |
| pygame.mouse.get_pos() | 獲取當前鼠標的x,y值 |
| pygame.mouse.get_visible(bool) | 設置鼠標在窗口內(nèi)可見或不可見 |
event.type 事件類型
| pygame.QUIT | 點擊窗口關閉按鈕 |
| pygame.KEYDOWN | 按鈕按下 |
| pygame.KEYUP | 按鈕松開 |
| pygame.MOUSEBUTTONDOWN | 鼠標點擊(左/右鍵) |
event.key按鈕類型
| pygame.K_RIGHT | 方向右鍵 |
| pygame.K_LEFT | 方向左鍵 |
| pygame.K_SPACE | 空格鍵 |
在這個檢測按鈕事件的函數(shù)中,我們先用for event in pygame.event.get()來獲取全部事件,然后先判斷event.type,如果是游戲非活躍狀態(tài)下點擊鼠標,則先用pygame.mouse.get_pos()獲取鼠標坐標檢測play_button.rect.collidepoint(x,y)來檢測是否有點擊到正確的矩形,如果有則設置游戲活躍狀態(tài)為True
如果是按下鍵盤按鈕,則檢測是按下哪個按鈕,如果是方向鍵則設置飛船的允許移動標志為True,如果是空格鍵,我們限定最多射出5發(fā)子彈,滿足條件時,才往子彈編組中添加新的子彈。
如果是松開鍵盤按鈕,則檢測是松開哪個按鈕,這時我們只用考慮方向鍵,并將對應的移動標志設置為False就可以了。
3.2 更新繪制屏幕的函數(shù)
def update_Screen(ai_settings,screen,ship,bullets,aliens,stats,play_button,show_board):'''繪制屏幕內(nèi)容的函數(shù)'''screen.fill(ai_settings.bgc) #先圖刷背景顏色ship.blitme() #畫好飛船位置for bullet in bullets.sprites():bullet.draw_bullet()aliens.draw(screen) #對編組每一個元素進行繪制if not stats.game_active:play_button.draw_button()show_board.draw_board()pygame.display.flip() #顯示出來| pygame.display.flip() | 更新待顯示的surface到屏幕上 |
這個函數(shù)里面,我們?nèi)缤瑢⒏鱾€圖層組合起來形成一幅圖像。
我們先用screen.fill(...)來填充背景顏色,然后調(diào)用ship.blitme()函數(shù)來繪制飛船,因為子彈我們是通過繪制矩形的方式來呈現(xiàn),沒有image這個屬性,所以我們不能直接用bullets.draw(screen)函數(shù)而需要逐個繪制子彈。接著直接aliens.draw(screen)就能直接繪制外星人,相當于調(diào)用了screen.blit(alien.image,alien.rect),所以類定義時需要有這兩個數(shù)據(jù)成員。
接著,在游戲活躍狀態(tài)為False時調(diào)用play_button.draw_button繪制PLAY按鈕,接著則是調(diào)用show_boadrd.draw_board()將顯示板的其他元素顯示出來。最后則是調(diào)用pygame.display.flip()來讓所有surface顯示
3.3 創(chuàng)建外星人及群的函數(shù)
def create_alien(ai_settings,screen,aliens,number_x,number_y):'''創(chuàng)建一個外星人的函數(shù)'''alien = Alien(ai_settings,screen)alien.rect.x = alien.rect.width + 2 * alien.rect.width * number_xalien.rect.y = alien.rect.height + 2 * alien.rect.height * number_y#計算這個外星人的坐標aliens.add(alien) #將該外星人添加進編組中def get_alien_numberx(ai_settings,alien_width):'''計算一行能有多少個外星人的函數(shù)'''total_space_x = ai_settings.screen_width - 2 * alien_width #一行總長度number = int(total_space_x/(2 * alien_width)) #一行外星人個數(shù)return numberdef get_alien_numbery(ai_settings,ship_height,alien_height):'''計算一列能有多少個外星人的函數(shù)'''total_space_y = ai_settings.screen_height - ship_height - 3*alien_heightnumber = int(total_space_y/(2 * alien_height))return numberdef create_aliens(ai_settings,screen,ship,aliens):'''創(chuàng)建外星人群的函數(shù)'''alien = Alien(ai_settings,screen)alien_width = alien.rect.widthalien_height = alien.rect.height #獲取一個外星人的寬度與高度total_number_x = get_alien_numberx(ai_settings,alien_width)total_number_y = get_alien_numbery(ai_settings,ship.ship_rect.height,alien_height)#獲取行和列for number_y in range(total_number_y):for number_x in range(total_number_x):create_alien(ai_settings,screen,aliens,number_x,number_y)#創(chuàng)建外星人在創(chuàng)建一個外星人的函數(shù)中,我們用了alien.rect.x = alien.rect.width + 2 * alien.rect.width * number_x這樣的語句來創(chuàng)建對應位置的外星人,這里2*...可以改變,這里主要是為了在兩個外星人之間留著一個外星人的空隙。
在計算外星人一行,一列有多少個外星人的函數(shù)中,我們想讓一行中左右兩邊各差一個外星人才到達窗口左右邊緣。一列中應考慮與飛船的距離及與窗口上邊界差多少個外星人。這些可以自己調(diào)整。在計算number時都是2*...則是考慮兩個外星人之間差一個外星人的身位。
在創(chuàng)建外星人群的函數(shù)中,我們先創(chuàng)建一個臨時用的外星人,但不添加進編組以獲取一個外星人的長和寬。接著調(diào)用計算一列、一行中有多少個外星人函數(shù),最后用循環(huán)一個個創(chuàng)建外星人便可。
3.4 更新子彈位置的函數(shù)
def update_bullets(bullets,aliens,ai_settings,screen,ship,stats,show_board):'''更新子彈顯示的函數(shù)'''bullets.update() #調(diào)用編組中元素的所有update函數(shù)for bullet in bullets.copy():if bullet.rect.bottom <= 0:bullets.remove(bullet) #將超出屏幕邊界的子彈刪除collision = pygame.sprite.groupcollide(bullets,aliens,True,True)if collision:for alien in collision.values():stats.score += ai_settings.alien_score #射中后加分stats.update_high_score() #檢查是否需要更新最高分show_board.prep_score(stats) #更新分數(shù)顯示show_board.prep_high_score(stats) #更新最高分顯示if len(aliens) == 0:bullets.empty()ai_settings.speed_up()create_aliens(ai_settings,screen,ship,aliens)stats.level += 1show_board.prep_level(stats)#射殺完外星人后重新新建| pygame.sprite.groupcollide(g1,g2,bool1,bool2) | 檢查g1和g2之間是否有碰撞,如果有則根據(jù)布爾型值來確定是否刪除編組對應發(fā)生碰撞的sprite,bool1對應g1,返回字典。 |
在更新子彈位置的函數(shù)中,我們先調(diào)用bullets.update()來更新每顆子彈的位置,然后檢查是否有超出邊界的,如果有則從編組中刪除。接著我們調(diào)用pygame.sprite.groupcollide(...)來檢查子彈和外星人兩個編組間是否有碰撞,如果有碰撞刪除對應的子彈和外星人,并且實現(xiàn)加分,判斷是否超過歷史高分,更新需要分數(shù)顯示等等的功能。最后用len(aliens)判斷是否擊殺全部外星人,沒有了則調(diào)用創(chuàng)建外星人群函數(shù),并且調(diào)用ai_settings.speed_up()來提升難度并修改stats.level,最后更新游戲等級顯示。
3.5 改變外星人群運動狀態(tài)函數(shù)
def change_aliens_move(ai_settings,aliens):'''改變外星人群x軸移動方向,并讓其在y軸移動一段距離'''for alien in aliens.sprites():alien.rect.y += ai_settings.alien_yspeedai_settings.alien_xdirection *= -1在這個函數(shù)中我們改變alien.rect.y并且改變外星人的x軸移動方向,在下一個檢測左右邊緣函數(shù)中,如果碰到左右邊緣我們調(diào)用這個上面的函數(shù)。
3.6 檢測外星人碰到左右邊緣函數(shù)
def check_aliens_edge(ai_settings,aliens):'''檢查外星人群是否有接觸邊緣的現(xiàn)象并改變運動方向'''for alien in aliens.sprites():if alien.check_edge():change_aliens_move(ai_settings,aliens) #確一改變一群break在這里我們遍歷編組的sprite,并且調(diào)用alien.check_edge()來檢測是否到達邊緣,如果有一個到達則改變一整群的運動狀態(tài)。
3.7 飛船被擊中后的函數(shù)
def after_ship_hit(ai_settings,screen,bullets,aliens,ship,stats,show_board):'''飛船被擊中后的函數(shù)'''stats.ship_hp -= 1 #減少生命值ship.reset_ship() #重新放置飛船位置bullets.empty() aliens.empty() #清空外星人和子彈create_aliens(ai_settings,screen,ship,aliens)#重新放置子彈show_board.prep_hp(stats) #更新生命值顯示sleep(0.5)在這里我們定義了外星人碰到飛船或到達屏幕底部后的行為,扣除生命值,重置飛船位置,清空當前外星人和子彈,再新建一群外星人,然后調(diào)用show_board.prep_hp(stats)來更新生命值面板,前面已有from time import sleep,最后我們調(diào)用sleep(0.5)來使其停頓一會。
3.8 檢查外星人是否到達底部的函數(shù)
def check_aliens_bottom(ai_settings,screen,bullets,aliens,ship,stats):'''檢查外星人是否到達底部'''for alien in aliens.sprites():screen_rect = screen.get_rect()if alien.rect.bottom >= screen_rect.bottom:after_ship_hit(ai_settings,screen,bullets,aliens,ship,stats)break3.9 更新外星人位置的函數(shù)
def update_aliens(ai_settings,screen,bullets,aliens,ship,stats,show_board):'''檢查是否有外星人處于屏幕邊緣并更新位置的函數(shù)'''check_aliens_edge(ai_settings,aliens)aliens.update()if pygame.sprite.spritecollideany(ship,aliens):after_ship_hit(ai_settings,screen,bullets,aliens,ship,stats,show_board)check_aliens_bottom(ai_settings,screen,bullets,aliens,ship,stats)if stats.ship_hp < 1 :stats.game_active = Falseai_settings.initial_speed() #重置速度ai_settings.initial_ship_life() #重置飛船生命stats.level = 1 #重置等級| pygame.sprite.spritecollideany(sprite,group) | 檢測sprite和group之間的碰撞,返回布爾值 |
pygame中的碰撞檢測:https://www.cnblogs.com/msxh/p/5027688.html
在這個函數(shù)中,我們先調(diào)用檢查外星人碰到左右邊緣的函數(shù),然后調(diào)用aliens.update()來更新外星人的水平位置,接著通過pygame.sprite.spritecollideany(...)來檢測飛船和外星人是否有碰撞(這里飛船類中如果沒有繼承Sprite也是可以的。可能在類屬性定義中包含需要的標識符)如果有碰撞調(diào)用飛船被擊中的函數(shù),然后再檢測外星人是否到達底部,如果這里有到達,在函數(shù)中也會調(diào)用飛船被擊中的函數(shù)。最后則是判斷生命值是否小于1,小于則重置游戲。
總結
以上是生活随笔為你收集整理的用pygame写一款飞船游戏(笔记)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 过滤的原理及其必要性
- 下一篇: AndroidStudio使用手机进行模