基于LabVIEW的俄罗斯方块游戏设计

您所在的位置:网站首页 labview小游戏制作视频 基于LabVIEW的俄罗斯方块游戏设计

基于LabVIEW的俄罗斯方块游戏设计

2024-05-11 18:57| 来源: 网络整理| 查看: 265

0 来源

labview俄罗斯方块程序

1 项目设备和工具

装有LabVIEW2017软件的个人PC电脑

2 项目背景2.1 课题背景

俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它由前苏联数学家阿列克谢·帕基特诺夫于1984年6月发明。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。

截至2009年,俄罗斯方块发售了1.25亿份,受到50多个国家和地区的玩家喜爱,有超过50种语言的版本,运行在几十种游戏平台上。在俄罗斯方块网络版的北美和欧洲官方网站上,每天超过100万人次玩这个游戏。

2.2 选题意义

俄罗斯方块不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。俄罗斯方块既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“水满则溢,月盈则亏”,其简单易学的特性,为人民所喜爱。

俄罗斯方块创下了许多电子游戏史上无人能够打破的纪录,各平台上的游戏综合销量高达数亿份,迄今拥有9项吉尼斯世界纪录,包括通过手提电话下载次数最多的游戏、被移植次数最多的游戏等。

以此为背景,我开发了一个基于LabVIEW虚拟平台实现的俄罗斯方块游戏。运行程序后,系统将自动生成随机的俄罗斯方块,通过使用“←(左移)”、“→(右移)”、“↓(加速下降)”、“↑(原速下降)”“Shift(旋转)”等按键,可以实现俄罗斯方块在交互界面上的基本操作。系统根据背景板上的方块堆叠信息和消除行数统计,可以发出“游戏结束”和“分数统计”等指令。

3 程序设计3.1 随机方块的生成和记录3.1.1 随机方块的生成

俄罗斯方块英文名是Tetris,这个名字来源于希腊语tetra,意思是“四”,而游戏的作者最喜欢网球(tennis)。于是,他把两个词tetra和tennis合而为一,命名为Tetris。俄罗斯方块游戏通常包括以下7种方块,每种方块都有四个元素,如图3-1所示。系统中的随机方块生成子函数,实现了对这7种方块的随机选择。

图3-1 随机方块的类型

随机方块产生的程序框图如图3-2所示。

图3-2 随机方块生成的程序框图

首先在程序面板的数值中选择随机数(0-1)控件,可以得到介于0和1之间的任一数值,将这一数值乘以7,并向下取整,可以得到由0到6的7种整型变量。选择条件结构,连接上述的整型变量后,右键选择向下添加分支。

在7个分支的结构框内,分别创建二维数组常量,定义数组元素为布尔(F)型。根据图3-1所列出的随机方块类型,分别在对应编号的结构框内对俄罗斯方块的形状进行填充。当结构框右边缘的空心点变为实心,则说明所有通道完成编辑。该程序对应的前面板界面如图3-3所示。

图3-3 随机方块的显示界面

新建数组变量,并将其命名为“随机方块”,使用布尔菜单中的方形指示灯显示数组中的元素。下拉左侧的数字,可以修改数组为二维数组。拖动方块的边界,可以对界面大小和指示灯长宽比进行调整。

在程序框图将条件结构框的输出端与随机方块相连,并运行程序,可以看到随机方块以方形灯点亮的状态在界面中显示。

3.1.2 方块信息的记录

此外,程序还需要使用一个二维数组来记录方块的位置信息,如图3-4。

图3-4 方块信息矩阵

为了显示随机方块的信息,首先在前面板添加名为“方块信息”的二维数组变量,使用数值菜单中的数值显示控件定义元素,如图3-5所示。

图3-5 方块信息数组在前面板的显示

方块信息数组可以将随机方块中亮灯的元素坐标逐一记录,并显示在前面板中。为了实现这一功能,需要在程序框图中遍历随机方块数组的每一个元素,判断各元素的布尔属性值。若元素属性为“真”,则将行数据和列数据进行记录。

方块信息记录的程序框图如图3-6所示。程序使用嵌套的for循环遍历随机方块中的所有元素,分别对数组内的行和列进行查找。循环的次数分别为随机方块的行数和列数。

利用“数组大小”控件,可以得到随机方块的数组大小信息,由于“随机方块”数组是一个二维数组,因此“数组大小”控件输出的是包含行数和列数的一维数组信息。通过“索引数组”控件,可以将行数和列数两个变量分离,并赋值给两个循环框图的循环次数。

在每次循环中,需要对“随机方块”的某坐标元素进行判定。首先需要创建“随机方块”的属性节点,将其中各个元素的值由“索引数组”控件读出。若该处的指示灯量,则值为真,可以通过条件结构框进行下一步操作。

对于值为真的情况,通过在条件框内将循环得到的元素行数与列数,由“创建数组”控件打包为子数组,分次填入到“方块信息”数组中。此处定义“方块信息”中的元素为长整型变量,可在前面板进行显示。

图3-6 方块信息记录的程序框图3.2 方块旋转3.2.1 方块旋转的算法

由3.1.2节可知,每个随机方块信息都通过记录其布尔值为真的坐标数据,保存在“方块信息”数组中。先以方块0为例,多次进行顺时针90°旋转。图形每次旋转后,坐其标信息的变化如图3-7所示。

图3-7 方块旋转后的坐标变化情况

对图3-7中旋转变换前后的坐标信息进行比较可以发现,后一次变化得到的行数据,即为上一次的列数据;取出前一次行数据的最大值,分别与每个元素相减,即可得到变换后的列数据值。定义变换前的数据为矩阵D,变换后的数据为矩阵D’,则可以用公式3-1和公式3-2进行表示。

图3-8 方块信息表示法(3-1)

         

(3-2)3.2.2 方块旋转的编程实现

由图3-7中的表格可知,“方块信息”的数组第一列代表随机方块的行,第二列是随机方块的列。通过上节所述的坐标变换方法,可以先对“方块信息”的元素进行变换改写。其程序框图如图3-9所示。

图3-9 旋转过程中方块信息的变换(程序)

首先通过索引数组的第一列(元素所在的列)和第0列(元素所在的行)。取出行的最大值和每一元素相减,得到的数据和初始信息的列合并为新数组并转置,即可得到变换后的方块信息。运行过程见图3-10所示。

图3-10 旋转过程中方块信息的变换(运行界面)

得到了方块的信息矩阵,需要通过其中的坐标数据,改写原来的布尔型数组显示界面。这一过程的实现需要使用顺序结构,包括数组初始化和替换数组两个步骤。如图3-11所示。

图3-11 方块旋转子VI程序框图3.3 整行消除3.3.1整行消除的算法

根据游戏规则,当方块下落后形成一整行时会对该行元素消除。为了实现这一功能,可以设计算法如图3-12所示。

图3-12 整行消除的实现流程

程序首先检查底行元素,若整行均占满,则对整行元素进行消除。消除后,底行为未初始化的空白内容,因此可在界面顶部添加一行值为“F”的布尔元素行,然后再重新搜索底行;若整行未占满,则检查上一行。

3.3.2 整行消除的程序实现

根据3.3.1节所述的方法,可以编写整行消除子VI如图3-13所示。

图3-13 整行消除的程序实现

该程序使用顺序结构,由两个分支组成。前一分支主要实现了整行元素的判断和删除;后一分支新建了“删除后”数组,将结果的界面送入。

在第一分支,程序首先对删除前的界面进行行数和列数的提取,得到的列数用于后续分支,得到的行数作为for循环的循环总次数使用。程序从底行开始进行循环。当运行到某一行时,程序通过索引该行的所有元素,对其进行“与”运算。如果检测结果为整行,则送入条件结构处理:创建显示控件,对删除的行数进行统计,同时删除该行元素。此时可以在界面上得到未经初始化的整行,如图3-14所示。

图3-14 删除整行的功能测试结果

在第二分支,首先初始化一个新数组,这一数组的行数即为删除的行数,列数来源于前一分支对删除前界面的提取。删除了整行的数组信息和新插入的行进行合并,即可得到删除后的界面,如图3-15所示。

3.4 主程序设计

在以上三个子VI的基础上,需要结合俄罗斯方块的游戏规则,搭建完整的主程序。主程序的编写主要包含三个方面,即变量的初始化、实现正常下落堆积的超时事件结构,以及控制方块变换的按键事件结构。

3.4.1 主程序变量的初始化

由于游戏的运行需要依托LabVIEW的事件结构,因此需要实现对程序需要用到的变量进行初始化。结合程序所要实现的功能,可使用如下控件变量,如表3-1所示。

表3-1 主程序定义的控件变量

变量初始化的程序框图如图3-16所示。

图3-16 主程序的变量及其初始化

首先采用顺序结构,对方块的初始位置、超时事件执行速度、游戏得分等数据进行调用,对随机产生的新方块进行显示和记录。同时定义了其他编程中需要使用的控件,以便调用属性节点的值。

3.4.2 超时事件结构设计

事件结构包括一个或多个子程序框图或事件分支,结构处理时间时,仅有一个子程序框图或分支在执行。等待事件通知时,该结构可超时。当使用超时事件结构时,程序可以以一定速率持续运行。事件框的左上角,“超时”接线端指定了超时前等待事件的时间,以毫秒(ms)为单位。根据上节,可将初始化的速度控件接入,表示事件的等待时间调整为了200 ms,即俄罗斯方块可以以200 ms一格的速度进行下落。

在超时事件框内编写了层叠式顺序结构的程序,该部分的内容可以分为四个步骤展开。如图3-17所示,首先,方块所处的行位置会从初始化的-4开始,每经200 ms进行自加。

图3-17 行数自加

随后在第二个顺序框内,如图3-18所示,界面根据方块的行位置信息和方块元素的坐标分行信息和列信息各自累加,组建成新的数组,定义为“移动后的位置信息”,用于存放更新后的位置信息。另一方面,程序统计了方块的行数最大值,以便后续对方块是否落底进行判断。

图3-18 下落后方块的位置信息更新

紧接着,需要计算叠加的方块数,如图3-19所示。首先通过查询二维数组大小,索引得到方块移动后位置信息的最大行,并作为判断重叠的循环次数。移动后方块信息的每个元素坐标,需要代入到堆叠后的界面进行检查。如果检查到的坐标位置已经有方块存在,则叠加方块的数目会进行累加。

图3-19 计算重叠方块数

最后,游戏要根据当前的运行情况进行判定,如图3-20所示。如果方块尚未到达了最底行或叠加在其他方块上,则继续下落并显示在游戏界面上;否则就需要根据实际情况,做出继续产生新的随机方块、进行整行消除操作,或是终止游戏的命令。

图3-20 游戏运行情况的判断思路

根据图3-20所展示的流程可知,要让游戏界面能正常显示方块下落过程,需要两个条件结构。

通过比较方块最低行和界面行数的大小,可以知道是否达到最底行;由前一个顺序结构的分支统计的重叠方块,可知新方块是否落在了其他方块之上。对这两个条件的结果进行“与”运算,可以此判断方块继续下落还是产生新方块。由上述内容,可以编写对应的程序如图3-21所示。

图3-21 方块正常下落及显示

如果正常下落,则需要将正常下落的方块信息每隔200ms在游戏界面上更新一次。首先需要计算方块的行数,将其作为循环次数。然后使用移位寄存器,以“堆叠后的界面”为初值,不断索引下落过程中方块的位置信息,将索引到的位置用“T”填充在堆叠界面上,最终将此结果传送给游戏界面。

如果前一方块已经下落结束,则需要调用3.1节设计的“随机方块的生成和记录”子VI,从初始位置添加新的方块;随后,调用3.3节所设计的“整行消除”子VI,消除形成整行的部分,并将消除的行数进行累加,计入游戏得分;最后,对堆叠界面的最顶行元素做“或”运算。如结果为“真”,则弹出对话框,提示游戏结束,并退出事件结构,结束程序运行。上述过程可由图3-22的程序框图表示出来。

图3-22 方块完成下落后的程序框图3.4.3 按键事件结构设计

为实现俄罗斯方块的所有基础功能,还需要使用按键事件结构,从而控制方块的左右移动和旋转。在事件结构框添加新的事件分支,选择“键按下”,可以得到按键事件分支,进行按键功能的编辑。

图3-23 添加按键事件分支

(1)方块旋转在主程序中的实现

本文使用了4个分支的顺序结构,完成方块在按键控制下的一次旋转。前3个分支的程序设计如图3-24所示。其中,第一个分支调用了3.2节所设计的方块旋转子VI,实现方块的旋转并记录对应元素的坐标信息。随后的两个分支更新了方块的位置信息,并计算旋转过程中与堆叠界面元素的重叠情况。由于这两个分支的内容与超时结构中的两个分支完全相同,此处不再赘述。

图3-24 方块的旋转、信息更新与重叠判断

第4个分支中,程序对方块旋转后的位置和界面边缘进行比较。在没有重叠方块,且左右均没有越界的条件下,可以将旋转90°后的方块信息显示在游戏界面上,显示的方法同图3-21。值得注意的是,由于此处使用了三个条件进行布尔运算,因此可以使用布尔控件中的“复合运算实现”,如图3-25所示。

图3-25 方块的正常旋转与显示

如图3-26,如果方块旋转后越界,或是有重叠情况,那么就应该保持方块原来的转态。这里可以在原来旋转90°的基础上再进行三次旋转,从而恢复原状。

图3-26 方块旋转回初始位置

(2)方块左右移动在主程序中的实现

以方块左移为例,当“左”键按下,方块的列位置首先进行减1操作,如图3-27所示。

图3-27 左移操作时的列位置变化

随后进行方块的位置坐标更新,以及重叠判断,这两个分支的内容和图3-24相同。最后判断边界,如果没有超过边界且和堆叠的方块无重叠,则在游戏界面更新(该部分与图3-25相同);否则将列位置通过加1改回,如图3-28所示。

图3-27 方块移回

方块右移与前文思路相同,只是将列数变化方向与左移相反并比较右侧边界,如图3-28所示。

图3-28 右移过程中的边界判断

至此,便完成了俄罗斯方块所有基础功能的程序编写。当然,在实际运行中,还有必要对界面和参数进行适当的调整,优化项目外观和功能。

4 综合调试与运行效果4.1 程序调试

打开主函数的前面板,运行程序如图4-1所示。

图4-1 主函数的运行界面

从图4-1中不难看出,该程序可以充分借助各个控件的值,进行一系列运算,从而实现俄罗斯方块旋转、下降、消行、移动等基础功能。

但是仍存在一些问题亟待优化。首先,游戏界面不够简洁美观,堆叠界面以及右边的参数在游戏过程中没有显示的必要,反而在运行时会对用户产生视觉干扰;其次,方块的下落速度不可调,导致玩俄罗斯方块的时长增加。即便是第一个方块,也只能等待其慢慢地下落至底部,大大降低游戏体验;再者,点击运行或结束前一次游戏的对话框,随机方块就又重新开始下落,因此游戏缺少一个总的控制开关;最后,游戏得分只来自于消除行数,其实也可以根据产生的方块总数进行判断,这样更能科学地区分游戏的运行状态。

针对以上问题,对程序的前面板和程序框图进行进一步优化。

4.1.1 前面板的界面优化

由前文所述,对前面板的界面进行了一系列的优化。首先,调整前面板的界面大小,只保留“游戏界面”、“新方块”、“游戏得分”等必要的显示控件。其次,对“游戏界面”和“新方块”的元素进行染色和替换,使其在视觉上更加接近经典“俄罗斯方块”游戏配色。同时修改背景颜色,增加一些视觉装饰元素,并提前添加好开关控件和速度等显示控件。优化后的前面板界面如图4-2所示。

图4-2 优化后的前面板界面

该界面使用经典LCD显示屏的青灰色构成主题色。标题加粗并用了一些俄罗斯风格的剪贴画装饰。与原先的程序结构不同,用户点击开关控制才能开始运行游戏,因此有充分的时间阅读游戏界面右侧的操作提示。数值显示控件和“游戏界面”控件使用相近背景色,使主界面更加整齐居中,在视觉上更突出。底部的“文明游戏提示”模仿自微信小程序的《玩家须知》。

4.1.2 程序参数调整与优化

(1)方块下落速度调整

本文添加新的事件分支,对方块的下落进行增速或减速处理;同时添加了指针显示控件(首先将值初始化为1),对当前的下落速度进行“快”、“慢”两档的显示。如图4-3,以方块加速下落为例,分析程序的实现原理。

图4-3 速度增加原理

新建速度调节显示控件,通过大小比较,可以调节的指针只能在数字1和3的位置,并以2为步进值改变。调节速度的运算参数,将根据速度调节的值重新调整速度的大小。速度减小与其原理相同,如图4-4所示。

图4-4 速度减小的编程实现

(3)控制开关设计

设计控制开关如图4-5所示。

图4-5 控制开关设计

创建按钮型布尔控件,设置机械动作为“单击时转换”。开关按下后通过非门输出为“假”,由于堆叠界面只进行了初始化,所以首行检测不到方块,两者信号通过或运算可以使循环结构开始工作,随机方块下落;当堆叠界面的首行存在方块,或是鼠标再次点击开关,或运算输出结果为“真”,则停止循环结构。

这里对游戏结束的结果也做了改动。首先通过字符串连接函数,在对话框显示了游戏的最终得分;其次,在对话框弹出后,“开关控制”按钮被赋值为假,从而强制弹起。因此在点击对话框重回主界面后,需要再次点击开关才能使方块下落。

(4)游戏得分计算

游戏得分的计算如图4-6所示。

图4-6 游戏得分计算程序

游戏得分的规则是,每消除一行可以获得10分,界面中每叠加一个方块可以获得1分。将两类得分相加,更新至初始值为0的游戏得分“显示控件”中。由于要在游戏结束界面的弹窗显示游戏得分,这一顺序结构的分支处于游戏结束之前。

4.2 运行效果展示

运行程序,前面板在不同运行状态下的界面如图4-7所示。

图4-7 游戏运行效果展示5 总结

在本科阶段曾因课程设计,了解过MATLAB以及Visual Studio的GUI界面开发,但关于LabVIEW的学习还是首次。LabVIEW以数据流为编程核心,图像化、模块化的语音简明易懂。但是该平台含有非常丰富的控件和函数,想要精通绝非一朝一夕之功。

此项目旨在复刻《俄罗斯方块》这一经典游戏,许多的编程灵感来自于B站视频(BV1dV411v7ih),该作者从编程思想、LabVIEW的操作技巧等方面都提供了详尽的指导,在此一并感谢。当然,由于是刚接触这一软件平台,这一程序还有不少不够成熟的地方,后文将对该程序的特点和不足加以阐述。

5.1 程序的特点

(1)该程序建立了简洁的前面板,可以成功实现俄罗斯方块下落、旋转、堆叠、消行等基本功能。

(2)在此基础上,程序添加了开关和速度控制功能、修改了计分原则,使操作过程更加人性化。

5.2 程序的不足

(1)主程序中很多事件分支使用了相同的功能部分,例如边界判断、界面更新等。相比一次次复制粘贴,若是能根据具体目标设计成相应的子函数模块,也许能优化程序结构,使内容更加简洁可读。

(2)传统的俄罗斯方块使用的是四个按键,而这里的按键事件结构包含了5种按键的设置。原因在于加速下落这一功能编写存在障碍。原本的思路是,创建“键释放”事件,让“↓”键释放时,可以停止方块的加速下落。但是“键释放”事件本人并没有成功实现键位的编程调整,只好折衷新增事件分支,选取“↑”键由用户将下降速度手动减回。

(3)音效和背景音乐的添加尚未成功。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3