我們終于把pygame的方方面面都說了一遍,也經過了兩個小游戲的洗禮,如果您真的好好學習了每一部分并自動動手演練過,那就是一個很不錯的Python游戲開發(fā)人員啦!
但是,不得不說我們到現(xiàn)在為止,寫的東西都不夠酷!pygame就這點能耐么?第一篇介紹pygame的時候,我就說了pygame很適合做一個植物大戰(zhàn)僵尸之類的游戲,OK,那么,這次開始我們就來用pygame山寨一個吧哈哈。
游戲介紹就省略了,不過說實話這游戲我也沒玩幾關,感受了一下就關了。所以現(xiàn)在仿制的與真品相比肯定差了很多,這里只是稍微把我們學習的東西溫習應用一下而已,如果各位看到什么不對勁兒的東西,只要不是很致命,也就一笑而過吧。
游戲是否賣座,創(chuàng)意是極為重要的。所有其他技術性的東西,比如畫面音樂都是有可替代性的,也就是說,可以通過學習獲得的,而創(chuàng)意則不同,植物大戰(zhàn)僵尸之前,有無數(shù)的塔防游戲,為什么沒有這么火?首先制作精良,上手容易,然后兩者的結合給人耳目一新,闖關的模式更是易于上手難于精通,非常具有可挖掘性。當然原因肯定不止這么多,不管是游戲還是電影,成功永遠有規(guī)律可循,然而卻永遠無法復制??梢詫W習一下它的好的地方,但光學習是不可能突破的。
這個雖然極為重要,但不是我們的重點,我們這里基本就是抄襲——哦不,是參考,所以就不多講了(也沒有人能講出什么東西來)。
好的游戲往往需要極為漂亮的畫面,這里也還是發(fā)揮拿來主義吧~ 各種背景角色啊音樂都解包復制過來就是了。怎么解包?網上搜一下。
不過如果分析一下資源包里的文件,會發(fā)現(xiàn)它分的特別細,比如說一個太陽花,周圍一圈花瓣,居然是一個一個分開來存放的!這個引擎還挺有意思。我們的pygame不太適合用這樣的圖片資源,還是把每一幀完整的分別存放吧。當然可以一幀一個文件,有些麻煩,還增加讀盤時間?;叵胂耂urface里學習的東西,我們可以把這么多幀拼成一個圖片,然后取一部分就可以了。比如說太陽花,處理以后會是下面的樣子:
每個幀都并列排開,太陽花的話一共有18個畫面,很長的一張圖。每個畫面都有共同的高度和寬度,所以一旦我們讀進這個文件并轉成Surface以后,就拆成18個Subsurface,在渲染的時候,分別畫出來,就有動態(tài)的效果了。
很顯然我們在分割的時候需要知道寬度(高度的話,如果只有一行,就無所謂了),可以在代碼里寫好,我這里就是這么做的。不過也許自己在寫游戲的時候,美工和程序不在一起做,那么就需要良好溝通,或者這種小制作的話,就把圖片文件名規(guī)定一下,叫【sunflower_82x77_18.png】好了,意思是【名字_寬x高_數(shù).后綴】,這樣代碼可以根據讀入的文件名自動轉換。只是舉個例子,總之,游戲資源繁多,好好的管理是很重要的。
因為只是做一個demo,太復雜的構架也就免了,這次我就隨便寫寫了。而且也沒有什么絕對優(yōu)秀的構架可以放到哪里都好用,根據要求自己選擇判斷才是重要的。
我們之前的各種動畫,變化的只有位置,在一款優(yōu)秀的游戲中,這個是不允許存在的,飛機什么的可能還好說一些,要是有人物走動的時候,腳也不動一下豈不見鬼了?不過,難道每畫一幀就換一個圖片貼上去么?好像很麻煩啊……
放心,一點都不比移動困難,溫習一下之前的Sprite篇(其實AI部分結束那個時候我就開始穿插寫實戰(zhàn)了,發(fā)現(xiàn)缺少Sprite的知識實在不方便,就加了一個Sprite的介紹,實戰(zhàn)就挪到了最后),我們既然把畫圖全部交給Sprite來做,那么圖片的切換也可以交給它來做。
這里有兩個內容,一個是load_image函數(shù),它接受三個參數(shù),圖片文件名、每一幀的寬度和總幀數(shù),它所做的事情就是把圖片讀入之后分割Subsurface,把一個Subsurface的列表返回。這個函數(shù)被SunFlower類的初始化函數(shù)調用,返回值存放在靜態(tài)變量images里。
為什么把Subsurface列表存為靜態(tài)變量,也是有含義的。這樣一來這個圖片只會第一次新建SunFlower類的實例的時候加載一次,下一次在新建一個太陽花的時候,就不會再讀取sunflower.png文件了,節(jié)約內存和時間。
然后看update方法,這里做的事情便是是SunFlower當前的image指向下一個Subsurface(到頭的話重新開始),這樣每次blit的時候,就會和上一次有些差別,動態(tài)效果就出來了。
不過對于“基于時間的移動”那部分學習的比較好的話,很肯會考慮到一個問題。我們這里是一幀切換一個畫面,萬一游戲變得很復雜或者運行的機器很糟糕,每一幀都花了大量時間的話,豈不是就動的很慢了?牛機器上的話,又要擺的像螺旋槳一樣看著就要飛起來似地……怎么辦?一樣,使用基于時間的幀切換!
與上一個SunFlower類相比,我們多了一個_rate靜態(tài)變量,然后初始化的時候也多了一個passed_time靜態(tài)變量,update也多了一個參數(shù)。盡管看起來有變得復雜了一些,這一切都是值得的!_rate意味著一幀畫面要保持多少毫秒,passed_time則記錄著游戲經過了多少毫秒(為了避免passed_time無限增大,我在合適的時候把它歸零了),我們通過這兩個參數(shù)計算出現(xiàn)在應該顯示第幾幀,盡管形式不同,這和基于時間的移動是一個道理。希望大家能看明白(不明白的話多看幾遍……再看不明白的去復習第8部分,再不明白的,面壁去……哦,我是說咱倆都得去面壁)。
如果沒能成功的運行起來(雖然似乎有點不應該),也沒關系,這個系列完成以后會放出完整代碼的。
本次使用的太陽花資源圖片: sunflower.png