基於MonoGame重製《俄羅斯方塊》遊戲

dax.net發表於2024-08-15

兩年前,我使用C#基於MonoGame編寫了一款《俄羅斯方塊》遊戲,相關介紹可以參考【這篇文章】。最近,使用業餘時間將之前的基於MonoGame的遊戲開發框架重構了一下,於是,也就趁此機會將之前的《俄羅斯方塊》遊戲也重製一次,加入了許多我一直打算加入的功能,甚至包括提供跨平臺的版本。

先說說這個遊戲開發框架,我給它取名為Mfx(MonoGame Fx,Fx是Framework的縮寫,但又不想跟MonoGame Framework重名),倉儲地址是:https://github.com/daxnet/mfx。這個重構過的框架在整體結構設計上比其前任版本Ovow(https://github.com/daxnet/ovow)更為合理,去掉了一些不必要的功能,也加入了一些新的功能。業餘時間有限,所以也沒打算將它真正開發成一個完整的遊戲引擎,就是能夠支援我自己寫的一些小遊戲就可以了,所以,也不打算對它做過多介紹。

回到重製版《俄羅斯方塊》遊戲,先開源:【https://github.com/daxnet/tetris-sharp-revised】,在這個頁面的Releases列表裡,可以直接點選最新的釋出版本,然後選擇對應的作業系統的ZIP包進行下載把玩,目前該遊戲編譯輸出Windows、Linux和MacOS三個版本(Linux我在Ubuntu 24.04 LTS Desktop下測試可用,MacOS沒有試過)。當然,如果不想玩遊戲,可以直接看影片:

與舊版本相比,新版檔案尺寸更小,打包後尺寸為62MB,相比之前的107MB,減小了45MB,其實新版本自帶的背景音樂更加豐富,資源大小也變得更大,但總尺寸是下降了,也是因為.NET從6升級到8後,本身也做了不少的最佳化。對於這樣一個簡單的遊戲為何會有這麼大尺寸?主要有兩個方面的原因:各種資源需要佔用一部分空間,另外就是在打包編譯後的程式時使用了--self-contained開關,也就意味著將整個.NET 8都打包在了一起,玩家不需要安裝任何.NET相關的執行庫。那反過來想想,如果使用相同的這套技術開發了一個大型遊戲,雖然資源會佔更多的空間,但是即便是幾百MB甚至上GB,或許你也不會在意它的尺寸了。

下載並解壓之後,雙擊TetrisSharp.exe(Linux下先chmod +x ./TetrisSharp,然後直接執行)即可開始遊戲,點選【NEW GAME】選單就能進入主介面開始遊戲,【CONTINUE】選單目前是不可用的,在遊戲過程中,按下鍵盤上的ESC鍵,即可返回標題介面,此時CONTINUE選單才可用,點選即可繼續遊戲。【LOAD】選單也是不可用的,但在遊戲的過程中任意時刻退出遊戲,遊戲狀態會被儲存下來,下一次重新執行遊戲時,LOAD選單就會變成可用狀態,點選即可載入上次儲存的遊戲狀態。點選【INPUT SETTINGS】選單可以進入按鍵設定介面:

紅色字型提示當前正在設定的按鍵,此時只需要在鍵盤或者遊戲手柄上按下對應的鍵,紅色選中項就會跳到下一個專案。如果中途有任何按鍵設定錯誤,可以點選【RESET】按鈕,從頭開始重新設定按鍵。設定完畢後,點選【SAVE】按鈕儲存,或者點選【CANCEL】按鈕取消設定。對於遊戲手柄,目前好像並不是所有手柄都支援(我自己使用的是8BitDo M30),建議可以連上試試,切換一下手柄的模式(估計需要XBOX模式),如果不行,還是先用鍵盤體驗吧。

如上圖所示,第一次執行遊戲,預設使用鍵盤作為輸入,按鍵定義如下:

  • 方塊下移:S
  • 方塊左移:A
  • 方塊右移:D
  • 方塊旋轉:J
  • 方塊下落到底:K
  • 暫停遊戲:空格鍵
  • (隱藏:回到開始介面:ESC)

跟老版本相比,新版本在介面上進行了最佳化(如下上圖為老版本,下圖為新版本):

主要改進地方有:

  1. 棋盤變得更大:由原來的12x24改為了15x28
  2. 方塊材質進行了調整
  3. 方塊下落時會在棋盤上留下投影,方便定位
  4. 為方塊快速下落新增獨立按鍵,按下後直接將方塊下落到最底端
  5. 介面配色和字型做了調整
  6. 顯示已經使用過的方塊數量
  7. 統計最高分,當分數突破最高分後會更新最高分

此外,在遊戲操控方面也做了一些最佳化,按鍵控制更加靈活。由於修正了舊版本中的背景音樂載入問題,新版記憶體佔用率大幅下降,為原來的50%左右,從400多MB降為了200多MB。總而言之,新版本更接近一個完整的遊戲。

與老版本相同,新版也提供了自定義方塊的功能,只不過新版使用了更為簡潔的文字檔案,而非之前的XML檔案。在遊戲目錄下,找到blocks.txt檔案,雙擊開啟即可編輯。檔案格式如下:

  • #開頭行為註釋行
  • 每個方塊的定義都是以block "<名稱>"指令開頭,end block指令結束,中間包含1到多行方塊變體(也就是旋轉形態Rotation)的定義
  • 每個方塊變體佔用一行,比如L形方塊,它有四個旋轉形態:𠃊、𠃎、𠃍、廠,那麼就有四行0和1的數字來定義它的形態
  • 對於每個旋轉形態,使用數字0和1來定義它的形狀,可以有多行,每行之間用空格隔開

比如,如果我們希望把下面這個方塊加入到遊戲中:

基於MonoGame重製《俄羅斯方塊》遊戲

如果將它旋轉起來,就會有以下四種旋轉形態,如果在每種旋轉形態中,需要顯示材質的方格用1表示,而不需要顯示的方格用0表示,就得到:

基於MonoGame重製《俄羅斯方塊》遊戲

因此,對於這個方塊,就可以用下面的文字進行定義:

block "custom"
	111 101
	11 10 11
	101 111
	11 01 11
end block

將這個定義加到blocks.txt檔案中後,重新啟動遊戲,就會出現這個自定義的方塊,比如:

程式設計方面,因為使用的C#,所以遵循物件導向基本原則無疑,在Mfx框架和遊戲本身中,也應用了一些設計模式(比如Builder、Adapter、Mediator等)以使得遊戲的整體結構更為優雅,有時間我可以在另外的博文中介紹。對於原始碼的使用,如果希望自己除錯,首先確保.NET 8 SDK已經安裝,然後用Visual Studio 2022開啟src目錄下的TetrisSharp.sln,將TetrisSharp專案設定為啟動專案,直接F5即可除錯。如果希望直接編譯原始碼,則可在src目錄下,使用下面的命令生成編譯,生成的結果會輸出到bin\Release\net8.0目錄下:

REM 生成Windows編譯
dotnet publish -c Release --sc -r win-x64

REM 生成Linux Desktop編譯
dotnet publish -c Release --sc -r linux-x64

REM 生成MacOS編譯
dotnet publish -c Release --sc -r osx-x64

OK,今天先介紹這麼多,有興趣的讀者歡迎試玩吐槽。

(P.S. 遊戲中的材質、字型、音效和背景音樂均來自【愛給網】付費區,付費下載,如有版權問題請聯絡網站)

相關文章