Pygame 官方文档 - Tutorials - 逐行的黑猩猩教程(Line By Line Chimp)
逐行的黑猩猩教程(Line By Line Chimp)
作者: Pete Shinners
聯(lián)系方式: pete@shinners.org
介紹(Introduction)
? ? ? ?在pygame示例中,有一個(gè)名為“黑猩猩”的簡(jiǎn)單示例。這個(gè)例子模擬了一只可被打的猴子在一個(gè)小屏幕上走動(dòng),并且承諾有財(cái)富和回報(bào)。示例本身非常簡(jiǎn)單,并且在錯(cuò)誤檢查代碼上有點(diǎn)單薄。這個(gè)示例程序演示了許多pygame的功能,如創(chuàng)建圖形窗口,加載圖像和聲音文件,渲染TTF文本以及基本事件和鼠標(biāo)處理。
? ? ? ?這個(gè)程序和圖像可以在pygame的標(biāo)準(zhǔn)源代碼發(fā)布中找到。對(duì)于pygame的1.3版本,此示例已完全重寫,以添加更多功能并更正錯(cuò)誤檢查。這大約是原始示例大小的兩倍,但現(xiàn)在給我們提供了更多可查看的內(nèi)容,以及我可以建議您自己的項(xiàng)目可以重用的代碼。
本教程將逐塊瀏覽代碼。解釋代碼的工作原理。還將提到如何改進(jìn)代碼以及錯(cuò)誤檢查可以提供哪些幫助。
? ? ? ?這是一個(gè)很好的教程,特別對(duì)于第一次看到pygame代碼的人。一旦完全安裝了pygame,您就可以在examples目錄中找到并運(yùn)行自己的黑猩猩演示。
導(dǎo)入模塊(Import Modules)
這是將所有需要的模塊導(dǎo)入程序的代碼。 它還檢查一些可選的pygame模塊的可用性。
? ? ? ?首先,我們導(dǎo)入標(biāo)準(zhǔn)的“os”和“sys”python模塊。這些允許我們做一些事情,比如創(chuàng)建獨(dú)立于平臺(tái)的文件路徑
? ? ? ?在下一行中,我們導(dǎo)入pygame包。導(dǎo)入pygame時(shí),它會(huì)導(dǎo)入屬于pygame的所有模塊。一些pygame模塊是可選的,如果找不到它們,它們的值將設(shè)置為“None”。
? ? ? ?有一個(gè)名為“l(fā)ocals”的特殊pygame模塊。該模塊包含pygame的子集。該模塊的成員是常用的常量和函數(shù),已證明將其放入程序的全局命名空間中是有用的。這個(gè)locals模塊包括像“Rect”這樣的函數(shù)來(lái)創(chuàng)建一個(gè)矩形對(duì)象,以及許多常量,如“QUIT,HWSURFACE”,用于與其余的pygame交互。像這樣將locals模塊導(dǎo)入全局命名空間是完全可選的。如果您選擇不導(dǎo)入它,則局部作用域下的所有成員始終在pygame模塊中可用。
? ? ? ?最后,如果pygame中的字體或聲音模塊不可用,我們決定打印一條很棒的警告消息。
加載資源(Loading Resource)
這里我們有兩個(gè)函數(shù)可以用來(lái)加載圖像和聲音。 我們將在本節(jié)中單獨(dú)查看每個(gè)功能。
? ? ? ?此函數(shù)可以傳入要加載的圖像的名稱。它還可以選擇使用一個(gè)參數(shù)來(lái)設(shè)置圖像的顏色鍵。在圖形中使用顏色鍵來(lái)表示透明圖像的顏色。
此函數(shù)的第一件事是創(chuàng)建文件的完整路徑名。在此示例中,所有資源都位于“data”子目錄中。通過(guò)使用os.path.join函數(shù),將創(chuàng)建一個(gè)路徑名,該路徑名適用于運(yùn)行游戲的任何平臺(tái)。
? ? ? ?接下來(lái),我們使用pygame.image.load函數(shù)加載圖像。我們將此函數(shù)包裝在try / except塊中,因此如果加載圖像時(shí)出現(xiàn)問(wèn)題,我們可以正常退出。加載圖像后,我們對(duì)convert()函數(shù)進(jìn)行了重要調(diào)用。這將生成Surface的新副本并轉(zhuǎn)換其顏色格式和深度以匹配顯示。這意味著將圖像blitting 到屏幕將盡快的發(fā)生。
? ? ? ?最后,我們?yōu)閳D像設(shè)置了colorkey。如果用戶為colorkey參數(shù)提供了參數(shù),我們將該值用作圖像的顏色鍵。這通常只是一個(gè)顏色RGB值,如白色(255,255,255)。您還可以傳遞值-1作為顏色鍵。在這種情況下,該函數(shù)將在圖像的左上角像素處查找顏色,并將該顏色用于colorkey。
? ? ? ?接下來(lái)是加載聲音文件的功能。 這個(gè)函數(shù)做的第一件事是檢查是否正確導(dǎo)入了pygame.mixer模塊。 如果沒有,它返回一個(gè)虛擬播放方法(dummy play method)的小類實(shí)例。 這將足夠像一個(gè)正常的聲音對(duì)象使這個(gè)游戲運(yùn)行,沒有任何額外的錯(cuò)誤檢查。
? ? ? ?此函數(shù)類似于圖像加載功能,但處理一些不同的問(wèn)題。 首先,我們創(chuàng)建聲音圖像的完整路徑,并將聲音文件加載到try / except語(yǔ)句塊中。 然后我們只簡(jiǎn)單地返回加載的Sound對(duì)象。
游戲?qū)ο蟮念?#xff08;Game Object Classes)
? ? ? ?這里我們創(chuàng)建兩個(gè)類來(lái)表示游戲中的對(duì)象。 幾乎游戲的所有邏輯都進(jìn)入了這兩個(gè)類。 我們將在這里一次一個(gè)地查看它們。
? ? ? ?在這里我們創(chuàng)建一個(gè)代表玩家拳頭的類。它源生自pygame.sprite模塊中包含的Sprite類。創(chuàng)建此類的新實(shí)例時(shí),將調(diào)用__init__函數(shù)。我們要做的第一件事是確保為我們的基類調(diào)用__init__函數(shù)。這允許Sprite的__init__函數(shù)準(zhǔn)備我們的對(duì)象以用作精靈。這個(gè)游戲使用一個(gè)精靈繪圖組類(sprite drawing Group classes)。這些類可以繪制具有“image”和“rect”屬性的精靈。通過(guò)簡(jiǎn)單地更改這兩個(gè)屬性,渲染器(renderer)將在當(dāng)前位置繪制當(dāng)前圖像。
? ? ? ?所有精靈都有一個(gè)update()方法。此功能通常每幀調(diào)用一次。在這里你應(yīng)該放置代碼來(lái)移動(dòng)和更新sprite的變量。用于拳頭的update()方法將拳頭移動(dòng)到鼠標(biāo)指針的位置。如果拳頭處于“出拳”狀態(tài),它也會(huì)略微抵消拳頭位置。
? ? ? ?以下兩個(gè)函數(shù)punch()和unpunch()改變?nèi)^的出拳狀態(tài)。如果拳頭與給定的目標(biāo)精靈碰撞,則punch()方法也會(huì)返回true值。
? ? ? ?黑猩猩類的要做的工作比拳頭多一點(diǎn),但并沒有更加復(fù)雜。這個(gè)類將在屏幕上來(lái)回移動(dòng)黑猩猩。當(dāng)猴子被拳頭打中時(shí),他會(huì)旋轉(zhuǎn)到令人興奮的效果。這個(gè)類也源生自基礎(chǔ)的Sprite類,并初始化與拳頭類相同。在初始化時(shí),類還將屬性“area”設(shè)置為顯示屏幕的大小。
? ? ? ?黑猩猩的update函數(shù)只是查看當(dāng)前的“頭暈”狀態(tài),當(dāng)猴子被拳擊中旋轉(zhuǎn)時(shí)返回True。它調(diào)用_spin或_walk方法。這些函數(shù)以下劃線為前綴。這只是一個(gè)標(biāo)準(zhǔn)的python習(xí)語(yǔ),它表明這些方法只能由Chimp類使用。我們甚至可以給它們一個(gè)雙下劃線,這將告訴python真正嘗試使它們成為私有方法,但我們不需要這樣的保護(hù)。 ?
? ? ? ?walk方法通過(guò)將當(dāng)前rect移動(dòng)給定的偏移量來(lái)為猴子創(chuàng)建一個(gè)新位置。如果此新位置越過(guò)屏幕的顯示區(qū)域,則會(huì)反轉(zhuǎn)移動(dòng)偏移量。它還使用pygame.transform.flip函數(shù)鏡像圖像。這是一種粗糙的效果,使猴子看起來(lái)像是在轉(zhuǎn)動(dòng)他正在移動(dòng)的方向。
? ? ? ?當(dāng)猴子目前“頭暈”時(shí)調(diào)用spin方法。 dizzy屬性被用于存儲(chǔ)當(dāng)前的旋轉(zhuǎn)量。當(dāng)猴子一直旋轉(zhuǎn)(360度)時(shí),它會(huì)將猴子圖像重置回原始的非旋轉(zhuǎn)版本。在調(diào)用transform.rotate函數(shù)之前,您將看到代碼對(duì)名為“rotate”的函數(shù)進(jìn)行局部引用。對(duì)于這個(gè)例子沒有必要這樣做,這里只是為了保持以下行的長(zhǎng)度更短。請(qǐng)注意,調(diào)用旋轉(zhuǎn)功能時(shí),我們始終從原始猴子圖像旋轉(zhuǎn)。旋轉(zhuǎn)時(shí),質(zhì)量略有下降。反復(fù)旋轉(zhuǎn)相同的圖像,每次質(zhì)量都會(huì)變差。此外,旋轉(zhuǎn)圖像時(shí),圖像的大小實(shí)際上會(huì)發(fā)生變化。這是因?yàn)閳D像的角將旋轉(zhuǎn)出來(lái),使圖像更大。我們確保新圖像的中心與舊圖像的中心匹配,因此它不會(huì)移動(dòng)而旋轉(zhuǎn)。
? ? ? ?最后一個(gè)方法是punched(),它告訴精靈進(jìn)入其暈眩狀態(tài)。這將導(dǎo)致圖像開始旋轉(zhuǎn)。它還制作了名為“original”的當(dāng)前圖像的副本。
初始化所有東西(Initialize Everything)
? ? ? ?在我們可以對(duì)pygame做很多事情之前,我們需要確保它的模塊已初始化。 在這種情況下,我們還將打開一個(gè)簡(jiǎn)單的圖形窗口。 現(xiàn)在我們?cè)诔绦虻膍ain()函數(shù)中,它實(shí)際上運(yùn)行了所有東西。
? ? ? ?第一行的初始化pygame的為我們完成了一些工作。它檢查導(dǎo)入的pygame模塊并嘗試初始化它們中的每一個(gè)??梢苑祷夭z查模塊是否未能初始化,但我們不會(huì)在這里費(fèi)事。也可以采取更多控制并手動(dòng)初始化每個(gè)特定模塊。通常不需要這種類型的控制,但如果您愿意,可以使用。
? ? ? ?接下來(lái)我們?cè)O(shè)置顯示圖形模式。請(qǐng)注意,pygame.display模塊用于控制所有顯示設(shè)置。在這種情況下,我們要求一個(gè)簡(jiǎn)單的瘦窗口。有關(guān)于設(shè)置圖形模式的完整單獨(dú)教程,但如果我們真的不在乎, pygame會(huì)很好地為我們提供有用的東西。 Pygame將選擇最佳顏色深度,因?yàn)槲覀儧]有提供。
? ? ? ?最后我們?cè)O(shè)置窗口標(biāo)題并關(guān)閉窗口的鼠標(biāo)光標(biāo)。非常基本的事情,現(xiàn)在我們有一個(gè)小黑窗口準(zhǔn)備做我們的吩咐的事。通常光標(biāo)默認(rèn)為可見,因此除非我們想隱藏它,否則無(wú)需真正設(shè)置狀態(tài)。
創(chuàng)建背景(Create The Background)
? ? ? ?我們的程序在背景上有文本信息。 我們很高興創(chuàng)建一個(gè)surface對(duì)象來(lái)表示背景并重復(fù)使用它。
第一步是創(chuàng)建surface對(duì)象。
? ? ? ?這為我們創(chuàng)建了一個(gè)與顯示窗口大小相同的新surface對(duì)象。 注意創(chuàng)建Surface對(duì)象后額外調(diào)用convert()。 沒有參數(shù)的轉(zhuǎn)換將確保我們的背景與顯示窗口的格式相同,這將為我們提供最快的結(jié)果。
? ? ? ?我們還將整個(gè)背景填充為純白色。 填充采用RGB三元組作為顏色參數(shù)。
把文字放在背景上并居中(Put Text On The Background, Centered)
if pygame.font:font = pygame.font.Font(None, 36)text = font.render("Pummel The Chimp, And Win $$$", 1, (10, 10, 10))textpos = text.get_rect(centerx=background.get_width()/2) background.blit(text, textpos)? ? ? ?如您所見,完成此操作有幾個(gè)步驟。首先,我們必須創(chuàng)建字體對(duì)象并將其渲染到新的surface對(duì)象。然后我們找到新surface對(duì)象的中心并將其blit(粘貼)到背景上。
? ? ? ?使用字體模塊的Font()構(gòu)造函數(shù)創(chuàng)建字體。通常,您會(huì)將TrueType字體文件的名稱傳遞給此函數(shù),但我們也可以傳遞None,它將使用默認(rèn)字體。 Font構(gòu)造函數(shù)還需要知道我們想要?jiǎng)?chuàng)建的字體大小。
? ? ? ?然后,我們將該字體渲染為新的surface對(duì)象。render函數(shù)創(chuàng)建一個(gè)適合文本大小的新surface對(duì)象。在這種情況下,我們還告訴reander創(chuàng)建抗鋸齒文本(為了一個(gè)漂亮的光滑外觀)和使用深灰色。
? ? ? ?接下來(lái),我們需要在顯示屏上找到文本的居中位置。我們從文本尺寸創(chuàng)建一個(gè)“Rect”對(duì)象,這使我們可以輕松地將其分配給屏幕中心。
最后我們將文本blit(blit就像復(fù)制或粘貼)到背景圖像上。
設(shè)定完成后顯示背景(Display The Background While Setup Finishes)
我們屏幕上仍然有一個(gè)黑色的窗口。讓我們等待其他資源加載時(shí)顯示我們的背景。
? ? ? ?這會(huì)將我們的整個(gè)背景blit到顯示窗口上。 這個(gè)blit是不言自明的,但是這個(gè)翻轉(zhuǎn)(flip)行為呢?
? ? ? ?在pygame中,對(duì)用于顯示surface對(duì)象的更改不會(huì)立即可見。 通常,必須在已更改的區(qū)域中更新顯示以使其對(duì)用戶可見。 使用雙緩沖顯示器時(shí),必須交換(或翻轉(zhuǎn))顯示以使更改變得可見。 在這種情況下,flip()函數(shù)可以很好地工作,因?yàn)樗惶幚碚麄€(gè)窗口區(qū)域并處理單緩沖和雙緩沖表面。
準(zhǔn)備游戲?qū)ο?#xff08;Prepare Game Object)
在這里,我們創(chuàng)建了游戲所需的所有對(duì)象。
? ? ? ?首先,我們使用上面定義的load_sound函數(shù)加載兩個(gè)聲音效果。 然后我們創(chuàng)建每個(gè)sprite類的實(shí)例。 最后我們創(chuàng)建了一個(gè)sprite Group,它將包含我們所有的sprite。
? ? ? ?我們實(shí)際上使用了一個(gè)名為RenderPlain的特殊精靈組。 該精靈組可以將它包含的所有精靈繪制到屏幕上。 它被稱為RenderPlain,因?yàn)閷?shí)際上有更高級(jí)的Render組。 但對(duì)于我們的游戲,我們只需要簡(jiǎn)單的繪圖。 我們通過(guò)傳遞一個(gè)包含應(yīng)該屬于該組的所有精靈的列表來(lái)創(chuàng)建名為“allsprites”的組。 我們以后可以在這個(gè)組中添加或刪除精靈,但在這個(gè)游戲中我們不需要。
? ? ? ?我們創(chuàng)建的clock對(duì)象將用于幫助控制我們游戲的幀速率。 我們將在游戲的主循環(huán)中使用它,以確保它不會(huì)運(yùn)行得太快。
主循環(huán)(Main Loop)
這里沒什么,只是一個(gè)無(wú)限循環(huán)。
? ? ? ?所有游戲都以某種循環(huán)方式運(yùn)行。 通常的順序是檢查計(jì)算機(jī)的狀態(tài)和用戶輸入,移動(dòng)并更新所有對(duì)象的狀態(tài),然后將它們繪制到屏幕上。 你會(huì)看到這個(gè)例子并沒有什么不同。
? ? ? ?我們還調(diào)用了我們的clock對(duì)象,這將確保我們的游戲運(yùn)行速度不超過(guò)每秒60幀。
處理所有輸入事件(Update the Sprite)
這是處理事件隊(duì)列的極其簡(jiǎn)單的情況。
? ? ? ?首先,我們從pygame獲取所有可用的事件并循環(huán)遍歷每個(gè)事件。 前兩個(gè)測(cè)試查看用戶是否已退出游戲,或按下了退出鍵。 在這些情況下,我們只是從main()函數(shù)返回,程序干凈地結(jié)束。
? ? ? ?接下來(lái),我們只是檢查鼠標(biāo)按鈕是否被按下或釋放。 如果按下按鈕,我們?cè)儐?wèn)第一個(gè)物體是否與黑猩猩相撞。 我們播放適當(dāng)?shù)穆曇粜Ч?#xff0c;如果猴子被擊中,我們告訴他開始旋轉(zhuǎn)(通過(guò)調(diào)用它的punched()方法)。
更新Sprites(Update the Sprites)
allsprites.update()? ? ? ?Sprite組有一個(gè)update()方法,它只調(diào)用它包含的所有sprite的update方法。 每個(gè)物體都會(huì)四處移動(dòng),具體取決于它們處于哪種狀態(tài)。這是黑猩猩將一步一步向一側(cè)移動(dòng)的地方,或者如果他最近被打了一拳則旋轉(zhuǎn)得更遠(yuǎn)。
繪制整個(gè)場(chǎng)景(Draw The Entire Scene)
既然所有物體都在正確的位置,那么是時(shí)候繪制它們了。
? ? ? ?第一個(gè)blit調(diào)用將把背景繪制到整個(gè)屏幕上。 這會(huì)擦除我們從前一幀看到的所有內(nèi)容(效率稍低,但對(duì)于此游戲來(lái)說(shuō)足夠好)。 接下來(lái)我們調(diào)用sprite容器的draw()方法。 由于這個(gè)精靈容器實(shí)際上是“DrawPlain”精靈組的一個(gè)實(shí)例,它知道如何繪制我們的精靈。 最后,我們將pygame的軟件雙緩沖區(qū)的內(nèi)容flip()到屏幕上。 這使得我們繪制的所有內(nèi)容都可以同時(shí)顯示。
游戲結(jié)束(Game Over)
? ? ? ?用戶已退出,是時(shí)候清理干凈了。在pygame中清理正在運(yùn)行的游戲非常簡(jiǎn)單。 事實(shí)上,由于所有變量都被自動(dòng)破壞,我們真的不需要做任何事情。
?
以上內(nèi)容,自己翻譯,可能有誤,可參考:Tutorials - 逐行的黑猩猩教程(Line By Line Chimp)
點(diǎn)我回頂部 ?
?
?
?
?
?
?
?
Fin.
總結(jié)
以上是生活随笔為你收集整理的Pygame 官方文档 - Tutorials - 逐行的黑猩猩教程(Line By Line Chimp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 中国乡镇企业会计杂志中国乡镇企业会计杂志
- 下一篇: 开源即时通讯软件