PyGame 入門遊戲開發第二篇


3樓貓 發佈時間:2024-04-15 13:32:45 作者:韓大 Language

推麻將的玩法 上一篇介紹了一個遊戲運行的最基本結構,本篇開始根據一個具體的遊戲,做一個遊戲關卡。下面要做的是一個叫“推麻將”的桌面玩法。現在介紹一下這個玩法的具體內容:
  1. 一副麻將隨機放在桌上,共 8 行 14 列
  2. 任何兩個相同的麻將,直線相連如果沒有其他麻將阻隔,就可以消除掉
  3. 桌上如果有空位(有麻將消除了留下的空位),相鄰的四個方向的麻將行列,都可以整隊移動;但是移動之後,被推動的這隊麻將,必須至少要有一個能被消除的麻將,否則不能移動
  4. 桌上所有麻將都被消除完就是勝利;
  5. 消除和推動麻將的移動,使用鼠標點擊來操作
第一個關卡
根據上篇設計的關卡基類 Scenario,我們可以為了一個特定的遊戲,建立一個子類 MainScenario。
編寫 MainScenario 也很簡單,主要就是實現一個 start() 方法。此方法所需要做的事情,就是多次調用基類的 add_group() 方法,把需要顯示的遊戲對象,都以 Group 的組織形式,添加到關卡中去。
Group 對象及其內部的 Sprite 對象,一旦被 add_group() 放到 MainScenario 後,由於 Director 的 run() 方法,就會每幀(每秒60次的)去調用 MainScenario 的 update() 方法,因此在 MainScenario 中的 Group 對象,以及 Sprite 對象的 update() 方法也會被調用。所以我們遊戲邏輯的主要實現代碼就是:
  1. 編寫 MainScenario.start() :放置遊戲關卡初始的所有遊戲對象組 Group 以及需要的遊戲對象 Sprite
  2. 編寫遊戲對象 Group 和 Sprite 的子類,通過實現 __init__() 和 update() 方法來完成各種遊戲行為
上面的代碼,在關卡中加入了三個 Group:
  • bg 代表背景,在上面的遊戲中,是由一批帶圓點花紋的 Sprite 組成的桌布
  • table 代表桌子,上面這個遊戲是一個放了幾十個麻將牌的桌子,其中每個麻將是一個 Sprite,桌子 Table 類則繼承 Group
  • effect 代表特效層,特效層初始化的時候,沒有任何的 Sprite 成員,而是在運行時添加和刪除“爆炸特效” Sprite,用來顯示“消除”麻將的效果。因此建立了 bomb1/bomb2 兩個 Sprite 對象,先作為屬性掛在每個麻將 Sprite 對象上。而 bomb1/bomb2 對象的類 Bomb,也會保存 effect 這個 Group 的對象,用以實現動畫效果。
注意三個 Group 的 add_group() 的順序:最先添加的,會被放在最底層顯示,以此類推。所以 bg 作為背景是最底下,中間是 table 層,上面是特效 effect 層。三個 Group 對象通過 add_group() 放入到關卡 MainSenario 中。
然後根據遊戲玩法我們設計了幾個類,用來實現上述的玩法:
  1. Table:存放所有麻將的對象,會記錄所有麻將的位置,每幀根據麻將的位置重繪畫面,麻將移動過程也是通過 Table 顯示。
  2. Mahjong:可以放在 Table 上顯示,一個關卡中會有 8x14 共 112 個對象,每個對象保存自己的圖案。點擊麻將的事件處理也由此類處理。
  3. Edge:點擊麻將後,顯示的“選中”框,通過 effect 這個 Group 顯示。Table 對象會記錄 Edge 的位置,以記錄當前選定的麻將。
  4. Point:桌面背景層,通過 bg 這個 Group 顯示。點擊 Point 會觸發麻將的移動邏輯。桌面上也是由 112 個 Point 對象組成,因此被點擊的 Point 是可以知道其座標位置的。
  5. Bomb:消除麻將時顯示的“爆炸”動畫,每個麻將對象身上都有屬性是 Bomb 對象(b1/b2),需要顯示的時候直接加入 effect Group,過一段時間後消失,形成一個簡單的動畫效果。
最終,上面所有的 Sprite,都以所需的遊戲邏輯構建,並且被放入 Group 中。
對於遊戲來說,為每個可以單獨顯示的“東西”設計一個類,是非常自然的做法;然而,有一些並不可見的邏輯,也應該考慮設計成一個類,譬如這裡的 Table 類型。事實上,Table 對象保存了整個遊戲程序中最重要的狀態,就是所有麻將的位置。有了 Table 對象,其他所有的可顯示對象,在處理“被鼠標點擊”事件的時候,都能獲得完整的所有麻將的狀態,非常方便編寫遊戲業務邏輯。
加載圖像資源
在處理完“桌子”之後,下來需要處理的最複雜的資源,就是麻將了。一般來說,遊戲的圖像資源,都是一個圖片文件。很多圖像都拼接在同一個文件上,如下圖:
每個麻將需要獲得這個文件中圖像的某一塊,需要有兩個步驟:
  1. 把整個圖片加載到內存中,變成一個對象(變量)
  2. 截取自己需要的那一部分圖像,變成一個對象,存放到 Mahjong 對象的 image 屬性和 Rect 屬性上。image 屬性是 Sprite 基類規定了,用來顯示的圖像內容屬性。而 Rect 屬性則決定此 Sprite 對象顯示在屏幕上的位置和大小。
上述代碼的 pygame.image.load() 是作為類靜態代碼執行,只會執行一次,並不會每個 Mahjong 對象構造出來都運行一次。這行代碼就是加載圖片資源:一個由 36 個麻將組成的圖片。
上述代碼的 self.image.blit() 就是從一個 pygame.surface.Surface 對象上,截取某一塊圖像作為內容。至於需要截取哪一塊圖像,由 symbol 參數決定,這個參數以一個二位數組,標識一個麻將花色。這個數值的內容,也代表了在圖形文件 southeast.jpg 上具體某一行、列的麻將圖像。從此,Mahjong 對象有了可以顯示的內容,只要把此對象 add() 到一個 Group 上,屏幕就會顯示一個麻將牌了。
通過 symbol 的數值,可以計算出 southeast.jpg 圖像文件上具體的圖像的位置。並且通過設定的空白邊的高、寬,準確截取想要的圖像。以上的加載圖像代碼,包含了 cols/lines/margin_width/magin_height 這些常量,這些數值是和 southeast.jpg 綁定的。在 Unity 等遊戲引擎中,通常會有一些圖形文件處理工具,來幫你以可視化的方式,切割一整個圖形文件,然後生成你需要的各個遊戲對象(Sprite)。
隨機生成一桌麻將
上述代碼在 MainScenario.start() 中,對於 9x4 的圖形資源,每取出一個,就生成 4 個相同的 Mahjong 對象。循環中的 [j, i] 變量,代表了麻將的圖案。然後把這 112 個麻將放在一個數組中,通過 Table.put_in() 放到桌上。
一般來說,麻將的圖案和麻將美術資源應該是解耦的,上面代碼中的 Mahjong.cols, Mahjong.lines 這兩個常量,決定了生成的 Mahjong 對象的 symbol 屬性的值,如 [0,1] 代表“二筒”、[1,2] 代表“三條”。按專業的做法,這個值(如 [0,1],[1,2])是不應該是根據 southeast.jpg 這個圖片上對應圖案的“座標”來確定的,而應該有另外一個配置文件,寫下每個麻將圖案代表的數值(可能是從 0-36),對應美術資源 southeast.jpg 文件上的位置座標。但是這個遊戲比較簡單,麻將的圖形文件也不太可能更換,所以代碼中這麼寫也可以接受。因此 Mahjong.symbol 屬性就是由兩個 int 組成的數組。這樣使用美術資源的圖像座標,代表麻將圖案,由於是一個兩個元素的數組變量,讓代碼的理解也變得困難了一些。
Table 對象通過一個屬性 heap 記錄每個麻將的位置,heap 是一個 14x8 的二維數組,下標是桌上麻將的行、列數字,元素則是 Mahjong 對象。如果某個位置沒有麻將,這個座標所對應的值是 None。 由於需要隨機打亂位置,所以 Table.put_in() 必須要使用隨機數來實現這個功能:
  1. 用一個數組 mahjiongs 存放“未放入”的麻將堆
  2. 用一個數組 random_symbol 存放“打亂順序”的麻將堆
  3. 隨機從 mahjiongs 抽出一個麻將,加入到 random_symbol 中,直到 mahjiongs 變空
  4. 用 random_symbol 的順序,一個個放入 Table 的 14x8 的數組 heap 中。
Table 通過 heap 屬性,記錄所有的麻將,然後通過對 Majiong.pos 賦值,傳入其所在 heap 數組的座標,讓每個 Mahjong 自己調整 Rect 屬性,從而實現按預定桌面位置進行顯示:
以上的 Table.show() 方法,會在 Table.update() 中調用,索引每幀都會刷新顯示桌面上所有麻將的位置。這樣遊戲邏輯,只需要修改 Table.heap 的內容,就能自由控制桌面上需要顯示的麻將了。
上面的 theMajiang.show(),實際上是根據 Mahjong.pos 屬性去設置自己的 Rect 數值,以確定顯示位置的。而 Mahjong.pos 屬性,在 Table.put_in() 的時候已經正確賦值了。
Mahjong.show() 還有一個功能,就是顯示麻將牌移動的動畫效果。我們下一篇繼續介紹。

© 2022 3樓貓 下載APP 站點地圖 廣告合作:asmrly666@gmail.com