Pygame游戲開發(fā)之太空射擊實戰(zhàn)子彈與碰撞處理篇_第1頁
Pygame游戲開發(fā)之太空射擊實戰(zhàn)子彈與碰撞處理篇_第2頁
Pygame游戲開發(fā)之太空射擊實戰(zhàn)子彈與碰撞處理篇_第3頁
Pygame游戲開發(fā)之太空射擊實戰(zhàn)子彈與碰撞處理篇_第4頁
Pygame游戲開發(fā)之太空射擊實戰(zhàn)子彈與碰撞處理篇_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第Pygame游戲開發(fā)之太空射擊實戰(zhàn)子彈與碰撞處理篇目錄視頻碰撞邊界框敵人與玩家碰撞射擊子彈精靈按鍵事件生成子彈子彈碰撞

視頻

本教程的視頻

碰撞

碰撞是游戲開發(fā)的基本組成部分。碰撞檢測就是要檢測游戲中的一個對象是否正在接觸另一個對象。碰撞處理決定了當碰撞發(fā)生時你想要發(fā)生什么。

在我們的游戲中,我們目前有許多敵人的精靈沿著屏幕飛向玩家,我們想知道其中一個精靈何時出現(xiàn)。對于我們游戲的這個階段,我們只會說敵人擊中玩家意味著游戲結(jié)束了。

邊界框

請記住,Pygame中的每個精靈都有一個rect定義其坐標和大小的屬性。Pygame中的一個Rect對象的格式是[x,y,width,height],其中x和y表示矩形的左上角。此矩形的另一個詞是邊界框,因為它表示對象的邊界。

這種碰撞檢測稱為AABB,代表軸對齊邊界框,因為矩形與屏幕軸對齊-它們不會傾斜一定角度。AABB碰撞非常受歡迎,因為它速度很快-計算機可以非??焖俚乇容^矩形的坐標,如果您要比較大量對象,這將非常有用。

要檢測碰撞,我們需要查看玩家的rect碰撞,并將其與每個敵人的rect碰撞進行比較?,F(xiàn)在,我們可以通過循環(huán)遍歷敵人并對執(zhí)行此比較的每個敵人來執(zhí)行此操作:

在這張圖片中,您可以看到只有矩形#3與大黑色矩形相撞。#1在x軸上重疊,但在y軸上不重疊;#2在y中重疊,但在x中不重疊。為了使兩個矩形重疊,它們的邊界必須在每個軸上重疊。在代碼中編寫以下內(nèi)容:

ifmob.rect.rightplayer.rect.leftand\

mob.rect.leftplayer.rect.rightand\

mob.rect.bottomplayer.rect.topand\

mob.rect.topplayer.rect.bottom:

collide=True

對我們來說幸運的是,Pygame有一個內(nèi)置的方式,通過使用這個spritecollide()函數(shù)來做到這一點。

敵人與玩家碰撞

我們將此命令添加到游戲循環(huán)的更新部分:

#Update

all_sprites.update()

#checktoseeifamobhittheplayer

hits=pygame.sprite.spritecollide(player,mobs,False)

ifhits:

running=False

spritecollide()語法

#Findspritesinagroupthatintersectanothersprite.

spritecollide(sprite,group,dokill,collided=None)-Sprite_list

該spritecollide()函數(shù)采用3個參數(shù):要檢查的sprite的名稱、要與之進行比較的組的名稱,以及名為dokill的True/False參數(shù)。

dokill參數(shù)如果設(shè)置為True,則所有發(fā)生碰撞的sprite都將從組中刪除。例如,如果我們試圖查看玩家是否撿到了一枚硬幣,我們希望將其設(shè)置為True硬幣消失。

collied參數(shù)是一個回調(diào)函數(shù),用于計算兩個精靈是否發(fā)生沖突。它應(yīng)該將兩個精靈作為值,并返回一個bool值,指示它們是否發(fā)生沖突。如果未傳遞collied參數(shù),則所有精靈都必須具有rect值,該值是精靈區(qū)域的矩形,將用于計算碰撞。

該spritecollide()命令的返回結(jié)果是被擊中的精靈列表(請記住,玩家可能一次與多個敵人相撞)。我們將該列表分配給變量hits。

如果hits列表不為空,則if語句將為True,并且我們設(shè)置running為False游戲?qū)⒔Y(jié)束。

射擊

子彈精靈

現(xiàn)在我們準備添加一個新的精靈:子彈。這將是一個精靈,在我們射擊時生成,出現(xiàn)在玩家精靈的頂部,并以相當高的速度向上移動。定義精靈現(xiàn)在應(yīng)該開始看起來很熟悉了,所以下面是完整的Bullet類:

classBullet(pygame.sprite.Sprite):

def__init__(self,x,y):

pygame.sprite.Sprite.__init__(self)

self.image=pygame.Surface((10,20))

self.image.fill(YELLOW)

self.rect=self.image.get_rect()

self.rect.bottom=y

self.rect.centerx=x

self.speedy=-10

defupdate(self):

self.rect.y+=self.speedy

#killifitmovesoffthetopofthescreen

ifself.rect.bottom0:

self.kill()

在子彈精靈的__init__()方法中,我們傳遞x和y值,以便我們可以告訴精靈出現(xiàn)在哪里。由于玩家精靈可以移動,因此將設(shè)置為玩家射擊時玩家所在的位置。我們設(shè)置speedy為負值,以便它將向上移動。

最后,我們檢查子彈是否從屏幕頂部脫落,如果是這樣,我們將其刪除。

按鍵事件

為了保持簡單,我們將讓它每次玩家按下空格鍵時,都會發(fā)射一顆子彈。我們需要將其添加到事件檢查中:

foreventinpygame.event.get():

#checkforclosingwindow

ifevent.type==pygame.QUIT:

running=False

elifevent.type==pygame.KEYDOWN:

ifevent.key==pygame.K_SPACE:

player.shoot()

我們的新代碼檢查事件,如果存在KEYDOWN事件,則檢查它是否是K_SPACE按鍵。如果是這樣,我們將運行玩家精靈的shoot()方法。

生成子彈

首先,我們需要添加一個新組來保存所有項目符號:

bullets=pygame.sprite.Group()

現(xiàn)在,我們可以將以下方法添加到Player類中:

defshoot(self):

bullet=Bullet(self.rect.centerx,self.rect.top)

all_sprites.add(bullet)

bullets.add(bullet)

該shoot()方法所做的就是生成一顆子彈,使用玩家的頂部中心作為生成點。然后,我們確保將子彈精靈添加到all_sprites(以便將其繪制和更新)和bullets,我們將用于碰撞。

子彈碰撞

現(xiàn)在我們需要檢查子彈是否擊中了敵人。這里的區(qū)別在于,我們有多個子彈(在bullets組中)和多個敵人(在mobs組中),所以我們不能像以前那樣使用spritecollide(),因為這只會將一個精靈與一個組進行比較。相反,我們將使用groupcollide():

groupcollide()語法

#Findallspritesthatcollidebetweentwogroups.

groupcollide(group1,group2,dokill1,dokill2,collided=None)-Sprite_dict

發(fā)現(xiàn)兩組中的所有精靈之間的沖突。通過比較每個Sprite的Sprite.rect屬性或使用collided函數(shù)(如果不是None)來確定碰撞。

返回值是個字典,未發(fā)生碰撞時,字典為空。發(fā)生碰撞時,字典的keys是group1中發(fā)生碰撞的對象(一直以為字典的keys值是個字符串之類的東西,沒想到還可以是對象),values是一個列表,其元素是group2中與每一個group1發(fā)生碰撞的所有對象。

Groupcollide返回值的形態(tài)和使用是個難點,舉例說明:比如group1有三架飛機對象p1、p2、p3,group2有八個敵人對象b1、b2、b3、b4、b5、b6、b7、b8,假如p1與b1、b4、b7發(fā)生碰撞,p2與b2、b5、b8發(fā)生碰撞,

groupcollide(group1,group2,1,1)

返回值是如下的字典:

{p1:[b1,b4,b7],p2:[b2,b5,b8]}

group1中的每個發(fā)生碰撞的Sprite都會添加到返回字典中,作為鍵。每個項的值是組2中相交的精靈列表。

如果任一dokill參數(shù)為True,則碰撞的精靈將從其各自的組中刪除。

collieded參數(shù)是一個回調(diào)函數(shù),用于計算兩個精靈是否發(fā)生沖突。它應(yīng)該將兩個精靈作為值,并返回一個bool值,指示它們是否正在碰撞。如果未傳遞collided,則所有精靈都必須具有rect值,該值是精靈區(qū)域的矩形,將用于計算碰撞。

#Update

all_sprites.update()

#checktoseeifabullethitamob

hits=pygame.sprite.groupcollide(mobs,bullets,True,True)

forhitinhits:

m=Mob()

all_sprites.add(m)

mobs.add(m)

該groupcollide()函數(shù)類似于spritecollide(),除了您命名兩個組進行比較,并且您將獲得的是被擊中的敵人列表。有兩個dokill選項,每個組一個。

如果我們只是刪除敵人,我們將遇到一個問題:敵人用完了!因此,我們要做的就是hits循環(huán),對于我們摧毀的每個敵人,將生成另一個新的敵人。

現(xiàn)在它實際上開始感覺像一個游戲:

在下一課中,我們將學(xué)習(xí)如何向游戲添加圖形,而不是使用那些純色矩形。

此部分的完整代碼

#KidsCanCode-GameDevelopmentwithPygamevideoseries

#Shmupgame-part3

#Videolink:/watchv=33g62PpFwsE

#Collisionsandbullets

importpygame

importrandom

WIDTH=480

HEIGHT=600

FPS=60

#definecolors

WHITE=(255,255,255)

BLACK=(0,0,0)

RED=(255,0,0)

GREEN=(0,255,0)

BLUE=(0,0,255)

YELLOW=(255,255,0)

#initializepygameandcreatewindow

pygame.init()

pygame.mixer.init()

screen=pygame.display.set_mode((WIDTH,HEIGHT))

pygame.display.set_caption("Shmup!")

clock=pygame.time.Clock()

classPlayer(pygame.sprite.Sprite):

def__init__(self):

pygame.sprite.Sprite.__init__(self)

self.image=pygame.Surface((50,40))

self.image.fill(GREEN)

self.rect=self.image.get_rect()

self.rect.centerx=WIDTH/2

self.rect.bottom=HEIGHT-10

self.speedx=0

defupdate(self):

self.speedx=0

keystate=pygame.key.get_pressed()

ifkeystate[pygame.K_LEFT]:

self.speedx=-8

ifkeystate[pygame.K_RIGHT]:

self.speedx=8

self.rect.x+=self.speedx

ifself.rect.rightWIDTH:

self.rect.right=WIDTH

ifself.rect.left0:

self.rect.left=0

defshoot(self):

bullet=Bullet(self.rect.centerx,self.rect.top)

all_sprites.add(bullet)

bullets.add(bullet)

classMob(pygame.sprite.Sprite):

def__init__(self):

pygame.sprite.Sprite.__init__(self)

self.image=pygame.Surface((30,40))

self.image.fill(RED)

self.rect=self.image.get_rect()

self.rect.x=random.randrange(WIDTH-self.rect.width)

self.rect.y=random.randrange(-100,-40)

self.speedy=random.randrange(1,8)

self.speedx=random.randrange(-3,3)

defupdate(self):

self.rect.x+=self.speedx

self.rect.y+=self.speedy

ifself.rect.topHEIGHT+10orself.rect.left-25orself.rect.rightWIDTH+20:

self.rect.x=random.randrange(WIDTH-self.rect.width)

self.rect.y=random.randrange(-100,-40)

self.speedy=random.randrange(1,8)

classBullet(pygame.sprite.Sprite):

def__init__(self,x,y):

pygame.sprite.Sprite.__init__(self)

self.image=pygame.Surface((10,20))

self.image.fill(YELLOW)

self.rect=self.image.get_rect()

self.rect.bottom=y

self.rect.centerx=x

self.speedy=-10

defupdate(self):

self.rect.y+=self.speedy

#killifitmovesoffthetopofthescreen

ifself.rect.bottom0:

self.kill()

all_sprites=pygame.sprite.Group()

mobs=pygame.sprite.Group()

bullets=pygame.sprite.Group()

player=Player()

all_sprites.add(player)

foriinrange(8):

m=Mob()

all_sprites.add(m)

mobs.add(m)

#Gameloop

running=True

whilerunning:

#keeplooprunningatthe

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論