Pygame 教程(6):使用精灵
本章,你將學(xué)習(xí)如何使用 Pygame 中的精靈。
導(dǎo)航
上一章:監(jiān)測(cè)游戲時(shí)間
文章目錄
- 導(dǎo)航
- 精靈
- Sprite
- Group
- 碰撞檢測(cè)函數(shù)
- 實(shí)例:彈球
- 創(chuàng)建精靈
- 使用精靈
- 完整代碼
- 結(jié)語(yǔ)(很重要!!)
精靈
當(dāng)游戲?qū)ο笞兊梅倍嗟臅r(shí)候,把所有游戲?qū)ο蟮奶幚泶娣旁谝粋€(gè)個(gè)函數(shù)中,雖然是一種可行的方法,但是會(huì)使代碼邏輯比較混亂,難以維護(hù)。這時(shí),精靈(sprite) 應(yīng)運(yùn)而生。使用精靈,可以將游戲?qū)ο蠓庋b到一個(gè)個(gè)類當(dāng)中,以將處理游戲?qū)ο蟮倪壿嬇c主代碼邏輯分離開,使代碼架構(gòu)更加清晰明了。
Pygame 中,通過(guò)pygame.sprite模塊使用精靈。該模塊定義了Sprite類(用于定義精靈)和Group類(用于管理精靈的容器)以及一些繼承于這兩個(gè)類的拓展類和檢測(cè)精靈碰撞的函數(shù)。
下面將主要介紹Sprite和Group類,以及常用的檢測(cè)碰撞的函數(shù)。
Sprite
pygame.sprite.Sprite通常作為可見(jiàn)游戲?qū)ο蟮幕悺?gòu)造函數(shù)Sprite(*groups) -> Sprite接受任意數(shù)量的Group容器以添加到這些容器中。
繼承它的子類需要為image和rect屬性賦值。image屬性是一個(gè)pygame.Surface對(duì)象,指定該游戲?qū)ο蟮膱D像。rect屬性是一個(gè)pygame.Rect對(duì)象,用于指定該游戲?qū)ο蟮奈恢?#xff0c;也用于檢測(cè)精靈碰撞而使用。
Sprite類中定義的方法如下表(詳見(jiàn)官方文檔):
| update(*args, **kwargs) -> None | 用于控制精靈行為的方法,通常子類需要重寫該方法。當(dāng)調(diào)用了Group.update方法時(shí),組中的所有精靈都會(huì)被調(diào)用Sprite.update方法,如果在Group.update方法中傳入了參數(shù),參數(shù)也將被傳入Sprite.update方法中。 |
| add(*groups) -> None | 任意數(shù)量的Group對(duì)象作為參數(shù)傳遞,精靈將被添加到尚未成為成員的組中。 |
| remove(*groups) -> None | 任意數(shù)量的Group對(duì)象作為參數(shù)傳遞,精靈將從它所在的組中移除。 |
| kill() -> None | 將精靈從所有包含它的組中移除,這并不會(huì)改變本身的狀態(tài),之后也可以繼續(xù)使用該精靈。 |
| alive() -> bool | 判斷此精靈是否屬于1個(gè)或多個(gè)組。 |
| groups() -> group_list | 返回包含此精靈的Group對(duì)象的列表。 |
Group
pygame.sprite.Group類通常作為用于管理多個(gè)Sprite對(duì)象的容器。此類也可以被繼承以創(chuàng)建有更具體行為的容器。構(gòu)造函數(shù)Group(*sprites) -> Group接受任意數(shù)量的Sprite對(duì)象作為參數(shù)以添加到容器中。Group類還支持以下標(biāo)準(zhǔn)的 Python 操作:
- in,判斷是否包含了某個(gè)精靈。
- len,獲取組中的精靈總數(shù)。
- bool,判斷組中是否包含任何精靈。
- iter,迭代組中所有的精靈。
Group類中定義的方法如下表(詳見(jiàn)官方文檔):
| sprites() -> sprite_list | 返回組中包含的所有精靈的列表。 |
| copy() -> Group | 創(chuàng)建該組的副本。 |
| add(*sprites) -> None | 向組中添加任意數(shù)量的精靈,只添加尚未成為改組成員的精靈。 |
| remove(*sprites) -> None | 從組中刪除任意數(shù)量的精靈。只刪除是該組成員的精靈。 |
| has(*sprites) -> bool | 判斷組中是否包含給定的所有精靈。 |
| update(*args, **kwargs) -> None | 對(duì)組中所有的精靈調(diào)用Sprite.update方法,被傳入Group.update方法的參數(shù)也將傳入Sprite.update方法中。 |
| draw(Surface) -> List[Rect] | 將組中包含的所有精靈繪制到給定的圖像上,使用每個(gè)精靈的image屬性作為源圖像,rect屬性作為位置。Group并不保存精靈的順序,所以繪制順序是任意的。 |
| clear(Surface_dest, background) -> None | 在給定的圖像上清除上次調(diào)用Group.draw方法所使用的精靈,通過(guò)在對(duì)應(yīng)精靈的位置上進(jìn)行填充來(lái)清除。參數(shù)background通常是一個(gè)Surface圖像,要求尺寸與目標(biāo)圖像相同,但是也可以是一個(gè)回調(diào)函數(shù),需要兩個(gè)參數(shù):目標(biāo)圖像和要清除的區(qū)域。 |
| clear(Surface_dest, background) -> None | 從組中移除所有的精靈。 |
碰撞檢測(cè)函數(shù)
sprite模塊中還定義了一些碰撞檢測(cè)函數(shù)。以下內(nèi)容將介紹常用的函數(shù)(詳見(jiàn)官方文檔)。
spritecollide(sprite, group, dokill, collided = None) -> Sprite_list:返回一個(gè)組中與一個(gè)精靈相交的所有的精靈的列表。布爾參數(shù)dokill指定是否將所有將組中所有碰撞的精靈刪除。可選的參數(shù)collided是一個(gè)回調(diào)函數(shù),用于計(jì)算兩個(gè)精靈是否碰撞,它應(yīng)該把兩個(gè)精靈作為參數(shù),并返回一個(gè)布爾值,表明是否相撞。如果沒(méi)有傳遞collided參數(shù),則所有精靈都要求有rect屬性,用于計(jì)算碰撞。collided可以傳入的 Pygame 內(nèi)置函數(shù)有:collide_rect,collide_rect_ratio,collide_circle,collide_circle_ratio,collide_mask。
collide_rect(left, right) -> bool:使用pygame.Rect.collide_rect方法檢測(cè)兩個(gè)精靈之間的碰撞,要求兩個(gè)精靈都有rect屬性。
collide_rect_ratio(ratio) -> collided_callable:一個(gè)可調(diào)用的類,collide_rect函數(shù)的可縮放版本,初始化時(shí)傳入一個(gè)比率。
collide_circle(left, right) -> bool:通過(guò)檢測(cè)以精靈為中心的兩個(gè)圓是否重疊來(lái)檢測(cè)碰撞。如果精靈有radius屬性,將被用來(lái)創(chuàng)建圓,否則,將創(chuàng)建一個(gè)足夠大的圓完全包圍精靈的rect屬性。兩個(gè)精靈必須有rect屬性和可選的radius屬性。
collide_circle_ratio(ratio) -> collided_callable:一個(gè)可調(diào)用的類,collide_circle函數(shù)的可縮放版本,初始化時(shí)傳入一個(gè)比率。
groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict:參數(shù)與spritecollide函數(shù)類似,找到所有在兩組之間發(fā)生碰撞的精靈。group1中的所有精靈將添加為返回字典的鍵,而每個(gè)鍵對(duì)應(yīng)的值就是group2中與該精靈發(fā)生碰撞的精靈列表。
spritecollideany(sprite, group, collided = None) -> Sprite | None:簡(jiǎn)單測(cè)試精靈是否與組中任何一個(gè)精靈相撞,如果有碰撞,將返回組中的一個(gè)精靈,否則,返回None。
實(shí)例:彈球
本實(shí)例將利用Sprite創(chuàng)建一個(gè)彈球引用程序。
請(qǐng)創(chuàng)建一個(gè)新的文件,命名為ball.py,并添加以下代碼:
import sysimport pygameclass BallGame:def __init__(self) -> None:self.screen = pygame.display.set_mode((600, 600))pygame.display.set_caption('Ball')def run(self):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()pygame.display.flip()if __name__ == '__main__':game = BallGame()game.run()創(chuàng)建精靈
我們需要?jiǎng)?chuàng)建一個(gè)繼承于Sprite類的精靈類Ball,在BallGame之前添加如下代碼:
class Ball(pygame.sprite.Sprite):def __init__(self, screen_rect) -> None:super().__init__()self.image = pygame.Surface((20, 20))pygame.draw.circle(self.image, (255, 255, 255), (10, 10), 10)self.screen_rect = screen_rectself.rect = self.image.get_rect()self.rect.center = self.screen_rect.centerself.vel = (2, 1)def update(self):self.rect.x += self.vel[0]self.rect.y += self.vel[1]if self.rect.left < 0 or self.rect.right > self.screen_rect.width:self.vel = (-self.vel[0], self.vel[1])if self.rect.top < 0 or self.rect.bottom > self.screen_rect.height:self.vel = (self.vel[0], -self.vel[1])上述代碼中,Ball類繼承于Sprite類,以定義一個(gè)精靈,并且使用pygame.draw.circle函數(shù)在image上繪制了一個(gè)白色的圓,同時(shí)將rect定位到屏幕矩形的中心。
update方法中,更新了rect的位置,并防止球超出屏幕范圍。
使用精靈
更改BallGame類的方法,代碼如下:
class BallGame:def __init__(self) -> None:self.screen = pygame.display.set_mode((600, 600))pygame.display.set_caption('Ball')self.ball = Ball(self.screen.get_rect())def run(self):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()self.screen.fill((0, 0, 0))self.ball.update()self.screen.blit(self.ball.image, self.ball.rect)pygame.display.flip()這里并沒(méi)有使用Group來(lái)組織精靈,是因?yàn)槲覀冎皇褂昧艘粋€(gè)精靈,無(wú)需使用它。
完整代碼
import sysimport pygameclass Ball(pygame.sprite.Sprite):def __init__(self, screen_rect) -> None:super().__init__()self.image = pygame.Surface((20, 20))pygame.draw.circle(self.image, (255, 255, 255), (10, 10), 10)self.screen_rect = screen_rectself.rect = self.image.get_rect()self.rect.center = self.screen_rect.centerself.vel = (2, 1)def update(self):self.rect.x += self.vel[0]self.rect.y += self.vel[1]if self.rect.left < 0 or self.rect.right > self.screen_rect.width:self.vel = (-self.vel[0], self.vel[1])if self.rect.top < 0 or self.rect.bottom > self.screen_rect.height:self.vel = (self.vel[0], -self.vel[1])class BallGame:def __init__(self) -> None:self.screen = pygame.display.set_mode((600, 600))pygame.display.set_caption('Ball')self.ball = Ball(self.screen.get_rect())def run(self):while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()self.screen.fill((0, 0, 0))self.ball.update()self.screen.blit(self.ball.image, self.ball.rect)pygame.display.flip()if __name__ == '__main__':game = BallGame()game.run()代碼運(yùn)行截圖:
結(jié)語(yǔ)(很重要!!)
至此,Pygame 教程已經(jīng)結(jié)束啦🎉🎉!!!通過(guò)此教程,你已經(jīng)學(xué)會(huì)了 Pygame 的基礎(chǔ)知識(shí)。你已經(jīng)可以嘗試自己編寫簡(jiǎn)單的應(yīng)用了。筆者也會(huì)努力更新,爭(zhēng)取寫出更多好的作品。
總結(jié)
以上是生活随笔為你收集整理的Pygame 教程(6):使用精灵的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [太原理工大学] 2023 信息安全技术
- 下一篇: ALP300智能型低压马达保护器