1 绪论
1.1课题研究背景
如今,计算机系统的发展已明显地朝三个方向发展,这三个方向就是:巨型化,单片化,网络化。对于解决复杂计算和高速数据处理的问题仍然是巨型机在起作用,因而,目前巨型机正在朝高速及高处理能力的方向发展。单片机在出现时Intel公司就给其单片机取名为嵌入式微控制器。单片机的最明显的优势,就是可以嵌入到各种仪器、设备中。这一点是巨型机和网络不可能做到的。单片机在内部已集成了趆来趆多的部件,这些部件包括一般常用的电路,例如:定时器,比较器,EEPROM,D/A转换器,串行通信接口等。同时,俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它曾经造成的轰动与经济价值可以说是游戏史上一件大事。因此,对它的研究,无论从技术上,还是社会意义上看都是很有价值的。单片机在游戏上的应用是具有非常大的潜力的,它能将游戏带入到另一个阶段。
1.2课题发展概况
如今,游戏机风行的程度,是第一台电子游戏机的研制者诺兰-布什纳尔先生始料不及的。在全世界最大的城市,直至最小的村庄,从纽约最辉煌的游乐场,到高加索最小的乡镇儿童娱乐点,在千家万户,正在进行着千千万万这样的“战斗”,伴随着无数成功与失败,兴奋与懊丧。游戏机带来了一个全球性的疯狂症,其他任何娱乐与之相比都望尘莫及。然而,究竟是什么原因使游戏机如此风行呢? 在回顾了游戏机发展简史之后,我们不难悟出,技术进步在游戏机发展过程中起到了极大的促进作用。
第二次世界大战以后,电子计算机技术得到了突飞猛进的发展。先是由晶体管代替了笨重的真空管,后来出现了集成电路和大规模集成电路,使电子计算机一代一代实现更新,同时软件技术也发展迅速。在美国,集中了许多计算机软件的设计人才,他们工作之余,时常喜爱编一种能与人斗智的“游戏”,以此来锻炼编程的能力。这种“游戏”花样繁多,但其特点都是利用计算机软件事先设计好的“分析”、“判断”能力反过来与人较量。由于不断修改更新,使计算机的“智力”水平与人难分高低。
随着深蓝计算机与人的棋类对决,到现在的PSP游戏机或者是家庭用的X-BOX游戏机,游戏机的技术是日益的发展、进步。
但是,技术进步绝不是游戏机风行的唯一因素。随着终端设备开发能力的加强,作为娱乐终端的游戏机也得到了很大程度的发展。只有得到了游戏终端技术的支持,才能做出更新、更高难的游戏。这也加速了游戏机在全球风行程度,所以对于游戏机的研究和设计具有很重要的意义,这也是本课题研究的来源。
1.3课题主要解决的问题及功能
现如今,游戏风靡全球,各种游戏层出不穷,大到网络型的复杂游戏,小到手机游戏、单机游戏、智力游戏等简单游戏。但是这种简单也是相对于网络游戏等大型游戏而言的,小游戏本身的代码还是相当繁杂,它要执行一系列指令才能正确的完成一个简单的操作,才能按照玩家的意志工作。所以我们现在见到的游戏多是在基于电脑这种高速执行指令的平台上运行的,脱离了它就什么事都做不了了。那么俄罗斯方块这种小游戏能否在单片机上编出来呢?答案是肯定的,所以我就根据小游戏机设计了这款游戏,可以选关,可以计分,当达到一定的分值自动升级。难度会越来越高,速度会越来越快。
2 方案设计
2.1方案论证
2.1.1程序部分
首先,我们编写的这个游戏是一个小型游戏,实现的功能比较简单,不像大型游戏那样功能复杂,它只要控制俄罗斯砖块放到正确的位置即可,难度随着砖块的增多而加大,对于实现这样一个功能,程序不是太复杂,用一块单片机足以达到目的。
其次,它的控件也比较少只有4个方向键和2个辅助的功能键,这些控键在Proteus中用弹跳式按键代替即可。
第三,游戏地图相对比较小、画面简单,只有几个图形,这些在一块稍大的液晶屏上就足以显示,用不着电脑显示屏。
第四,就编程语言方面来说,编写这样一个简单的小游戏不需要什么高级的语言,C语言或汇编语言就足以完成,C语言是一种通用型的语言,编程灵活、可读性强、移植性好;汇编语言是一种直接面向硬件的基础语言,最接近机器语言,执行速度快(本游戏采用C语言编写)。由以上几点可知:单片机上运行推箱子游戏在硬件和软件两个方面都是可行的。
2.1.2硬件部分
硬件部分我们主要使用的芯片是51单片机,有AT89C51、AT89S51、STC89C51、STC89C52几种型号可供选择。首先明确一点,这几个型号都属于51单片机,程序和电路是通用的。其中AT89C51是美国ATMEL公司生产的,下载程序需要专门的高压编程器,现在已经停产,故不作考虑。AT89S51是美国ATMEL公司生产的,可以直接通过ISP线下载程序,已经替代了AT89C51。STC89C51是台湾宏晶公司生产的,可以直接通过串口下载程序,相较AT89S51来说会更加便利。STC89C52与STC89C51师出同门,是属于51单片机的,这一点毋庸置疑,完全符合设计的要求。其次,STC89C51或AT89S51的程序存储空间只有4KB,有时候会不够用,而STC89C52有8KB的程序存储空间,而且价格相同,所以在我们本次的设计中选择了STC89C52。
2.2设计要求
现如今,游戏风靡全球,各种游戏层出不穷,大到网络型的复杂游戏,小到手机游戏、单机游戏、智力游戏等简单游戏。但是这种简单也是相对于网络游戏等大型游戏而言的,小游戏本身的代码还是相当繁杂,它要执行一系列指令才能正确的完成一个简单的操作,才能按照玩家的意志工作。所以我们现在见到的游戏多是在基于电脑这种高速执行指令的平台上运行的,脱离了它就什么事都做不了了。所以我就根据小游戏机设计了这款游戏,通过一系列主控按键进行操控,可以选关,可以计分,当达到一定的分值自动升级。难度会越来越高,速度会越来越快。
3 系统硬件平台设计
3.1 STC89C52单片机概述
STC89C52是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程Flash 存储器。使用Atmel 公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。AT89S52具有以下标准功能: 8k字节Flash,256字节RAM,32 位I/O 口线,看门狗定时器,2 个数据指针,三个16 位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89S52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
3.2 STC89C52单片机最小系统
单片机最小系统主要由电源、振荡、复位电路以及扩展电路等部分组成。在本设计中,扩展了液晶显示接口。因此,本设计所涉及到的最小系统如下图所示。
3-1STC89C52最小系统
Fig3-1 STC89C52 Minimum System
3.3电源系统
电源电路。对于STC89C52单片机来说,电压范围在3.3-5.5V都能工作。我们现在采用2种方式给单片机,电池盒(3节5号电池)和USB(电脑USB,移动电源,手机充电器等)
图3-2电源电路
Fig.3-2 Power System
3.4复位系统
MCS51单片机通常采用上电自动复位和按钮复位两种方式。通常因为系统运行等需要,常常需要人工复位,本设计采用按钮复位的方式,即按下开关一定时间就能使RTS引脚端为高电平,从而使单片机复位。同时,简单复位电路中,干扰信号易串入复位端,由此可能会引起内部某些寄存器错误复位,这时可在RST引脚上接去耦电容。在STC12C5A60S2单片机中有两个复位端口,即RST/P4.7、RST2/P4.6,当晶振频率小于或等于12MHz时,使用RST端口。由于本设计使用外接12MHz的晶振作为振荡时钟,所以采用如图3-2所示的复位系统。
图 3-3 复位系统
Fig 3-3 Rest System
3.5时钟电路
单片机系统里都有时钟电路,在单片机系统里晶振作用非常大,全称叫晶体振荡器,它结合单片机内部电路产生单片机所需的时钟频率,单片机晶振提供的时钟频率趆高,那么单片机运行速度就趆快,单片机的一切指令执行都是依靠单片机晶振提供的时钟频率。
晶振通常与锁相环电路配合使用,以提供系统所需的时钟频率。本设计中STC89C52使用12MHz的晶体振荡器作为振荡源,由于单片机内部带有振荡电路,所以外部只要连接一个晶振和两个电容即可,电容容量一般在15pF至50pF之间。如图3-3所示即为本设计的振荡电路。
图 3-4 时钟电路
Fig 3-4 clock circuit
3.6程序下载系统
单片机系统的传统编程方式是先将单片机从电路板上取下,放入专用的编程器进行编程,再放入电 路板进行调试。其缺点是频繁拔插器件容易损坏器件的引脚;如果频繁的调试程序,必须重复拔插 ,大降低了开发效率。ISP(在线系统编程)技术是一种无需将存储芯片从嵌入式设备上取出就能对 其进行编程的过程。其优点是,即使器件焊接在电路板上,仍可对其进行编程。在线系统可编程是 Flash存储器的固有特性(通常无需额外电路),Flash几乎都采用这种方式编程。 ISP的实现相对要简单一些,一般通用做法是内部的存储器可以由上位机的软件通过串口来进行改写 。对于8051系列单片机来讲可通过SPI接口或其它的串行接口接收上位机传来的数据并写入存储器中 。而上位机PC机与下位机单片机通过RS-232串行接口总线进行的串行通信。8051系列单片机带有一个全双工的串行接口,因此用RS-232串行接口总线非常方便。[2]PC机配置RS-232标准接口,RS-232信 号电平为负逻辑(逻辑“0”为+12V;逻辑“1”为-12V),8051单片机输入、输出电平为TTL电平 (逻辑“0”为小于等于0.5V;逻辑“1”为大于等于2.4V)。所以8051单片机与PC机间点对点异步 通信需加电平转换电路,否则将烧坏TTL电路。MAX232是MAXIM公司生产的电平转换器件,只需在外 部接入相应的电解电容即可。因此,本设计采用直连串口线进行串口通信,其中STC12C5A60S2的 P3^0/RXD和P3^1/TXD分别和下载器的第10管脚/T和第9管脚/R相连,串口线的第5管脚接地,2、3管 脚和下载器的7、8管脚相连。具体电路如图2-5所示。
图3-5 程序下载系统
Fig 3-5 Program Download System
3.7 LCD液晶显示电路
128X64是一种具有4 位/8 位并行、2 线或3 线串行多种接口方式的点阵图形液晶显示模块;其显示分辨率为128×64.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4 行16×16 点 阵的汉字. 也可完成图形显示.低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶 显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
图3-6 LCD液晶显示接口电路
Fig 3-6 Liquid Display Interface Circuit
3.8操作控制接口
操作控制模块是智能俄罗斯方块游戏系统的输入器件。控制器包括六个按键,分别为:向左/速度递减、旋转、向右/速度递减、暂停、快速下降、确认。如图2-8所示为控制器的接线图。与单片机的具体接口可根据实际设定。
图片3-7 控制模块接口
Fig 3-7 Control Interface
4 系统软件平台构建
4.1μVision简介
μVision是德国Keil公司开发的单片机IDE软件,最初主要用于8051系列单片机,目前也有支ARM系列单片机的专用版本MDK-ARM。本设计使用的是keilμVision3版本的开发软件进行程序开发。
4.2设计方案论证
首先,我们编写的这个游戏是一个小型游戏,实现的功能比较简单,不像大型游戏那样功能复杂,它只要控制俄罗斯砖块放到正确的位置即可,难度随着砖块的增多而加大,对于实现这样一个功能,程序不是太复杂,用一块单片机足以达到目的。
其次,它的控件也比较少只有4个方向键和2个辅助的功能键,这些控键在Proteus中用弹跳式按键代替即可。
第三,游戏地图相对比较小、画面简单,只有几个图形,这些在一块稍大的液晶屏上就足以显示,用不着电脑显示屏。
第四,就编程语言方面来说,编写这样一个简单的小游戏不需要什么高级的语言,C语言或汇编语言就足以完成,C语言是一种通用型的语言,编程灵活、可读性强、移植性好;汇编语言是一种直接面向硬件的基础语言,最接近机器语言,执行速度快(本游戏采用C语言编写)。由以上几点可知:单片机上运行推箱子游戏在硬件和软件两个方面都是可行的。
4.3俄罗斯方块游戏设计
4.3.1游戏功能简介
俄罗斯方块游戏的规则很简单,当方块从屏幕上方落下来时,玩家控制方块的位置以及旋转方块,巧妙地安排布置达到充分利用屏幕空间的目的。每当屏幕的一整行被方块排满时,作为奖赏,整行从屏幕上消失,剩余的方块依次往下降一行。当方块堆积达到无法再落下方块的时候,游戏结束。本设计中游戏主要的功能点包括:
(1)每4个小方块可以组合成一组方块群,游戏共有7种方块群,每次随机产生一种;玩家使用向左、向右、快速向下这些按键控制方块的位置,旋转按键控制方块顺时针旋转。在主控制手柄上还有退出、暂停按钮,可以实现随时切换到启动时的状态和暂停游戏的功能。
(2)在程序设计中加入了游戏难度(即方块的下落速度)选项,来让玩家自己决定游戏的难度,同时每消除三十行,系统会将游戏难度(即方块的下落速度)加一,来增加游戏的多样性。这样不仅丰富了俄罗斯方块游戏的功能,而且使其更具趣味性。
(3)在游戏的运行过程中,玩家通过留个按键进行操作,每消去一行,系统就给玩家加一分,在方块到顶端后,游戏结束,系统会结算并显示出玩家的游戏分数。
4.3.2 系统界面的设计
(1)菜单选项界面
当玩家将本设计的作品上电启动后,系统首先在LCD显示器件上呈现一个动态的开机动画。然后,系统会提供游戏难度(即方块的下落速度)的选择界面,通过按键“向左”和“向右”可以对游戏的难度(即方块的下落速度)进行选择。通过“确认”按键可以确定自己的选择并开始游戏
(2)游戏界面
游戏的界面主要提供了:游戏区域、显示分数、显示速度、下个图形,按键提示等部分组成,显示了玩家在游戏中所需的基本信息。
图4-1 游戏界面
Fig4-1 Game interface
4.3.3 游戏系统“枚举算法”概述
本文绕开了涩难懂、比较复杂的“矩阵算法”,提出了另一种“枚举算法”来实现这个经典游戏。“枚举算法”没有复杂的数学理论、避免了在程序中大量使用矩阵运算公式,设计思路清晰、明了,非常适合游戏设计的初学者理解和实现。
所谓枚举算法,就是直接枚举出游戏中各图块的基本形状和它们的旋转形状,然后控制每一种不同形状的方块在游戏戏中的产生、移动、旋转、落下、填满和清除等游戏过程。
4.3.4 俄罗斯方块造型设计的方法
众所周知,俄罗斯方块一般有七种基本形状,每个基本形状都由4个正方形的小方块构成。利用小方块不同的摆放位置,可产生19种旋转型图块。这七种图形分别是“I型”、“L型”、“反L型”、“Z型”、“反Z型”、“口型”、“T型”。如下图所示。
图4-2:方块模型
Fig4-2 Square model
本系统在构造19个方块模型时的思路是:定义一个数组,用以存储各个模型中4个小方块的顶点坐标。比如L型,其数据结构为{0,0,0,4,0,8,4,8}。其中,每两个数据为一个小正方形的列、行坐标,如下图所示。由图可知,整个界面的坐标原点在左上角,分别向右、向下作为横轴的正方向和纵轴的正方向。图中每一格代表了LCD12864中的连续四行,第1格的坐标是(0,0);第2格的坐标是(0,4);第3格的坐标是(0,8);第4格的坐标是(4,8);其它图块也按此方法编辑数组内容。
图4-3 L型
Fig4-3 L Shape
4.3.5 随机产生俄罗斯方块的方法
(1)产生随机数的理论依据
为了实现随机落下各类方块图形,游戏过程序中必须抽取随机数来确定方块的类型。随机数是一个既简单又复杂的问题。
本设计采用众所周知的线性叠加法,虽然没有完美的方法产生随机数,不过线性叠加法是一个合适的方法,它彻底解决了8位机随机数的问题。如果从一个足够长的数字序列中的某一个点取出一边串的数字,那么这些数字就看似随机。这个开始的点(数字)叫做种子。如果从相同的点(种子)开始,将会得到相同的数字,这是因为我们是从固定的序列中取数字(所以叫伪随机)。但这却是一个有用的特性,我们可以每次从不同的点取数,即改变种子,从而可以实现真正的随机。
(2)“线性叠加法”的概况
“线性叠加法”其实只涉及二个内容即:乘法和加法。只需三个步骤即:第一,为了取得新的种子,旧的种子与一个常数A相乘;第二,所得的结果和第二个常数C相加;第三,新的种子就是第二步结果的低32位。保留低32位很重要,用来获得下一个种子。计算公式为:
种子=A*种子+C
此公式在几何图中表示为一条直线,而且新种子由旧种子反复相加得来,所以叫线性叠加。随机函数的关键在于选择优秀的“常数A”(也叫乘数A),其实也就是选择了一个固定的数字序列。“常数C”,不像乘数A那样重要,但是一定是个奇数。事实上,C可选1。因为奇数(旧的种子)乘奇数(乘数A)是奇数,再加奇数(常数C)将会是一个偶数学偶数(旧的种子)乘奇数(乘数A),加奇数(常数C)将会是一个奇数。如此种子会在奇数和偶数之间转变。因为种了的变化足够随机,所以种子的值可以作为8位或16位随机数。
(3) Keil C51中“线性叠加法”的实现方法
在Keil C51中生成伪随机数需要用到两个函数,一个是srand(unsigned int seed),一个是rand()。首先给srand(unsigned int seed)提供一个种子,该种子为unsigned int类型,其取值范围从0到65536,srand(unsigned int seed)根据这个种子会由上述特定的公式生成一个随机数序列;然后调用rand(),它会依次从这个序列中返回一个数,其值在0 到32767之间。因随机数函数rand()函数实际上是线性随机的,如果在不指定srand(unsigned int seed)的种子的情况下,它每次都使用默认的种子,因此生成的序列会是同一个,所以会取到相同的数字序列。这可能会导致每次重新运行游戏时其随机数结果都是一样的。为了解决该问题,本设计在玩家进入游戏时读取按键按下瞬间定时器T0的计数值,作为srand(unsigned int seed)的种子。从而实现真正的随机。
(4)随机数程序流程图
下图为随机数程序的流程图
图4-4 随机数程序流程图
Fig4-4 Ramdom process flow program diagram
4.3.6 俄罗斯方块平移的实现方法
方块产生后,需要用全局变量来保存方块在游戏map区中的行坐标和列坐标。方块的平移包括左移和右移两种情况,无论那种情况都要首先进行合法性判断。
(1)俄罗斯方块平移特性
在本设计中规定当按下一次左移或右移按键时,map区中的当前图块就左移或右移一个正方形的宽度。而一个小正方形的宽度,则对应着LCD12864中的4列。
(2)平移合法性判断
平移的合法性判断经较简单,只需判断它旁边相邻位置是否被填充即可。
(3)平移算法的实现
在程序中,当有任意一个平移按键被按下时,系统接收到信号,然后调用平移函数进行判断其合法性,得到该函数的返回值为1后,再进行平移操作。其程序流程下图所示。
图4-5 平移算法流程图
Fig4-5 Translation algorithms flowchart
4.3.7 俄罗斯方块旋转的实现方法
(1)俄罗斯方块旋转图形概况
方块旋转是一个游戏实现的关键问题,实现旋转的数学方法有多种,如矩阵变换法、枚举法、索引法等。本文前面已经论述了此次设计采用枚举的方法,对19种俄罗斯方块造型进行构造。游戏过程中,每一种基本方块都要做旋转控制,于是就产生了旋转后的方块形状,本文将其称为“旋转型”。
基本型中的“I型”,只有一种旋转型,即由竖直旋转90度后成为水平。因此,基本型加上一种旋转型,共有两种形状。
基本型中的“L型”和“反L型”有三种旋转型,将它按顺时针每旋转一个90度就产生一种旋转型,可以旋转三次,得到三种不同的旋转型,因此,它的三种旋转型加上其基本型,“L型”和“反L型”方块分别有四种形状。
基本型中“Z型”和“反Z型”可以顺时针旋转一次90度,加上他们的基型分别有两种形状。
基本型中的“T型”有三种旋转型,将他按顺时针旋转一个90度就产生一种旋转型,它可以旋转三次,得到三种不同的旋转型,因此,它的三种旋转型加上其基本型,“T型”方块共有四种形状。
基本型中的“口型”方块没有旋转型,在游戏中只有一种形状。
综上所述,七种基本型方块,因旋转产生了不同的旋转型,这些旋转型加上他们的基本型,整个游戏中,共有19种不同的方块形状。
本设计实现旋转操作的具体方法,可分为两类,一类是I型的旋转策略;另一类则是其余17种基本型的旋转策略。
(2)旋转合法性判断
方块做顺时针旋转,每次旋转90度。本设计规定只要旋转后到达的地方未被填允,方块就可以进行旋转操作。
(3) I型的旋转策略
为了在视觉上实现I型的顺时针旋转,本设计采用位置错落的方式来实现。其具体过程下图所示。
图4-6 I型的旋转方法
Fig4-6 The rotation method of I shape
当落下的图块是图①所示时,其旋转周期为 ①——②——③——④——①。
当落下的图块是图②所示时,其旋转周期为 ②——③——④——①——②。
之所以把I型的旋转变换单独拿出来讨论,是因为I型只有基本型和旋转型共两种图块。如果在当前位置直接按这两种图块的坐标数组进行图形切换,则无法实现顺时针旋转的视觉效果。所以,在旋转处理程序中,当要旋转的当前图块为I型及其旋转型时,就要改变当前列、行这两个全局变量的值。
(4)其余17种基本型的旋转策略
除了I型的旋转比较复杂外,其余17种类型的方块只需按各自旋转的顺序在当前位置用已经编辑好的坐标数组来实现旋转即可。
4.3.8 俄罗斯方块下移的实现方法
在整个游戏过程中,方块是不断向下运行的,其下移特性为:方块每次下移的格数对应着LCD12864屏幕中的一行。具体程序实现流程下图所示。
图4-7 下移判断程序流程图
Fig4-7 Moves down judgment program flowchart
4.3.9 满行检测及消行功能的实现方法
随着方块的不断累积,方块每次下落到不能再运动时,系统就会检测游戏map区,当检测到map区中某一行堆积满后,系统就消去此行,作为奖励,其上方的方块群则依次下落一行。系统满行检测和消行功能是通过“满行检测及消行”函数实现的,即在每个图块落定和下一个图块未出来之前,按页扫描游戏map区,每半页算一行。若检测到某行被填满,则消去此行,并将其上方的图块往下移动相应的行数。
具体程序实现流程如下图所示。
图4-8 满行检测程序流程
Fig 4-8 Full line detection processes
4.3.10 游戏积分的计算方法
在游戏系统中,积分体现了玩家在此次游戏中的操作情况。本游戏系统加入了积分功能,玩家每消去一行,就能获得1个积分,最终会在游戏过程中进行结算并在结束时反馈给玩家。
图 4-9 积分系统程序流程图
Fig 4-9 Score system program flowchart