马 丽,薛根奇,吕海莲
(1.平顶山学院计算机学院(软件学院),河南 平顶山467000;2.平高集团有限公司焊接技术及压力容器实验室 河南 平顶山 467001;3.河南平高电气股份有限公司 河南 平顶山 467001)
基于Qt组件的俄罗斯方块设计
马 丽1,薛根奇2,3,吕海莲1
(1.平顶山学院计算机学院(软件学院),河南 平顶山467000;2.平高集团有限公司焊接技术及压力容器实验室 河南 平顶山 467001;3.河南平高电气股份有限公司 河南 平顶山 467001)
为提高经典益智游戏---俄罗斯方块的趣味性与高效性,提出了基于Qt组件的俄罗斯方块设计。在实现该游戏传统功能基础上,增加了添加障碍方块和旋转游戏区域等功能,显著提升了游戏的趣味性与高效性,带给玩家更好的游戏体验。该设计重点从游戏要素、游戏算法、方块运行判断等方面进行分析,最终通过运行游戏验证设计的有效性。
Qt;俄罗斯方块;碰撞检测;运行状态判断
俄罗斯方块游戏是最早的休闲益智游戏之一,是个老幼皆宜的小游戏,它适合无兴趣或无精力玩大型网络游戏的玩家[1-4]。
经过多年的发展,该游戏在网络已有多种语言的不同版本[5]。最常见的有QQ版和4399网页上的俄罗斯方块游戏[6]。QQ版俄罗斯方块游戏不仅画面设计优美、游戏背景颜色、音乐搭配合理,而且实现了联网对战功能。4399上的小俄罗斯方块游戏花样繁多,画面丰富多彩,吸引了不少‘面控’玩家。这两种火热的俄罗斯方块游戏的优点显而易见,但对网络的依赖性较大。因此文中基于Qt框架,设计一款电脑版的俄罗斯方块游戏,使玩家在无网络的情况下也能体验该游戏。俄罗斯方块是一款极易上手并且易于理解的益智类拼图游戏。这款小游戏使得它的玩家在进行一段时间的游戏后,普遍将这种再度组合的思维惯性应用到了眼前所看见的事物中,这种现象被称之为“俄罗斯方块的游戏效应”[7]。文中设计的俄罗斯方块游戏,在实现该游戏传统基本功能前提下,增加了添加障碍方块和旋转游戏区域等功能,实现了一款看似简单但功能繁多的俄罗斯方块游戏[8],让玩家尽情体验的乐趣。
QT框架是诺基亚开发的一款跨平台C++图形用户界面,允许真正的组件编程、易扩展。信号和槽是一种高级接口,应用于对象间的通信,是QT的核心。很多GUI工具包窗口小部件(widget)中,均有一个指向某函数的指针的回调函数响应触发的每个动作。而在QT中信号和槽取代了函数指针,且能携带任意数量和类型的参数,所有从QObject或其子类派生的类都包含信号和槽。当对象状态改变时,信号就由该对象发射出去,实现真正的信息封装,对象被当作一个真正的软件组件来使用。采用QT自带的Wigit()函数设计游戏界面,利用信号与槽机制将游戏界面上的功能按键与业务代码相关联。
俄罗斯方块游戏规则简单,屏幕上方随机产生不同形状的方块并以一定速度下落,玩家可控制方块的左、右位置以及旋转方块,使方块下落后充分利用屏幕空间。每当方块排满屏幕的一整行时,该行方块从屏幕上消失,其上的方块依次下降一行,玩家获得一定的分数。当方块堆积达到屏幕顶端的时候,游戏结束[9]。一个成功的俄罗斯方块游戏,主要实现游戏方块的预览、控制,游戏分数、等级更新等游戏操作提示功能[10]。本设计在实现传统俄罗斯方块基本功能基础上,增加了添加障碍方块和旋转游戏区域等功能。
2.1游戏功能接口设计
设计游戏类gamearae实现该游戏的各功能。利用类的构造函数GameArea::GameArea(int speed,QWidget*parent)初始化游戏,定义了默认的游戏区域大小、方块大小、方块下落速度等。用析构函数GameArea::~GameArea()回收资源。游戏的主要功能函数设计如下。
1)gamestart()函数,游戏开始接口。
2)setGameAreaColor()、setBoxBrushColor()改变游戏区域和方块颜色的接口。
3)setPlaySounds_MoveDown()、setPlaySounds_ItemChange()、setPlaySounds_MoveLeft()、setPlaySounds_Moveright(),方块左、右移动,以及变换下落时声音接口。
4)itemChange(),方块发生变换的接口。
5)Qpainter(),绘画图形的接口。
6)Qtimer(),定时器产生的接口。
7)Qrand(),随机产生方块的接口。
2.2游戏要素设计
俄罗斯方块游戏要素包括方块设计、控制设计以及结束设计等。
2.2.1方块设计
俄罗斯方块游戏通常有7种方块模型[11]。方块是俄罗斯方块游戏要素最基本的组成部分之一[12],良好的方块设计可以让玩家体验到游戏带来的乐趣。设计中,需要解决小方块绘制、图形随机出现、不同形状图形的存储数据结构、多线程控制等方面的关键技术[13]。
本俄罗斯方块游戏中设计了7种基本方块模型(Z字型、反Z字型、7字型、反7字型、竖字型、田字型、T字型)。每种方块均由4个小正方形组成,且有4种形状变化。故采用4*4矩阵设计方块,即由4个行高为4的小正方形按规则组成,矩阵中有颜色的表示有方块,无颜色表示无方块,用数组存储7种方块。故设计一个方块类(Myitem类),将矩阵上的方块按照坐标转化为二维数组的下标,实现矩阵和二维数组的对照。在4x4矩阵(二维数组)中,用0和1表示方块的位置,在1的位置上“画”上颜色则可以清晰的表示1个方块的形状。最后用QT自带的“画家”将图片用不同的颜色“画”出来,如图1(a)所示。每个4*4矩阵都有自己的横、纵坐标,通过矩阵逆时针旋转90°实现方块的形状变化。矩阵逆时针旋转后,每个小方块的坐标变换为:横坐标x1=3-y(旋转前的纵坐标)、纵坐标y1=x(旋转前的横坐标)。图1(a)Z形方块的另外3种形状变换如图1(b)、图1(c)图1(d)所示。无论怎样旋转,方块的形状都不会变化。其余6种方块形状变换方法与Z形方块类似,不再描述。为使设计的方块能在指定的游戏区域内运行,需定制坐标。左上角为方块的起始“0”坐标,从上往下,从左往右开始输出区域。将方块变化的坐标和游戏区域不变的坐标相结合,实现游戏区域的控制。方块的每次移动或旋转都会引起方块在游戏区域坐标的变换,每次变换后都需要将游戏区域与方块重新绘制。
图1 Z字型方块
2.2.2游戏控制设计
采用电脑小键盘的控制键控制方块运行。上键:方块有规律的变换方向,即根据玩家初始化时的方向依次变换;下键:控制加速降落或者直接坠落(取决于上面的功能按键设置),通过增加纵坐标来实现;左键:方块向左移动一个位置,通过减少横坐标来实现;右键:方块向右移动一个位置,通过增加横坐标来实现;其他键:方块不做任何变化,正常下落。方块下落时可使用左、右方向键控制方块左、右运动,同时也可使用上方向键循环的改变其形状。当方块到达边界或与其他方块碰撞时不能移动。
通过QT自带的“事件”,将硬件触发与设计的keypress-Event函数相结合,控制方块移动。按上、下、左、右不同的控制键,发出相应的硬件信号 Key_Up、Key_Down、Key_Left、Key_Right。系统会根据玩家键入的按键,判断、控制方块移动。若收到上述4种信号外的信号,则不能对游戏方块进行控制操作。
2.2.3游戏算法设计
为确保该游戏正常运行,游戏规定:当游戏开始或上一方块运行结束时,自动产生下一方块;方块运行过程中可移动或旋转;当方块堆满1行或者多行时,可消行。
2.2.3.1算法的数据结构
1)游戏方块(myitem)设计为含16个元素的二维数组,其中每一个元素代表方块在该位置是否绘图。即myitem[i,j]=1或0,分别表示在与此二维数组对应的4*4矩阵的坐标为(i,j)的位置上绘制与背景不同或相同的颜色。
2)游戏区域(gamearae)设计为含有200个元素的二维数组,其中每一个元素代表方块在此位置是否有方块。即gamearae[i,j]=1或0,分别表示在与此二维数组对应的10*20矩阵的坐标为(i,j)的位置上有、无方块。
2.2.3.2算法实现
1)初始化开始按钮,分别对方块与游戏区域赋值。
2)方块运动算法 利用QT的键盘方向键控制方块移动,方块在移动过程中进行碰撞检测。设键盘处理事件按键产生信号vigel,碰撞函数为ismoveend(),则方块移动算法描述如下:
①如果按下方向键的左键,发出Evevt(key_Left)事件,方块左移。判断碰撞函数ismoveend()中ismoveleft()函数>0?若是则可以移动,否则不能。
②如果按下方向键的右键发出Evevt(key_right)事件,方块右移。判断碰撞函数ismoveend()中ismoveright()函数<10,若是则可以移动,否则不能;
③如果按下方向键的下键发出Evevt(key_down)事件,方块下移。判断碰撞函数ismoveend()中ismovedown()函数> 0,若是则可以移动,否则不能。
3)方块旋转算法方块旋转判断itemchange函数中定义copymap指针、currunmap指针,与方块坐标StartX,则方块旋转算法为:若按下方向键的左键发出Evevt(key_up)事件,方块旋转。判断旋转函数startX<0,方块越界,需要重新确定方块的边界(startX=0)。若copymap&&currunmap=1,方块重叠,不能旋转,否则可以旋转。
2.3游戏界面设计
游戏界面设计采用QT自带的UI界面。根据前面设定的坐标建立一个20*10的Widgit窗口作为游戏区,行、列交叉处构成的方格即为一个方块的大小。方格大小设定后,游戏区域区的终止坐标为(右下角坐标(400,200));用gamearae类中的函数初始化游戏区域、起始位置、高、宽、小方块边长、图形出现位置等参数,完成指定区域的设计。
2.4游戏运行判断设计
方块、游戏区域设计完成,若要实现方块有条件地在游戏区域内移动,需判断方块是否可移动、可变化、可消行等。
移动判断:先假设方块可移动,保存现有游戏界面copymap,并绘出方块移动后的画面。然后再判断方块移动后是否有和其他方块重叠或者碰到边界,若无则可以移动,绘出移动后的界面,进行下一步操作,否则不能移动,还原上次保存的界面。判断是否重叠和方块的设计息息相关,如果移动后的方块在‘1’的部分上有重叠,则说明方块重叠,不能移动。若移动后下一步超过了边界或者与其他图形重叠,说明在左、右方向上不能移动,在下落的方向上,则说明该方块运行结束。边界的判断和游戏区域坐标有关,方块移动时对其纵、横坐标进行加减,加减后,若其纵、横坐标小于0则说明出界。
判断方块是否可左、右移的功能函数为ismoveleft()和ismoveright(),确认方块在4*4矩阵上的当前位置函数为currentItem_endPos()。如果方块左边界减去方块移动的步数≤0,说明游戏已经到达左边界,方块不能继续移动。将假设可以移动时保存的当前游戏界面copymap与移动后的方块进行相与运算,若结果为1,则说明方块重叠,方块不能向左移动,返回保存界面,进行下一步操作。
同理右移函数ismoveright()在确认好方块当前位置后,如果方块右边界加上移动的步数≥10,则说明游戏超出边界,不能向右移动。将假设可以移动时保存的当前游戏界面copymap与移动后的方块进行相与运算,若结果为1,则说明方块重叠,方块不能向右移动,返回保存界面,进行下一步操作。
重叠判断函数ismoveend(),利用currentItem_endPos()函数确认方块在4*4矩阵上的当前位置,若下边界加上下移的步数≥20,则说明方块到达下边界,方块运行停止。先假设可以移动一步,然后将假设可以移动时保存的当前游戏界面copymap与移动后的方块currentitem进行相与运算,若结果为1,则说明方块重叠,不能向下运拓,返回保存界面,该方块运行结束,新方块重新进行下一轮操作。重叠的判断则是利用方块的坐标与其所在行进行异或运算,相同为0不同为1,若异或结果为1则没有重叠。然后循环检测方块的16个坐标。
变换判断:首先要判断方块是否可下移。若可,则保存现有界面。然后假设可变换,并绘出变换后的图形,再判断是否有重叠或者超出游戏边界。若无则进行变换,将变换后的图形绘出来。若变换后和障碍物重叠或超出下边界,则方块不能变换,运行结束;若变换后超出左边界,则令方块靠左对其,即令方块的横坐标为0,纵坐标不变,然后绘出变换后的形状。若变换后超出右边界,则令起靠右对其,令方块的横坐标为20*4-4=76,纵坐标不变,然后绘出变换后的界面。若其在左、右方向上变换后与其他障碍物重叠且不超出边界,则不能变换,但可能下落。然后循环进行变换判断,直到这个方块运行结束,产生下一个方块。
设计itemchange()功能函数判断是否可变换,先保存当前图形到临时方块tempitem中,如果变换后方块的横坐标startX小于0,说明方块左越界,令startX=0,如果变换后方块的横坐标 startX+4*step(步数)大于 10,说明右越界,令startX=10-step。然后绘画出图片。
设计时定义了ismoveend()函数,先假设可变换,将假设可变换时保存的界面copymap与变换后的方块进行相与运算,若结果为1,则说明方块旋转后和别的图形有重叠,不能旋转。返回原来保存的界面,游戏继续下一步。方块旋转流程如图2所示。
图2 方块旋转流程图
消行判断:每个方块运行结束时,判断是否消行。可以一次消除一行,或者消除多行,消除多行和消除单行的原理一样[14]。当方块堆满一行或者多行时可消行。根据文中方块设计可知,若每行网格内全为‘1’,则表示此行已堆积满,需消除。此时纵坐标值比该行小的所有行下移一行,用户得分增加。继续向下检测,若下一行满行,消除,再继续往下检测,直到整个游戏区域检测一遍为止。检查完成后,该方块运行结束,产生下一方块。每次产生新的方块时触发重绘事件,重‘画’游戏区域和方块。消行功能函数clearrow(),利用将假设可以移动时保存的界面copymap的每一行与1进行与运算,若结果为1,则说明已满行,将整行的1全部修改为0即消行,且保存界面纵坐标全部减1,再循环检查整个游戏区域是否还有满行,若无则将游戏区域画出来。
该俄罗斯方块游戏实现了开始游戏、暂停游戏、重新开始、更改颜色、旋转游戏、网格显示、方块提示、打开声音、是否坠落、添加方块等功能。用户界面中,显示玩家姓名、级别、得分和消行数,方块在一定的区域内运动和变形[15]。
文中对经典的俄罗斯方块游戏,提出一种基于Qt框架的设计方法。该设计在确保该游戏传统功能的基础上,增加了添加障碍方块和旋转游戏区域等功能,显著提升了游戏的趣味性与高效性,满足了玩家在游戏中寻求刺激的需求,对类似的游戏开发也有一定的借鉴作用。
[1]刘步林.Delphi开发俄罗斯方块游戏[J].电脑编程技巧与维护,2015(2):26-31.
[2]刘峰国.漫谈经典游戏系列的起源[J].计算机与网络,2015(17):20-21
[3]于翀.JAVA开发网络化对战俄罗斯方块游戏的可行性[J].电子技术与软件工程,2014(11):271-272.
[4]Vista看天下.俄罗斯方块凭什么火了30年[J].现代青年(细节版),2014(8):63-65.
[5]曾庆维,冯镍.一种基于玩家水平的俄罗斯方块游戏[J].软件导刊,2014(1):25-30.
[6]赵志刚.基于J2ME的蓝牙联网俄罗斯方块游戏的设计与实现[D].山东大学,2013.
[7]张昱宏,康 翼,叶 喜.基于俄罗斯方块化的多功能家具设计[J].家具与室内装饰,2016(2):32-34.
[8]樊峰.基于FPGA及NIOS嵌入式处理器的俄罗斯方块游戏设计[D].武汉:武汉轻工大学,2013.
[9]于龙海,罗辰杰,王晓萍,等.俄罗斯方块的结构化汇编语言程序设计[J].单片机与嵌入式系统应用,2015(12):15-18.
[10]殷志坚,段晓磊.基于EasyX的俄罗斯方块游戏的设计和分析[J].科技传播,2015(21):137,157.
[11]王文举.C#语言开发俄罗斯方块游戏[J].电脑编程技巧与维户,2013(3):73-79.
[12]孟芸,朱肖安,罗刘敏,等.基于C语言的俄罗斯方块的设计与实现[J].硅谷,2014(23):19-20.
[13]杨桦,周春容.俄罗斯方块游戏中关键算法的分析与实现[J].电脑编程技巧与维户,2013(12):10-12.
[14]孟 芸,朱肖安,罗刘敏,等.基于C语言的俄罗斯方块的设计与实现[J].硅谷,2014(23):19-20.
[15]王西艳.俄罗斯方块游戏的设计与实现[J].办公自动化,2013(20):63-64.
Tetris design based on Qt components
MA Li1,XUE Gen-qi2,3,LV Hai-lian1
(1.School of Computer(Software),Pingdingshan University,Pingdingshan 467000,China;
2.Welding Technology and Pressure Vessel Laboratory of Pinggao group Co.,Ltd.,Pingdingshan 467001,China;3.Henan Pinggao Electric CO.,Ltd.,Pingdingshan 467001,China)
In order to improve the interest and efficiency of traditional classic tetris game,design scheme based on Qt components is proposed.On the basis of the traditional game function,added obstacle squares and rotating function such as game area,the interest and efficiency of the game is significantly increased,it bring much better experience to game player. The design key is focusing on analysis and judgment game elements,game algorithm and square running way,Finally the effectiveness of the design are verified by running the game.
Qt;tetris;collision detection;running state judgment
TN802
A
1674-6236(2016)21-0027-04
2016-02-24稿件编号:201602125
国家自然科学基金(61503206)
马 丽(1968—),女,河南辉县人,硕士,教授。研究方向:计算机方向教学和软件需求工程、模式识别与智能控制方向的研究。