crossin-PyGame系列-12_第1頁
crossin-PyGame系列-12_第2頁
crossin-PyGame系列-12_第3頁
crossin-PyGame系列-12_第4頁
crossin-PyGame系列-12_第5頁
已閱讀5頁,還剩29頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、目錄 Pygame 第 1 課】 hello pygame . 1 Pygame 第2課】 游戲的本質(zhì) . 4 Pygame 第3課】 游戲中的事件 . 5 Pygame 第 4 課】 獲取鼠標(biāo)位置 . 7 Pygame 第5課】 游戲中的運(yùn)動(dòng) . 9 Pygame第6課】面向?qū)ο蟮挠螒蛟O(shè)計(jì) . 14 Pygame 第7課】 多變的宿敵 .17 Pygame 第8課】 火力全開 . 21 Pygame第9課】一大波飛機(jī) .25 Pygame 第10 課】 命中目標(biāo) . 27 Pygame 第 11 課】 GAME OVER . 29 Pygame第12課】 屢敗屢戰(zhàn) . 31 Pygame 第

2、 1 課】hello pygame 我們已經(jīng)把python的基本內(nèi)容講得差不多了, 所以從今天起,嘗試一下新的方面:pygame - 用python來寫游戲。 pygame是一個(gè)python的游戲庫,借助它,我們可以用 python寫一些小游戲。雖然你想用 它寫出一個(gè)魔獸世界那樣的游戲是不大可能的, 但它的確適合python學(xué)習(xí)者入手游戲開發(fā)。 安裝pygame python標(biāo)準(zhǔn)庫里是沒有包含 pygame的,所以我們需要去下載安裝它。去 上的downloads找到對應(yīng)你python版本的安裝包下載并安裝。 Mac用戶要注意一下,可能 你mac里默認(rèn)的python

3、版本無法于pygame兼容,需要去 重新下載安裝 python2.7 。 安裝完之后,可以在你的 python shell 里驗(yàn)證一下: 1. import pygame 2. pygame.ver 3. 1.9.1release pygame 的 hello world 照例,我們要用一個(gè) hello world 程序來開始我們的學(xué)習(xí)。 在寫代碼之前,先去找一張圖片,確定圖片的長寬值。我們要用它來做為背景圖片。 1. # -*- coding: utf-8 -*- 2. import pygame 3. #入 pygame庫 4. from sys import exit

4、 5. #向sys模塊借一個(gè)exit函數(shù)用來退出程序 6. pygame.init() 7. #初始化pygame,為使用硬件做準(zhǔn)備 8. screen = pygame.display.set_mode(600, 170), 0, 32) 9. 猊,建了一個(gè)窗口 ,窗口大小和背景圖片大小一樣 10. pygame.display.set_caption(Hello, World!) 11. #設(shè)置窗口標(biāo)題 12. background = pygame.image.load(bg.jpg).convert() 13. #加載并轉(zhuǎn)換圖像 14. while True: 15. #游戲主循環(huán) 1

5、6. for event in pygame.event.get(): 17. if event.type = pygame.QUIT: 18. #接收到退出事件后退出程序 19. pygame.quit() 20. exit() 21. screen.blit(background, (0,0) 22. #|背景圖畫上去 23. pygame.display.update() 24. #刷新一下畫面 運(yùn)行代碼。幸運(yùn)的話,你會(huì)看到一個(gè)有圖片背景的窗口, 不再是黑乎乎或者白花花的控制臺(tái) 了。以后,我們的游戲就會(huì)出現(xiàn)在這個(gè)窗口里。hello.py M U coding: utf-8 import

6、pygame #辱入pygame庫 i from sys import exit 。向sys模塊借一個(gè)exit函數(shù)用來退出程序 pygame.init() #初始化pygame,為使用硬件做準(zhǔn)備 screen = pygame.display.set_node(600, 170), 0, 32) #創(chuàng)建了一個(gè)窗口,窗口大小和背景圖片大小一樣 pygame.display.set_caption(MHello, World!) #設(shè)曾窗口標(biāo)題 background = pygame.image.Load(1bg.jpg1).convert。 #加載并轉(zhuǎn)換圖像 while True: #游戲主循環(huán)

7、 for event in pygame.event.get(): if eventtype = pygame.QUIT: 祥接收到退出事件后退出程序 pygame.quit() exit() screen.blit(background, (0,0) 。將背景圖畫上去 pygame.display.update() #刷野一下畫面 Python , Tab Width: 8 Ln 21 r Col 35 INS crossinnono:-/Dpsktop$ python hel1o.py there is no soundcard Pygame第2課】游戲的本質(zhì) 你小時(shí)候有沒有玩過這樣一種玩

8、具: 一塊硬紙,一面畫著一只鳥, 一面畫著一個(gè)籠子。 硬紙 下粘上一根細(xì)棒。用手來回轉(zhuǎn)動(dòng)細(xì)棒,讓硬紙的兩面快速交替出現(xiàn),就會(huì)看見鳥被關(guān)在了籠 子里。 這種現(xiàn)象被稱為視覺暫留,又稱余暉效應(yīng)。人眼的性質(zhì)使得光信號(hào)在進(jìn)入之后, 會(huì)保持一小 段時(shí)間,這段時(shí)間大約是 0.10.4秒。電影、動(dòng)畫便是利用這種現(xiàn)象得以實(shí)現(xiàn),把一幅幅靜 態(tài)畫面快速連續(xù)播放,形成看上去連續(xù)的活動(dòng)畫面。游戲也不例外。 回顧一下昨天的代碼,你會(huì)注意到有一個(gè) while True 的循環(huán),注釋為“游戲主循環(huán)”。這 就是游戲的主體部分。 每次循環(huán)都相當(dāng)于是一張靜態(tài)的畫面, 程序一直運(yùn)行,畫面就有了動(dòng) 態(tài)的效果。這個(gè)程序中還看不出,因?yàn)槭?/p>

9、終只有一張固定不動(dòng)的背景圖片。 與動(dòng)畫不同,游戲中不僅要把一幅幅畫面播放出來, 還需要處理玩家的操作與游戲中內(nèi)容的 交互。所以在這個(gè)while循環(huán)中,還要去接收玩家的輸入,以及處理游戲中的各種邏輯判斷、 運(yùn)動(dòng)、碰撞等等。 在我們程序的主循環(huán)里,做了對退出事件的響應(yīng): 1. for event in pygame.event.get(): 2. if event.type = pygame.QUIT: 3. #接收到退出事件后退出程序 4. pygame.quit() 5. exit() 然后把圖像繪制到窗口中: 1. screen.blit(background, (0,0) 最后,把整個(gè)窗口

10、畫面更新: 1. pygame.display.update() 如果你看過泥土動(dòng)畫,那么就可以把整個(gè)游戲過程想象成拍攝泥土動(dòng)畫的過程:每一次, screen.blit() 相當(dāng)于去把人偶、 布景移動(dòng)一點(diǎn)點(diǎn)位置, pygame.display.update() 則是按下 快門拍下一幀新的畫面。而 if event.type = pygame.QUIT: 就是在判斷,導(dǎo)演是不是喊停 收工了。這一切都由計(jì)算機(jī)在很短的時(shí)間內(nèi)處理,以至于玩家感覺是連貫的。 盡管我們只是從簡單的游戲做起,但在本質(zhì)上,絕大多數(shù)的游戲都是相通的。 有些大型3D游戲需要在一次循環(huán)內(nèi)做很多事情,需要進(jìn)行復(fù)雜的物理運(yùn)算、計(jì)算光線

11、的照 射效果、處理大量電腦角色的智能、 網(wǎng)絡(luò)信息通訊等。在配置不高的電腦上,這些計(jì)算花費(fèi) 的時(shí)間就多,游戲刷新畫面的頻率就變慢了。 這也就是我們常聽說“一個(gè)游戲的幀率低”的 原因,這種時(shí)候你就會(huì)感到游戲不流暢。Pygame第3課】 游戲中的事件 有人問,為什么突然講游戲了?有人問,為什么不繼續(xù)講 python的基礎(chǔ)?有人問,為什么 不講爬蟲?有人問,為什么不講算法?, 因?yàn)橛泻芏鄡?nèi)容,每一塊都有想聽的人。 因?yàn)橥瑫r(shí)不可能推送很多內(nèi)容。 因?yàn)槲蚁矚g游戲開 發(fā),制作一款游戲的過程很有趣。我會(huì)盡量在論壇上補(bǔ)充更多方面的內(nèi)容。 微信上的推送有 大生的限制,不能讓所有人滿足,大家見諒。 上次課講了游戲最

12、根本的框架, 說到在每次循環(huán)中會(huì)接收玩家的操作。 這是游戲中很重要的 一個(gè)環(huán)節(jié)-事件響應(yīng)。 玩家的操作會(huì)觸發(fā)程序中的事件,常見的事件包括:關(guān)閉程序、按下鍵盤、移動(dòng)鼠標(biāo)、按下 鼠標(biāo)等等。今天我們挑其中一個(gè)來舉例說明:“鼠標(biāo)按下”事件( MOUSEBUTTONDOWN 還記得上次課中的這段代碼嗎: 1. for event in pygame.event.get(): 2. if event.type = pygame.QUIT: 3. #接收到退出事件后退出程序 4. pygame.quit() 5. exit() 復(fù)制代碼 它就是一段事件響應(yīng)的處理代碼。 pygame.event.get()

13、會(huì)接收所有程序中的事件。當(dāng)判斷這 個(gè)事件是一個(gè)關(guān)閉程序(QUIT)的事件時(shí),就將程序關(guān)閉。 現(xiàn)在,我們要增加一個(gè)事件響應(yīng):當(dāng)玩家點(diǎn)擊了鼠標(biāo)之后,就換一張背景圖。 在for循環(huán)中新增一段if語句: 1. if event.type = pygame.MOUSEBUTTONDOWN: 2. #接收到鼠標(biāo)按下事件后更換背景 3. background = pygame.image.load(bg2.jpg).convert() 復(fù)制代碼 pygame.image.load().convert() 是將圖片文件讀入程序,后面的 .convert() 可以省略。 運(yùn)行程序,在窗口上點(diǎn)擊鼠標(biāo),背景會(huì)變成

14、bg2.jpg的圖案。為了顯示效果,最好使用和 bg.jpg長寬一樣的圖片。 Hellol World! Untitled Document 1 X hello.py X # codtng: utf8 inport pygame 律導(dǎo)入pyganeJJ. fron sys inport exit 律向打s模塊借一個(gè)彌It函數(shù)用來退出程序 pyganeAntt() #初始化pygE j為使用硬件微準(zhǔn)備 screen = pygane.display.set_node(6691 179), 9, 32) #創(chuàng)建了一個(gè)窗口,窗口大小和背景圖片大小一樣 pygane-display.set_C3pti

15、on(Hello, wo rid iu) 律技置窗口標(biāo)題 background = pygame.inage.load(*bg Jpg),convert() 養(yǎng)加栽并轉(zhuǎn)換圖像 white True: #游戲主循環(huán) for event in pygame.event.get(): tf event.type = pygane.QUIT: #接收到退出事件后退出程序 pygame.quit() exitC) f event * type = pygame * HOUSEBUTTONDOWN: 沖接收到鼠標(biāo)按下事件后更換背景 background - pygame Aoad(* bg2* jpg 1

16、)* convert() screen * blit(bckground( (0jO) 群將背景圖畫上去 pygame.display.update) #刷新一下畫面 | Python b Width; 8, Ln 兀匚項(xiàng) ZO INS 不過點(diǎn)擊了一次之后,背景就不會(huì)再變了。而實(shí)際上,在你每次點(diǎn)擊的時(shí)候,程序都會(huì)去讀 取一遍bg2.jpg ,這是沒有必要。把這個(gè)程序的改進(jìn)留給你們:點(diǎn)擊鼠標(biāo)的時(shí)候,背景可以 在2張甚至多張圖片間切換,另外最好不要每次都去讀文件。Pygame第4課】獲取鼠標(biāo)位置 最近微信上很火的“打飛機(jī)”游戲, 通過手指在屏幕上觸摸的位置來移動(dòng)你的飛機(jī)。 在電腦 上,我們沒法直接

17、用手操作,但可以用鼠標(biāo)替代手指。 在電腦游戲里,鼠標(biāo)是個(gè)很好用的輸入設(shè)備。因此在很多游戲中,都需要得到鼠標(biāo)的位置, 以響應(yīng)用戶的操作。 現(xiàn)在,我們要在之前 hello world 的程序上增加一架飛機(jī),并且用鼠標(biāo)來控制飛機(jī)的位置。 得到鼠標(biāo)位置坐標(biāo)的方法是: 1. pygame.mouse.get_pos() 與以往用的函數(shù)有些不同, 這個(gè)函數(shù)會(huì)返回兩個(gè)值: 鼠標(biāo)的x坐標(biāo)和y坐標(biāo)。所以你需要兩 個(gè)變量來記錄返回值: 1. x, y = pygame.mouse.get_pos() 然后,在游戲主循環(huán)中,把實(shí)現(xiàn)準(zhǔn)備好的飛機(jī)圖片畫到屏幕上,位置就是 (x,y): 1. screen.blit(pl

18、ane, (x,y) 運(yùn)行程序,你會(huì)發(fā)現(xiàn),鼠標(biāo)移動(dòng)到哪,飛機(jī)就會(huì)“飛”到哪。但是,飛機(jī)圖片始終在鼠標(biāo)的 右下方。這是因?yàn)閳D片的坐標(biāo)原點(diǎn)是在左上角,原點(diǎn)與鼠標(biāo)的位置對齊。 如果你想讓圖片的中心和鼠標(biāo)位置對齊,則需要再調(diào)整一下 x, y的位置: 1. x-= plane.get_width() / 2 2. y-= plane.get_height() / 2 get_width和get_height 分別是獲取圖片的寬和高。 你可以挑張合適的背景圖和一張邊緣透明的飛機(jī)圖, 再把窗口的長寬調(diào)整一下, 讓它看上去 更舒服一些。 完整代碼: 1. # -*- coding: utf-8 -*- 2.

19、import pygame 3. from sys import exit 4. pygame.init() 5. screen = pygame.display.set_mode(600, 170), 0, 32) 6. pygame.display.set_caption(Hello, World!) 7. background = pygame.image.load(bg.jpg).convert() 8. plane = pygame.image.load(plane.jpg).convert() 9. #加載飛機(jī)圖像 10. while True: 11. for event in

20、pygame.event.get(): 12. if event.type = pygame.QUIT: 13. pygame.quit() 14. exit() 15. screen.blit(background, (0,0) 16. 16. x, y = pygame.mouse.get_pos() 17. #獲取鼠標(biāo)位置 18. x-= plane.get_width() / 2 19. y-= plane.get_height() / 2 20. #計(jì)算飛機(jī)的左上角位置 21. screen.blit(plane, (x,y) 22. #把飛機(jī)畫到屏幕上 23. pygame.dis

21、play.update() | * Untitled Document 1 X 4.py X coding: wtf-6 import pygne from sys Import exit pygne Anit() screen - pygame_display.set_mode(68 t 17。,日32) pygdne.display,set-CpttontHellOj World J) background - pygame .inage load (1 JpQ ) - convert ) plane = pygane.inige . load( plane, jpg ) . canver

22、t() #加載飛機(jī)圖像 white True: for event tn pygrnt * event .get (): i if event.type = pygne.QUIT: pygame.quit() extt() screen.bltt(background, (O,&) y = pygane-mouseget pos() 1 萩取鼠標(biāo)位置 - plne,get_width() f 2 y- plane,get_height() / 2 時(shí)十算飛機(jī)的左上角位置 screen.blit(planet (xty) 停把飛機(jī)畫到屏幕上 pygane.display.updatef) Pyg

23、ame第5課】 游戲中的運(yùn)動(dòng) 本來,在上一次pygame的教程中,我只是順手拿了微信“打飛機(jī)”里的圖來演示用鼠標(biāo)控 制圖片位置的操作。后來覺得,這個(gè)游戲還算比較適合用來做例子, 也有朋友反饋說想做這 個(gè)游戲,那不如就以“打飛機(jī)”為例來說 python游戲開發(fā)好了。 今天,就再進(jìn)一步:既然要打飛機(jī),那得能發(fā)射子彈才行。所以從最簡單的做起,來給游戲 加上“一顆”子彈。 上次的背景圖和飛機(jī)圖, 我自己稍微處理了下, 包括這一課要用到的子彈圖片, 都放在論壇 上,需要的自行下載。 大體的思路是這樣的: 1. 用之前在屏幕上繪制飛機(jī)的方法,再繪制一張很小的子彈圖片。補(bǔ)充一下:當(dāng)你需 要繪制一張帶透明部分

24、的圖片時(shí), 要用convert_alpha() 替代之前的convert(),具 體用法參見代碼中。 2. 子彈被發(fā)射的位置是飛機(jī)的位置,也就是鼠標(biāo)的位置。注意,要讓它們的中心點(diǎn)對 齊,而不是左上角對齊,處理方法我們已經(jīng)說過。 3. 讓這個(gè)子彈往上運(yùn)動(dòng)。還記得我在第 2課游戲的本質(zhì)里面說的嗎:在游戲主循 環(huán)中,要處理物理運(yùn)動(dòng)。所以在程序中要做的就是,每次循環(huán)里,把子彈圖片的 y 坐標(biāo)減少一個(gè)量(因?yàn)槠聊蛔笊辖堑淖鴺?biāo)是 (0,0)。為了能記住子彈上一次循環(huán)中 的位置,要有變量專門來記錄子彈的坐標(biāo)值。 4. 當(dāng)子彈移動(dòng)到屏幕上方外部之后 (y坐標(biāo)小于0),再把它的位置重置回發(fā)射的位置。 這樣看上去

25、就是又一顆子彈被發(fā)射出來了,盡管我們一直是在操作同一張圖片。游 戲中經(jīng)常會(huì)使用到諸如此類的小技巧,來欺騙你的視覺,這也是我覺得開發(fā)游戲很 有意思的一個(gè)地方,好像是在變魔術(shù)。 5. 為了看起來更符合常理,你得把子彈的圖片放在飛機(jī)的圖片下面,這樣看上去才會(huì) 是從飛機(jī)上發(fā)射出去,而不是憑空冒出來的。在程序中,就是先繪制子彈,再繪制 飛機(jī),像是畫油畫,后畫的會(huì)覆蓋掉先畫的。 6. 我在一開始就將子彈的位置設(shè)到屏幕上方之外,這樣它就會(huì)自動(dòng)被循環(huán)內(nèi)的條件判 斷給重置位置,而不需要我再額外手動(dòng)去初始化它的位置。 理清了如上的思路之后,能不能搞定代碼了?如果能的話, 就先別往下看,試著在程序里寫 寫看。 以下

26、是我的實(shí)現(xiàn)代碼: 1. # -*- coding: utf-8 -*- 2. import pygame 3. from sys import exit 4. pygame.init() 5. screen = pygame.display.set_mode(450, 800), 0, 32) 6. pygame.display.set_caption(Hello, World!) 7. background = pygame.image.load(back.jpg).convert() 8. plane = pygame.image.load(plane.png).convert_alpha

27、() 9. bullet = pygame.image.load(bullet.png).convert_alpha() 10. #加載子彈圖像 11. bullet_x = 0 12. bullet_y = -1 13. #初始化子彈位置 14. while True: 15. for event in pygame.event.get(): 16. if event.type = pygame.QUIT: 17. pygame.quit() 18. exit() 19. screen.blit(background, (0,0) 20. x, y = pygame.mouse.get_po

28、s() 21. if bullet_y 0: 22. #如果子彈位置超出了屏幕上端 23. bullet_x = x - bullet.get_width() / 2 24. bullet_y = y - bullet.get_height() / 2 25. #把子彈的中心位置設(shè)為鼠標(biāo)坐標(biāo) 26. else: 27. bullet_y -= 5 28. #子彈的位置往上移 29. screen.blit(bullet, (bullet_x, bullet_y) 30. #把子彈畫到屏幕上 31. x-= plane.get_width() / 2 32. y-= plane.get_heig

29、ht() / 2 33. screen.blit(plane, (x, y) 34. pygame.display.update() e Hello, World! f 但 5.py (/Desktop/pygame) gedit # -* coding: utf-8 inport pygame fron sys Import exit pygame. screen = pygame.display.set_mode(450, 800), 0, 32) pyganedisplayAset_caption(uHello, World!”) background = pygame.image.lo

30、ad(back.jpg1).convert() plane = pygame.image.load(1 plane.png1).convert_alpha() bullet = pygame.image.load(bulletrpng).convert_alpha() 。加載子彈圖像 bullet_x = 0 bullet_y = -1 #初始花子彈位置 while True: for event tn pygame.event.get(): if event.type = pygame.QUIT: pygame.quit() extt() screen.blit(background, (0

31、,G) y = pygame.nouse.get_pos() tf bullet_y (x, y) pygame.displayupdate() Python Tab Width: 8 Ln 35, Col 1 INS 5.py X Untitled Document 1 X Pygame第6課】面向?qū)ο蟮挠螒蛟O(shè)計(jì) 上節(jié)課中,我們的飛機(jī)已經(jīng)可以發(fā)射子彈了, 盡管只有一顆。為什么我只加了一顆?試著多 加幾顆你就會(huì)發(fā)現(xiàn),你得用好幾個(gè)變量去分別記錄它們的 xy坐標(biāo),在主循環(huán)中判斷每一顆 子彈的狀態(tài)。你可以用list把程序?qū)懙蒙陨圆荒敲磸?fù)雜,但這還沒完。別忘了你打飛機(jī)的 對手-敵機(jī)還沒有加入到游戲。到

32、時(shí)候你又需要更多的變量去記錄它們的坐標(biāo), 去判斷它們 的狀態(tài),去處理敵機(jī)、子彈、玩家飛機(jī)之間的關(guān)系。想想都覺得頭大。 于是乎,我之前煞費(fèi)苦心講解的面向?qū)ο缶驮撆缮嫌脠隽恕?我要把子彈相關(guān)的東西都封裝在 一起。 先看看目前子彈相關(guān)的有哪些東西: x、y坐標(biāo),一張圖片,好像就這么多。然后,還有一 段處理子彈運(yùn)動(dòng)狀態(tài)的代碼。來建一個(gè) Bullet類,把x、y、image作為成員變量,再提供 一個(gè)叫做move的成員函數(shù),處理子彈的運(yùn)動(dòng)。 #定義一個(gè)Bullet類,封裝子彈相關(guān)的數(shù)據(jù)和方法 1. class Bullet: 2. def _init_(self): 3. #初始化成員變量,x, y, i

33、mage 4. self.x = 0 5. self.y = -1 6. self.image = pygame.image.load(bullet.png).convert_alpha() 7. 7. def move(self): 8. #處理子彈的運(yùn)動(dòng) 9. if self.y 0: 10. mouseX, mouseY = pygame.mouse.get_pos() 11. self.x = mouseX - self.image.get_width() / 2 12. self.y = mouseY - self.image.get_height() / 2 13. else: 1

34、4. self.y -= 5 代碼的內(nèi)容基本和之前一樣,只是改為了面向?qū)ο蟮膶懛āH绻銓?_init_ , self這些 字眼感到陌生的話,請發(fā)送數(shù)字 47到50,回顧一下關(guān)于 python面向?qū)ο蟮恼n程。 接下來,程序主體就可以瘦身了。在原本加載子彈圖片、 初始化位置的地方,直接創(chuàng)建一個(gè) Bullet 的實(shí)例。 1. bullet = Bullet() 在主循環(huán)中處理子彈運(yùn)動(dòng)的地方,調(diào)用 Bullet的move方法。 1. bullet.move() 繪制子彈的時(shí)候,從 bullet實(shí)例中取數(shù)據(jù)。 1. screen.blit(bullet.image, (bullet.x, bullet

35、.y) 就這么簡單。 運(yùn)行程序看看效果是否正常。 相比昨天,游戲的功能沒有任何進(jìn)展, 但在結(jié)構(gòu)上清晰了許多。 之后,可以放心地添加更多子彈和敵機(jī),而不會(huì)導(dǎo)致代碼變成一坨。 # coding: utf-8 import pygame from sys import exit 帝定義一個(gè)Bullet類,封裝子彈相關(guān)的數(shù)據(jù)和方法 class Bullet: def _init_(self): self.x = 0 self.y = -1 self.inage = pygame.image.load(1 bullet.png1)convert_alpha() #初始化成員變量,x , y , imag

36、e def movefself): #處理子彈的運(yùn)動(dòng) if self.y 800), 0, 32) pygame.display.set_captton(Hello, World!”) background = pygame.image.load(1back.jpg).convert() plane = pygame.image.load(1 plane.png1).convert_alpha() bullet = Bullet() #創(chuàng)建一個(gè)Bullet的實(shí)例 while True: for event in pygame.event.get(): if event.type = pygan

37、e.QUIT: pygame.quit() exit。 screen.blit(background, (0,0) bullet.move() 津調(diào)用move方法,處理子彈的運(yùn)動(dòng) screenblit(bulletimage, (bulletx, bullet.y) 。繪制子彈,救據(jù)來自其成員變量 x, y = pygame.mouse.get_pos() x-= plane.get_width() / 2 y =plane.get_heght() / 2 screen.blit(plane, (x, y) pygame.display.update()Pygame第7課】多變的宿敵 在游戲中

38、,一般都有個(gè)宿敵什么的。 在我們這個(gè)打飛機(jī)小游戲中, 宿敵就是不斷從大而降的 敵機(jī)。它與本機(jī)、子彈構(gòu)成了這個(gè)游戲的三個(gè)要素: 本機(jī)會(huì)發(fā)射子彈,子彈向上運(yùn)動(dòng) 敵機(jī)會(huì)不停產(chǎn)生,向下運(yùn)動(dòng) 子彈碰到敵機(jī),敵機(jī)和子彈都銷毀,加分 本機(jī)碰到敵機(jī),本機(jī)和敵機(jī)都銷毀,游戲結(jié)束 這節(jié)課就來創(chuàng)造這個(gè)宿敵。 同樣,為敵機(jī)創(chuàng)建一個(gè)類: Enemy類的內(nèi)容大致與 Bullet相似。 1. class Enemy: 2. def _init_(self): 3. self.x = 200 4. self.y = -50 5. self.image = pygame.image.load(enemy.png).conver

39、t_alpha() 6. 6. def move(self): 7. if self.y 800: 8. self.y += 0.3 9. else: 10. self.y = -50 復(fù)制代碼 讓敵機(jī)在屏幕上方外部靠中間的位置產(chǎn)生, 并且在每一次循環(huán)中都向下移動(dòng), 當(dāng)飛出屏幕下 方后,就回到屏幕上方重新開始。 和bullet 一樣,我們創(chuàng)建一個(gè) Bullet對象,然后在循環(huán)中調(diào)用它的 move方法,并且繪制 在屏幕上。 1. enemy = Enemy() 2. 2. while True: 3. # 4. enemy.move() 5. screen.blit(enemy.image, (

40、enemy.x, enemy.y) 復(fù)制代碼 運(yùn)行程序。敵機(jī)開始在屏幕中部周而復(fù)始地自上向下運(yùn)動(dòng)。 這宿敵也太呆了吧! 這樣的游戲誰要玩! 所以我們要加點(diǎn)隨機(jī)性。 讓敵機(jī)的出現(xiàn)位置有變化,讓它的速度有變化。 給Enemy增加一個(gè)restart 方法: 1. def restart(self): 2. self.x = random.randint(50, 400) 3. self.y = random.randint(-200, -50) 4. self.speed = random.random() + 0.1 復(fù)制代碼 它的作用是,給敵機(jī)在屏幕上方的一定范圍內(nèi)隨機(jī)一個(gè)初始位置, 然后再給它

41、增加一個(gè)叫做 speed的隨機(jī)量,作為它的速度,在 move函數(shù)中被使用。這樣,它的行為開始有了變化。 這里用到了 random模塊,記得在程序開頭 import它。 restart 在_init_ 函數(shù)以及飛出屏幕下方時(shí)調(diào)用。后面,在敵機(jī)被擊中的時(shí)候,也會(huì)要調(diào) 用它。 再次運(yùn)行程序,看上去有那么點(diǎn)意思了。如果敵機(jī)再多一點(diǎn),子彈再多一點(diǎn),就更好了。這 個(gè),留在下節(jié)課中說。 Q Hello, World! class Enemy: def restart(self): 重置敵機(jī)位置和速度 selfaX = random.randint(50, 460) self.y = random.randi

42、nt(-200, -50) self.speed = random.random() + 0.1 def _intt_(self): #初始化 self.restartf) self.image = pygame.Image.load(1enemy.png1).convert_alpha() def nove(self): If self.y bullet.y) #更新敵機(jī)位置 enemy. rove() screen.blit(eneny.image, (enemy.x, enemy.y) x, y = pygae.nouse.getj)os() x =plane.get_width() /

43、 2 y二 plane*get_height() / 2 screen.tltt(plane, (x, y) pygane.display.update()Pygame第8課】火力全開 游戲中的幾個(gè)主要角色我們都有了, 接下來就是去完善它們,用它們來組成一個(gè)完整的游戲。 首先我們要處理的是子彈。只有一發(fā)子彈顯然是不夠的,群眾表示要火力全開! 所以,我們要有一個(gè)list ,這里list里面存放著一些 Bullet的對象。但一個(gè)list 的Bullet 都按之前的方法創(chuàng)建是不行的,那樣所有的子彈都會(huì)在同一時(shí)間發(fā)射出去, 同時(shí)到達(dá)屏幕上 方,又同時(shí)再次發(fā)射,這樣的視覺效果和一發(fā)子彈沒什么區(qū)別。 所以

44、我們要讓它們按照一定 的時(shí)間間隔,一個(gè)一個(gè)地發(fā)射。 另外,之前到了屏幕頂端就回頭的方法也會(huì)帶來問題, 重新發(fā)射的子彈會(huì)和按時(shí)發(fā)射的子彈 混在一起,打亂發(fā)射的節(jié)奏。所以,子彈“回收”的方法也要改。有種最簡單的方法,就是 不回收,每次發(fā)射都是創(chuàng)建一個(gè)新的 Bullet對象,飛出屏幕之后就拋棄它。這當(dāng)然是可以 的,但每次都要?jiǎng)?chuàng)建對象,讀取圖片,并在 list上做添加和刪除的操作。這樣會(huì)比較消耗 資源,在游戲開發(fā)中一般都盡量避免。 即使現(xiàn)在這個(gè)小游戲中它還不至于影響到體驗(yàn), 也應(yīng) 該養(yǎng)成節(jié)約的良好習(xí)慣。 我們今天要解決的就是兩個(gè)問題:定時(shí)和回收。 python中有定時(shí)運(yùn)行的方法。但這里,我不打算用它。

45、我們有現(xiàn)成的循環(huán)在這兒,只要設(shè) 定好隔多少次循環(huán)運(yùn)行, 就簡單地實(shí)現(xiàn)了定時(shí)的效果。 盡管在游戲中,每次循環(huán)的時(shí)間并不 相同,這么做會(huì)有潛在的問題: 間隔的真實(shí)時(shí)間會(huì)受電腦運(yùn)行速度的影響。 但暫時(shí)你可以忽 略這個(gè)細(xì)節(jié)(它是有解決辦法的)。 我們設(shè)定一個(gè)變量interval_b ,作為Bullet的發(fā)射間隔。在每次循環(huán)中,讓 interval_b 遞減,當(dāng)減到0以下時(shí),便運(yùn)行,并重置 interval_b 的間隔。 1. interval_b = 0 2. while True: interval_b -= 1 #當(dāng)間隔小于0時(shí),激活一發(fā)子彈 if interval_b 0: # (發(fā)射子彈代碼)

46、 interval_b = 100 關(guān)于子彈的重復(fù)利用,我們增加一個(gè)變量 active,只有active為True的子彈,我們才去 處理它的運(yùn)動(dòng)。另外,為了依次使用 list中有限的子彈,還需要一個(gè)變量 index_b來記錄 下一顆子彈是第幾號(hào)。 每激活發(fā)射一顆子彈, 就把index_b指向它的下一號(hào),最后一號(hào)之后 再回頭使用第0號(hào)。 修改一下Bullet類,增加active,并根據(jù)active的狀態(tài)處理運(yùn)動(dòng)。增加一個(gè) restart 方 法,用來重新發(fā)射子彈。 1. class Bullet:3. 4. 5. 6. 7. 2. def _init_(self): 3. 4. 5. 6. 7.

47、 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 在游戲中創(chuàng)建 self.x = 0 self.y = -1 self.image = pygame.image.load(bullet.png).convert_alpha() #默認(rèn)不激活 self.active = False def move(self): #激活狀態(tài)下,向上移動(dòng) if self.active: self.y -= 3 #當(dāng)飛出屏幕,就設(shè)為不激活 if self.y 0: self.active = False def restart(self):

48、 #重置子彈位置 mouseX, mouseY = pygame.mouse.get_pos() self.x = mouseX - self.image.get_width() / 2 self.y = mouseY - self.image.get_height() / 2 #激活子彈 self.active = True 5發(fā)子彈的list (5發(fā)足夠了,只要保證你的子彈數(shù)足夠在打完一輪之前到達(dá) 屏幕頂端) O 1. 猊,建子彈的list 2. bullets = 3. #向list中添加5發(fā)子彈 4. for i in range(5): 5. bullets.append(Bulle

49、t() 6. #子彈總數(shù) 7. count_b = len(bullets) 8. #即將激活的子彈序號(hào) 9. index_b = 0 10. #發(fā)射子彈的間隔 11. interval_b = 0 時(shí)間間隔到達(dá)時(shí),restart 一顆子彈,并將序號(hào)遞增。 1. while True: 2. #發(fā)射間隔遞減 3. interval_b -= 1 4. #當(dāng)間隔小于0時(shí),激活一發(fā)子彈 if interval_b 0: bulletsindex_b.restart() #重置間隔時(shí)間 interval_b = 100 #子彈序號(hào)周期性遞增 index_b = (index_b + 1) % cou

50、nt_b #判斷每個(gè)子彈的狀態(tài) for b in bullets: #處于激活狀態(tài)的子彈,移動(dòng)位置并繪制 if b.active: b.move() screen.blit(b.image, (b.x, b.y) 只處理active的子彈,繪制它們。 如此一來,你可以不停地向敵機(jī)開火了。 根據(jù)你電腦的運(yùn)行狀況,適當(dāng)調(diào)整一下子彈的移動(dòng) 速度和發(fā)射間隔,讓它看起來更自然。 至于敵機(jī)的行為,比子彈要簡單一些, 因?yàn)椴恍枰〞r(shí)出現(xiàn), 所以之前用的回收方法可以繼 續(xù)使用,我們下次再說。 class Bullet: def _tntt_(self): self.x = 0 self * y = -1 se

51、lf Anage 三 pyganeAnage.Load(1 bullet.png1) .convert_alphaO 啾認(rèn)不激舌 self.active = False def novefself): 律激活狀態(tài)下,向上移動(dòng) if self.active: self y -二 3 。當(dāng)飛出屏幕,就設(shè)為不激活 If self.y 0: self.active = False def restart(self): 。重置子彈位置 inouseXf nouseY 二 pygame, mouse. get_pos() self, x = nauseX - seif-tmage.get_wi.dth(

52、/ 2 self* y = mouseY - seif * image.get_height(5 / 2 #激活子彈 - 5elftactive = True5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. pygane.tntt() screen = pygane.display.set_node(450, 800), 0, 32) pygane.displayset_captton(”Hello, World!M) background = pygane.inage.load(back.jpg).convert() plane = pygane.imag

53、e.load(1 plane.png1).convert_alpha() 存創(chuàng)建子彈的list bullets = 響list中添加5發(fā)子彈 for t tn range(S): bullets.append(Bullet() 。子彈總數(shù) count_b = len(bullets) 。即將汲活的子彈序號(hào) index_b = 0 。發(fā)射子彈的間隔 tnterval_b = 6 enemy = Enemy() while True: for event in pygame.event.get(): if event.type = pygane.QUIT: | pygane.quit() exit

54、。 screen.blit(background, (0,0) #發(fā)射間隔遞減 interval =1 存當(dāng)間隔不于。時(shí),激活一發(fā)子彈 if interval_b 6: bulletsindex_b.restart() 。重置間福時(shí)間 tntervalb = 166 再子彈序耳周期性遞增 tndex_b = (tndex b + 1) % count 4判斷每個(gè)字彈的狀態(tài)- - for b tn bullets: 存處于激活狀態(tài)的子彈,移動(dòng)位置并繪制 if b.active: b.nove() sc reen * blit(b * image, (b.x, by) enemy.move() s

55、creen.blit(enemy.image, (enemy.x, enemy.y) x, y = pyganemouseget_pos() x-= plane.get_wtdth() / 2 y-= plane.get_hetght() / 2 screen.blit(planc, (x, y) pygane.displayupdate()Pygame第9課】一大波飛機(jī) 又到周一了,小伙伴們周末過得可好?是不是有人剛剛結(jié)束了無聊的暑假, 又開始豐富多彩 的校園生活了? 上周最后的課里說了, 這次我們要來加入一大波飛機(jī)正在接近的效果。 這個(gè)要比之前的子彈 容易實(shí)現(xiàn)多了。因?yàn)橹灰岋w機(jī)不停地從屏幕上方出現(xiàn)就好了,不用管它具體的間隔怎樣, 看上去像那么回事就可以。 之前我們單個(gè)飛機(jī)已經(jīng)完成了在屏幕上方區(qū)域內(nèi)隨機(jī)出現(xiàn), 能?,F(xiàn)在要做的,僅僅是把一架敵機(jī)換成一組敵機(jī): 1. enemies = 2. for i in range(5): 3. enemies.append(Enemy() 創(chuàng)建5個(gè)Enemy的對象,把它們添加到一個(gè)叫做 enemies的list 中。 然后,在主循環(huán)里,去處理每一架敵機(jī)的運(yùn)動(dòng): 1. for e in enemies: 2. e.move() 3. screen.blit(e.image, (e.x, e.y) 如果你覺得幾

溫馨提示

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

最新文檔

評論

0/150

提交評論