基于MonoGame重制《俄罗斯方块》游戏

两年前,我使用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来定义它的形状,可以有多行,每行之间用空格隔开

比如,如果我们希望把下面这个方块加入到游戏中:

如果将它旋转起来,就会有以下四种旋转形态,如果在每种旋转形态中,需要显示材质的方格用1表示,而不需要显示的方格用0表示,就得到:

因此,对于这个方块,就可以用下面的文本进行定义:

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. 游戏中的材质、字体、音效和背景音乐均来自【爱给网】付费区,付费下载,如有版权问题请联系网站)

posted @ 2024-08-15 20:57  dax.net  阅读(738)  评论(2编辑  收藏  举报