激情六月丁香婷婷|亚洲色图AV二区|丝袜AV日韩AV|久草视频在线分类|伊人九九精品视频|国产精品一级电影|久草视频在线99|在线看的av网址|伊人99精品无码|午夜无码视频在线

高校合作1:010-59833514 ?咨詢(xún)電話(huà):400-810-1418 服務(wù)與監(jiān)督電話(huà):400-810-1418轉(zhuǎn)接2

python微信小游戲開(kāi)發(fā)(從零開(kāi)發(fā)一個(gè)小游戲:PyGame入門(mén))

發(fā)布時(shí)間:2023-11-27 11:12:42 瀏覽量:156次

?從零開(kāi)發(fā)一個(gè)小游戲:PyGame入門(mén)

python微信小游戲開(kāi)發(fā)(從零開(kāi)發(fā)一個(gè)小游戲:PyGame入門(mén))

編程派微信號(hào):codingpy

編程派堅(jiān)信,這個(gè)時(shí)代人人都學(xué)點(diǎn)編程,不論對(duì)自身成長(zhǎng)還是日常工作,都將有巨大益處。因此,選擇了通過(guò)本公號(hào)與大家分享最易學(xué)的編程語(yǔ)言 Python 的教程和資源,希望對(duì)你有幫助。

今天分享的是 Python 翻譯組 最新譯文,原文來(lái)自real python,是一篇比較詳細(xì)的 PyGame 游戲開(kāi)發(fā)入門(mén)指南。

譯者:haiyuqiao,華中科技大學(xué)(在讀研究生),正在使用 Python 做數(shù)據(jù)分析。Fighting from now!校對(duì):EarlGrey,編程派主頁(yè)君。

以下是正文,一起來(lái)學(xué)習(xí)吧。

PyGame是 SDL 庫(kù)的 Python 包裝器(wrapper)。SDL 是一個(gè)跨平臺(tái)庫(kù),支持訪(fǎng)問(wèn)計(jì)算機(jī)多媒體硬件(聲音、視頻、輸入等)。SDL 非常強(qiáng)大,但美中不足的是,它是基于 C 語(yǔ)言的,而 C 語(yǔ)言比較難懂,因此我們采用 PyGame 。

在本教程中,我們將介紹 PyGame 的基本邏輯和沖突檢測(cè),以及如何在屏幕上繪圖和將外部文件導(dǎo)入到游戲中。

準(zhǔn)備工作

打開(kāi)PyGame下載頁(yè)面,根據(jù)你的操作系統(tǒng)和 Python 版本下載合適的 PyGame 安裝包。如果你使用的是 Python 3,那么請(qǐng)下載 1.9.2 版.

新建一個(gè) .py 文件,然后輸入以下代碼:

與其他 Python 程序一樣,我們首先導(dǎo)入想要使用的模塊。這里,我們將導(dǎo)入 pygamepygame.locals ,后續(xù)我們將使用其中的一些常量。最后一行會(huì)初始化所有導(dǎo)入的 PyGame 模塊,在做其他操作之前必須執(zhí)行調(diào)用該函數(shù)。

基礎(chǔ)對(duì)象

屏幕對(duì)象

首先,我們需要一張畫(huà)布,我們稱(chēng)之為“屏幕”,它是我們繪畫(huà)的平臺(tái)。為了創(chuàng)建一個(gè)屏幕,我們需要調(diào)用pygame.display 中的 set_mode 方法,然后向 set_mode() 傳遞包含屏幕窗口寬度和高度的元組(本教程中使用 800x600 尺寸)。

screen = pygame.display.set_mode((800,600))

運(yùn)行上述代碼,將會(huì)彈出一個(gè)窗口,然后當(dāng)程序退出后又立即消失。一點(diǎn)都不酷嘛,對(duì)吧?下一節(jié),我們將介紹游戲的主循環(huán),它將確保只有在我們給它正確的輸入時(shí)程序才會(huì)退出。

游戲主循環(huán)

游戲主循環(huán)/事件循環(huán)是所有操作發(fā)生的地方。在游戲過(guò)程中,它不斷的更新游戲狀態(tài),渲染游戲畫(huà)面和收集輸入指令。創(chuàng)建循環(huán)時(shí),需要確保我們有辦法跳出循環(huán),退出應(yīng)用。為此,我們將同時(shí)介紹一些基本的用戶(hù)輸入指令。所有的用戶(hù)輸入(和我們稍稍后提到的其他事件)都會(huì)進(jìn)入 PyGame 的事件隊(duì)列,通過(guò)調(diào)用 pygame.event.get() 可以訪(fǎng)問(wèn)該隊(duì)列。這將返回一個(gè)包含隊(duì)列里所有事件的列表,我們將循環(huán)這個(gè)列表,并根針對(duì)相應(yīng)的事件類(lèi)型做出反應(yīng)?,F(xiàn)在我們只關(guān)心 KEYDOWNQUIT 事件:

將上述代碼添加到之前的代碼下,并運(yùn)行。你應(yīng)該看到一個(gè)空的窗口。只有你按下 ESC 鍵 或者觸發(fā)一個(gè) QUIT 事,否則這個(gè)窗口不會(huì)消失。

Surface 和 Rects

SurfaceRects是 PyGame 中的基本構(gòu)件??梢詫?Surface 看作一張白紙,你可以在上面隨意繪畫(huà)。我們的屏幕對(duì)象也是一個(gè) Surface 。它們可以包含圖片。Rects 是 Surface 中矩形區(qū)域的表示。

讓我們創(chuàng)建一個(gè) 50x50 像素的 Surface,然后給它涂色。由于屏幕是黑色的,所以我們使用白色。 我們?nèi)缓笳{(diào)用 get_rect() 在 Surface上 得到一個(gè)矩形區(qū)域和 Surface 的 x 軸 和 y 軸。

Blit 和 Flip

僅僅只是創(chuàng)建了 Surface 并不能在屏幕上看到它。為此我們需要將這個(gè) Surface 繪制(Blit)到另一個(gè) Surface 上。Blit 是一個(gè)專(zhuān)業(yè)術(shù)語(yǔ),意思就是繪圖。你僅僅只能從一個(gè)Surface Blit 到另一個(gè)Surface,我們的屏幕就是一個(gè) Surface 對(duì)象。以下是我們?nèi)绾螌?surf 畫(huà)到屏幕上:

# 這一行表示:將surf畫(huà)到屏幕 x:400.y:300的坐標(biāo)上

screen.blit(surf,(400,300))pygame.display.flip()

blit() 有兩個(gè)參數(shù):要畫(huà)的 Surface 和 在源 Surface 上的坐標(biāo)。此處我們使用屏幕的中心,但是當(dāng)你運(yùn)行代碼時(shí),你會(huì)發(fā)現(xiàn)我們的 surf 并沒(méi)有出現(xiàn)在屏幕的中心。這是因?yàn)?blit() 是從左上角開(kāi)始畫(huà) surf 。

注意在 blit 之后的 pygame.display.filp() 的調(diào)用。Flip將會(huì)更新自上次 flip 后的整個(gè)屏幕,兩次 flip 之間發(fā)生的修改都將在屏幕上顯示。沒(méi)有調(diào)用flip()那就什么也不會(huì)出現(xiàn)。

Sprites

什么是 Sprites ?從編程術(shù)語(yǔ)來(lái)講,Sprites 是屏幕上事物的二維表達(dá)。本質(zhì)上來(lái)講,Sprite 就是一個(gè)圖片。Pygame 提供一個(gè)叫做 Sprites 的基礎(chǔ)類(lèi),它就是用來(lái)擴(kuò)展的,可以包含想要在屏幕上呈現(xiàn)的對(duì)象一個(gè)或多個(gè)圖形表示。我們將會(huì)擴(kuò)展Sprite 類(lèi),這樣可以使用它的內(nèi)建方法。我們稱(chēng)這個(gè)新的對(duì)象為 Player 。Plyaer 將擴(kuò)展 Sprite,現(xiàn)在只有兩個(gè)屬性:surfrect。我們也會(huì)給 surf 涂色(本教程使用白色),如之前 surface 例子,只是現(xiàn)在 Surface 屬于 Player :

現(xiàn)在我們將上述代碼整合在一起:

運(yùn)行上述代碼,你將會(huì)在屏幕中心看到一個(gè)白色的矩形:

如果將 screen.blit(player.surf,(400,300)) 改成 screen.blit(player.surf,player.rect) ,你覺(jué)得會(huì)發(fā)生什么?修改之后,試著在控制臺(tái)中打印 player.rect 。rect 的前兩個(gè)屬性分別是 rect 左上角的 x 和 y 軸坐標(biāo)。當(dāng)你將 rect 傳遞給 blit ,它將會(huì)根據(jù)這個(gè)坐標(biāo)畫(huà) surface 。我們后續(xù)將使用它控制 player 移動(dòng)。

用戶(hù)輸入

現(xiàn)在開(kāi)始才是有趣的部分。我們要把 Player 變得可控制!之前我們提過(guò),按鍵事件 pygame.event.get() 將把最新的事件從事件堆(event stack)中移除。Pygame 還有另外一個(gè)事件方法,pygame.event.get_pressed()。get_pressed()方法返回一個(gè)隊(duì)列,其中包含了所有按鍵事件組成的字典,我們將把它放在主循環(huán)中,這樣我們將在每一幀上的按鍵。

pressed_keys = pygame.event.get_presssed()

現(xiàn)在我們將寫(xiě)一個(gè)方法,接收上面那個(gè)字典,并且根據(jù)按下的鍵定義 sprite 的行為,代碼如下:

K_UP、K_DOWN、K_LEFTK_RIGHT 對(duì)應(yīng)鍵盤(pán)上的上、下、左 右方向鍵。我們判斷這些鍵是否按下,如果它為真,那么我們就朝相應(yīng)的方向移動(dòng) rect()。Rects 有兩個(gè)內(nèi)建的移動(dòng)方法,此處我們使用 move in place move_ip() ,因?yàn)槲覀兿M苿?dòng) rect 并且不用復(fù)制它。

將上述方法添加到 Player 類(lèi),將 get_pressed() 調(diào)用放在主循環(huán)中。整體代碼現(xiàn)在應(yīng)該是這樣的:

現(xiàn)在你可以使用方向鍵移動(dòng)矩陣塊了。也許你注意到了,你可以將矩形塊移出屏幕,這可能并不是你想要的。所以我們我們需要往 update 方法中添加一些邏輯,檢測(cè)矩形的坐標(biāo)是否移出了 800x600 的屏幕邊界;如果出了邊界,那么就將它放回在邊界上:

上述代碼沒(méi)有使用 move 方法,我們只要修改 上下左右的相應(yīng)坐標(biāo)即可。

現(xiàn)在我們添加一些敵人!

首先我們創(chuàng)建一個(gè)新的 sprite 類(lèi),命名為 Enemy。依照創(chuàng)建 player 的格式創(chuàng)建:

以上有幾點(diǎn)需要說(shuō)明。首先,當(dāng)我們?cè)?surface 上調(diào)用 get_rect 時(shí),我們將核心屬性 x 設(shè)為 820 ,y 的坐標(biāo)為一個(gè)隨機(jī)數(shù),由 random.randint() 生成。

在最終的代碼中,我們會(huì)在文件的開(kāi)頭導(dǎo)入 Random 庫(kù)(import random)。為什么選擇隨機(jī)數(shù)?因?yàn)槲覀兿M麛橙藦钠聊挥疫叄?20)的隨機(jī)位置(0-600)上出現(xiàn)。 我們還將使用 random 設(shè)置敵人的速度屬性,這樣敵人就會(huì)有快有慢。

敵人的 update() 方法沒(méi)有參數(shù)限制(我們不關(guān)心敵人的輸入),只要讓它向著屏幕左邊以一定的速度移動(dòng)就可以了。update 方法中的最后一個(gè) if 語(yǔ)句檢測(cè)敵人右側(cè)是否通過(guò)了屏幕左邊邊界(要確保它們不會(huì)一碰到屏幕的邊界就消失)。當(dāng)他們通過(guò)屏幕的邊界后,我們調(diào)用 Sprite 的內(nèi)建方法 kill(),從 sprite 組中刪除它們,這樣它們就不會(huì)再被渲染出來(lái)。kill 不會(huì)釋放被它們占用的內(nèi)存, 需要你確保你不再引用它們,以便 Python 的垃圾回收器回收。

Groups

Pygame 提供的另一個(gè)很有用的對(duì)象是 Sprite 的 Groups。誠(chéng)如其名,是 Sprite 的集合。為什么我們要使用 sprite.Group 而不是列表呢? 因?yàn)?sprite.Group 有一些內(nèi)建的方法,有助于解決沖突和更新問(wèn)題。那現(xiàn)在就創(chuàng)建一個(gè) Group,用來(lái)包含游戲中的所有 Sprites 。創(chuàng)建完 Group 后,我們要將 Player 添加到里面,因?yàn)樗俏覀兡壳拔ㄒ坏?Sprite 。我們也可以為敵人創(chuàng)建一個(gè) group 。 當(dāng)我們調(diào)用 Sprite 的 kill() 方法時(shí),sprite 將會(huì)從其所在的全部 group 中刪除。

python微信小游戲開(kāi)發(fā)(從零開(kāi)發(fā)一個(gè)小游戲:PyGame入門(mén))

enemies = pygame.sprite.Group()

all_sprites = pygame.sprite.Group()

all_sprites.add(player)

現(xiàn)在有了 all_sprites 的 group ,我們接著改變對(duì)象渲染方式,只要渲染 group 中的所有對(duì)象即可:

現(xiàn)在,任何放到 all_sprites 中的對(duì)象都會(huì)被渲染出來(lái)。

自定義事件

現(xiàn)在我們?yōu)閿橙藙?chuàng)建了一個(gè) sprite.Group ,但是并沒(méi)有實(shí)際的敵人。那怎樣才能在屏幕上出現(xiàn)敵人呢?我們當(dāng)然可以在剛開(kāi)始的時(shí)候創(chuàng)建一堆的敵人,但是這樣游戲玩不了幾秒。為此,我們創(chuàng)建一個(gè)自定義事件,它隔幾秒鐘就會(huì)觸發(fā)創(chuàng)建一批敵人。我們要監(jiān)聽(tīng)該事件,方式和監(jiān)聽(tīng)按鍵或退出事件一樣。創(chuàng)建自定義事件十分容易,只要命名即可:

ADDENEMY = pygame.USEREVENT +1

這樣就可以了!現(xiàn)在,我們有了一個(gè)叫做 ADDENEMY的事件,可以在主程序中監(jiān)聽(tīng)它。這里我們只需要注意一點(diǎn),即自定義事件需要有一個(gè)獨(dú)特的值,要比 USEREVENT 的值大,這就是我們?yōu)槭裁丛O(shè)定它為 USEREVENT + 1。這里說(shuō)明一點(diǎn):自定義事件本質(zhì)上就是整數(shù)常量。又因?yàn)楸?USEREVENT 小的數(shù)值已經(jīng)被內(nèi)置函數(shù)占據(jù),所以創(chuàng)建的任何自定義事件都要比 USEREVENT大。

定義好事件之后,我們需要將它插入事件隊(duì)列中。因?yàn)檎麄€(gè)游戲過(guò)程中都要?jiǎng)?chuàng)建它們,所以將設(shè)置一個(gè)計(jì)時(shí)器。可以通過(guò) PyGame 的 time() 對(duì)象實(shí)現(xiàn)。

pygame.time.set_timer(ADDENEMY,250)

這行代碼告訴 PyGame 每隔 250 毫秒(四分之一秒) 觸發(fā)一次 ADDENEMY 事件。這是在主游戲循環(huán)之外執(zhí)行的,不過(guò)在整個(gè)游戲中都處于執(zhí)行狀態(tài)。現(xiàn)在我們添加一些監(jiān)聽(tīng)事件的代碼:

現(xiàn)在我們會(huì)監(jiān)聽(tīng)ADDENEMY事件,當(dāng)它觸發(fā)時(shí),將創(chuàng)建一個(gè) Enemy類(lèi)的實(shí)例。然后我們將實(shí)例添加到enemies 這個(gè) Sprite Group(后續(xù)用它來(lái)檢測(cè)沖突)和 all_sprites Group(這樣它會(huì)和其他對(duì)象一起渲染)。

沖突

這才是 PyGame 的魅力所在!寫(xiě)沖突代碼(collision code)很難,但是 PyGame 提供了很多沖突檢測(cè)方法,你可以在這里查看其中一部分。本次教程使用 spritecollideany。spritecollideany() 接受一個(gè) Sprite 對(duì)象和一個(gè) Sprite.Group ,檢測(cè) Sprite 對(duì)象是否和 Sprite Group 中的其他 Sprites 沖突。這樣,我們可以拿 Player 和敵人所在的 Sprite Group 對(duì)比,檢測(cè) player 是否被敵人擊中。代碼實(shí)現(xiàn)如下:

檢測(cè) player 是否 enemies 中的 Sprites 沖突,如果發(fā)生沖突了,那么調(diào)用 player Sprite 的 kill() 方法。因?yàn)槲覀冎讳秩玖?all_sprites Group 中的 sprites ,kill() 方法將從其所在的全部 Groups 中移出 Sprite ,player就不再出現(xiàn),算是“殺死它了”。目前的完整代碼如下:

測(cè)試一下!

圖片

現(xiàn)在游戲可以玩了,但是長(zhǎng)得挺丑的。接下來(lái),我們將白色方塊變成有意思的圖片,讓游戲看上去有游戲的樣子。

前面的代碼示例中,我們使用了涂色的 Surface 對(duì)象表示游戲里的所有事物。雖然這樣有助于理解什么是 Surface 和它如何工作,但是卻讓游戲變得很丑!現(xiàn)在我們要給 player 和 enemy 添加一些圖片。我喜歡自己畫(huà)圖,我把 player 畫(huà)成小飛機(jī),enemy 是導(dǎo)彈,這些可以從我的代碼庫(kù)中下載。歡迎你使用我的作品,自己畫(huà)或者者下載一些免費(fèi)游戲素材。

修改對(duì)象的構(gòu)造函數(shù)

下面是我們現(xiàn)在的 player 構(gòu)造函數(shù):

新的構(gòu)造函數(shù)將會(huì)是這個(gè)樣子的:

我們想用一張圖片替代 Surface 對(duì)象。我們將使用 pygame.image.load() 導(dǎo)入圖片的路徑。load() 方法將會(huì)返回一個(gè) Surface 對(duì)象。我們?nèi)缓笤谶@個(gè) Surface 對(duì)象上調(diào)用 convert() 創(chuàng)建副本,這樣可以更快地將它畫(huà)在屏幕上。

接下來(lái),我們?cè)趫D片上調(diào)用 set_colorkey() 方法。set_colorkey用于設(shè)置圖片的顏色,如果不設(shè)置 Pygame 會(huì)將圖片設(shè)置為透明。這里我選用白色,因?yàn)楹惋w機(jī)的背景色一致。RLEACCEL 是一個(gè)可選參數(shù),它有助于 PyGame 在非加速顯示器上更快地渲染。

最后,我們和之前一樣調(diào)用 rect() 對(duì)象:在圖片上調(diào)用 get_rect()。

對(duì) enemy 構(gòu)造函數(shù)做同樣的操作:

現(xiàn)在的游戲雖然和以前一樣,但是比之前漂亮多啦!但是我仍然覺(jué)得它少了點(diǎn)什么東西。讓我們加點(diǎn)不斷漂浮的白云,這樣會(huì)有飛機(jī)劃過(guò)藍(lán)天的感覺(jué)。為此,我們需要遵循之前用過(guò)的一些原則。首先,我們創(chuàng)建 cloud 對(duì)象,畫(huà)上白云的照片,其 update() 方法讓它不停地向著屏幕左邊移動(dòng)。然后,我們需要添加一個(gè)自定義事件,每隔一段時(shí)間就生成白云(我們還要將添加白云到 all_spritesgroup)。白云對(duì)象的實(shí)現(xiàn)如下:

上面的代碼看起來(lái)都很熟悉,下面這個(gè)事件創(chuàng)建代碼也一樣,我們將它放在 enemy 事件代碼下面:

ADDCLOUD = pygame.USEREVENT+2

pygame.time.set_timer(ADDCLOUD,1000)

現(xiàn)在為它們創(chuàng)建一個(gè)新的 Sprite.Group:

clouds = pygame.sprite.Group()

現(xiàn)在,在主循環(huán)中,我們需要開(kāi)始監(jiān)聽(tīng)ADDCLOUD事件。

下面的代碼:

將會(huì)變成這樣:

我們還要把 clouds 添加到 all_sprites Group 和新的 clouds Group 中。我們這么做,是因?yàn)槲覀兪褂?all_sprites 來(lái)渲染,使用 clouds 調(diào)用它們的 update 函數(shù)。也許你很好奇,為什么我們將它不添加到 enemies Group中;畢竟我們調(diào)用的是一樣的 update 函數(shù)。原因在于,我們不想檢測(cè)白云和飛機(jī)之間的沖突。我們的飛機(jī)要順暢地通過(guò)所有的云層。現(xiàn)在剩下的就是調(diào)用 clouds Group 的 update() 方法了!

結(jié)語(yǔ)

大功告成!讓我們測(cè)試一下,效果應(yīng)該是這樣的:

完整代碼可以在 GitHub 上的代碼庫(kù)獲?。∠M窘坛虒?duì)你有用!

點(diǎn)此查看原文

Python 翻譯組是EarlGrey@編程派發(fā)起成立的一個(gè)專(zhuān)注于 Python 技術(shù)內(nèi)容翻譯的小組,目前已有近 30 名 Python 技術(shù)愛(ài)好者加入。

翻譯組出品的內(nèi)容(包括教程、文檔、書(shū)籍、視頻)將在編程派微信公眾號(hào)首發(fā),歡迎各位 Python 愛(ài)好者推薦相關(guān)線(xiàn)索。

推薦線(xiàn)索,直接在編程派微信公眾號(hào)推文下留言即可。


python微信小游戲開(kāi)發(fā)(從零開(kāi)發(fā)一個(gè)小游戲:PyGame入門(mén))

熱門(mén)課程推薦

熱門(mén)資訊

請(qǐng)綁定手機(jī)號(hào)

x

同學(xué)您好!

您已成功報(bào)名0元試學(xué)活動(dòng),老師會(huì)在第一時(shí)間與您取得聯(lián)系,請(qǐng)保持電話(huà)暢通!
確定