黄近秋,黄惠洪
目前,在中国乃至世界,游戏产业[1]已经逐渐成为微控制器领域的一个相当庞大以及重要的分支,而关于这方面的高级人才仍甚是缺乏,很多初学单片机的朋友都会对其庞大而复杂的机制感到困惑。本文以经典的推箱子游戏规则为基础,趣味而有序地对这个游戏从需求分析到整体方案进行了全新的设计。
首先运行游戏并载入相应的地图数据,屏幕上出现一个推箱子工人,其周围是预制好的地图、围墙、人可以行走的通道、几个可以移动的箱子和游戏胜利结束时安放这些箱子的目标位置。如图1所示。
玩家先通过功能按键选择希望到达的关卡,再通过键盘操纵推箱子工人的位置。当工人靠近箱子并朝箱子位置移动的时候,箱子在其移动方向没有被其他物件(箱子或者墙)
所阻碍的情况下可以被移动,并实时记录游戏的步数与所用的时间,当所有箱子被移到指定的安放位置后,则胜利通关并进入下一关的游戏。在游戏过程中,若遇到死局,可以按
返回键回到本次游戏的最初界面,但是所走的步数与时间均会累加。当玩家希望选择另一关的时候,可以按重选关键退出选择另一关游戏,不管系统处于何种状态下,均可实现关机动作,关机后也可开机继续游戏。
图1 第8关游戏界面
该游戏的系统硬件设计原理框图如图2所示。
系统硬件电路[主要由电源、AT89C55单片机、单片机复位电路、时钟电路、键盘和液晶显示模块等部分组成。系统要显示的信息通过P2口送到LCD液晶显示器;复位电路使单片机的片内电路初始化,使单片机从一种确定的状态开始运行;时钟电路用于提供单片机内各种微操作的时间基准;电源电路为各个电路提供稳定的+5V电源。
图2 系统硬件设计原理框图
电源电路如图3所示:
图3 电源电路
三端稳压芯片7805把9V输入电压稳压成5伏直流电源提供给单片机系统使用,右边两个电容是5伏电源的滤波及去耦电容,电阻和绿色的LED组成5伏电源的工作指示电路,只要电源部分正常,绿色的 LED(D4)就会点亮,用户可以根据这个 LED来判断整个电源部分是否工作正常。
键盘在单片机应用系统中,实现输入数据、传送命令的功能,是人工干预系统的主要手段。本文的键盘电路包括两个相对独立的键盘,直观地根据有无控制线的结构分为有线键盘和无线键盘。有线键盘即通常说的独立式键盘。如图4所示:
图4 独立式键盘
本游戏还可使用无线键盘进行操作,其原理跟独立式键盘原理一样,都是要使得单片机相应的引脚产生预期的高电平或低电平,从而达到无线遥控控制[6]。
液晶显示模块与单片机的连接如图5示:
图5 液晶显示模块
本文选用TS160128液晶显示模块,它不仅可以显示字符、数字,还可以显示各种图形、曲线及汉字,并且可以实现屏幕上下左右滚动、动画、闪烁、文本特征显示等功能。本液晶模块内有T6963C液晶驱动控制器。根据模块硬件的要求,必须在复位端接一阻值为5K的上拉电阻,VEE端接一阻值为 20K的下拉电阻,并且分压到 Vadj(CON)端用于屏幕亮度的调节。
定义核心数据结构,定义一个二维数组 map_define来进行地图定义,定义map来存放各关的地图,用于记录屏幕上各点的状态,其中,“0”表示空地,即什么都没有;“1”表示推箱子工人;“2”表示墙壁;“3”表示箱子;“4”表示目的地;“5”表示箱子被放在目的地上,即合成物。
对整个软件进行功能模块的划分:①初始化——主要是液晶屏幕的初始化跟中断设置;②选项——选择进入游戏、关于或者是关机;③游戏地图初始化,并根据各关的要求在屏幕上输出空地、墙、箱子、目的地、合成物和人,及其他信息;④进入游戏循环——这个游戏主循环时等待按键,当接收到上下左右键时执行相关的操作,接收到关机时退出游戏,接收到返回时返回到本关开头,接收到重选关时退出游戏进入关卡选择,接收到无效按键时做忽略处理;⑤判断是否过关——箱子的数目和目的地的数目是一样的,所以函数每执行一次操作就判断是否所有箱子都已经安放好,即都移到了目的地上,检测地图中是否还有“目的地”这一状态值的区域,如果有,则还没有完全放置好所有的箱子,否则,胜利结束游戏。
3.1.1 系统的主流程图
图6 系统的主流程图图
系统的主流程图如图6所示,其中power=0为待机;gamemode=1为游戏模式;rechoice=1表重选关;e2为选择入口变量。
3.1.2 中断服务程序
中断服务程序用于处理键盘被按下后系统的动作,其实现的流程图如图7所示。
图7 中断服务程序流程
在完成了整体框架的搭建后,接下来将对整个游戏的核心进行实现了。首先,可以先设计出游戏的核心数据结构(包括这些数据的存取方式),接着再根据游戏的特性设计出实现算法,最后就要将算法融入到与用户交互的各个环节中去。
3.2.1 地图与内部数据结构的设计
目前为止,已经完成所有动作数据的运算和处理,剩下的工作就是将这些数据图像展现在屏幕上,并实现交互。地图即游戏区域,对于整个游戏区域的绘制,采用分块绘制的方法,将整个游戏区域分成若干个很小的块状区域,然后根据该区域在地图中对应存储位置的状态值绘制地图。它是由多个纵向和横向分布的小方块组成,例如图8中的小方块A和B。本游戏的行列个数分别为12和14。
而在游戏的某一瞬间,整个游戏区域的图像总是由这些小方块根据不同的状态分别显示后构成的。需要显示的状态有可行走的空地、不可通过的墙壁、箱子、工人、目的地,合成物。
我们首先要定义一张空白的游戏地图,如图8所示:
图8 地图区域示意
idata uchar map_define[12] [14] =//定义地图
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, };
定义了这样一张空白地图之后,我们可以很方便地使得各关的游戏地图得到编辑和更新改变,可以用文件的方式进行各关卡游戏地图的存储。这里将函数名称定义为map[] [14] [12] ,其数据的具体存储方式如下所示(图9为其对应的游戏地图的显示效果):
unsigned char code map[] [14] [12] = //g=0,第 1 关
图9 第一关游戏
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,4,2,0,0,0,0,0,0,0,0,0,2,0,2,2,2,2,0,0,0,0,2,2,2,3,1,3,4,2,0,0,0,0,2,4,0,3,0,2,2,2,0,0,0,0,2,2,2,2,3,2,0,0,0,0,0,0,0,0,0,2,4,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, };
从以上数据我们看到,一个文件里面可以包含若干个地图的数据,而每个地图的开始我们可以定义“[g] ”这样的字段来标识开始,其中的g表示地图的序号,接着就是地图的数据内容实体,设计好数据的存储格式后,剩下的工作就是将这些数据图像展现在屏幕上,并实现交互,对于整个游戏区域的绘制,这里仍采用分块绘制的方法,将整个游戏区域分成若干个很小的块状区域(如以上介绍),然后根据该区域在地图中对应存储位置的状态值绘制其图像,最后将这些方块组合就构成了整个游戏区域,图10所示为该函数的流程图实现。
图10 地图构建流程
对于游戏区域的每个方块,函数体都根据其所对应位置的状态值调用相应的函数进行绘制,并在绘制直线时先计算出该方块区域所在游戏区域的位置(左上角的坐标位置)。
3.2.2 物体移动的算法设计
大多数的游戏都是通过与用户的交互并根据具体情况来做相应的运算处理的,在整个推箱子的游戏过程中,用户总是通过键盘操作界面的显示来实现交互。下面就从不同的角度来分析这个游戏的特性。
假设:游戏过程中的某一瞬间,工人在某个区域,此时游戏接收到用户的按键动作指示并按照游戏规则判断出该动作应该做出的响应。该响应是在没有违反游戏规则的情况下使工人执行用户指示的运动,对违反游戏规则的指示则不予以响应。分析了工人将会遇到的所有情况,以便归纳出动作的算法。图11:
图11 工人移动状态分析示意图
图中的符号含义如下所示。
假设移动趋势方向向右,其他方位移动趋势的情况也可以通过变化坐标方向,转为上面向右的情况。上图列出工人可能遇到的所有情况,在前面3种情况中,只要根据前言的物件就可以判断出工人是否可以移动了(按照指示方向移动),移动后的位置状态数据只改变两个区域;而第4种情况是工人的前方为箱子,需要深入判断箱子前方的状态才能判断出工人是否可以移动。所以要完全判断出操作指示是否可执行,需要 2个工人前方的位置状态值,移动后的位置状态数据改变了三个区域。而要判断位置状态得出执行动作,
则需要按照前面分析工人遇到的所有情况去处理,接下来就可以实现这些子模块了。包括以下两个方面:
(1) 键盘操作指示采集(用户交互),见中断服务程序。
(2) 人和箱子的移动判断
函数体对方向按键的处理部分,处理函数首先要根据移动的趋势计算出工人当前位置的前两个区域的位置。其具体实现流程如图12:
图12 人和箱子的移动判断流程
本文以经典的推箱子游戏规则为基础,构建了相应的硬件平台,并通过若干子地图构建整个游戏区域,根据操作规律设计了灵活的控制算法,通过TS160128点阵式液晶为载体显示数据,最后采用 C语言进行软件设计。测试结果表明,本设计达到了具有人性化的操作和美观的页面效果。
[1] 樊永显,许永,张向文,潘明,黄冬梅.基于STC89C54RC/RD+单片机的游戏系统设计[J] .湖南工业大学学报,2007,(05):66-69.
[2] 饶庆和.MCS-51单片机实用技术[M] .电子工业出版社,2003.4.
[3] 楼然苗等.51系列单片机设计实例[M] .北京航天航空大学出版社,2003.3.
[4] 李群芳等.单片微型计算机与接口技术(第 2版) [M] .电子工业出版社,2005.1.
[5] 郭勇等.Protel 99 SE印制电路板设计教程.机械工业出版社[M] ,2004.6.
[6] 张昊晔.基于无线传输的游戏机操纵系统设计[J] .信息技术,2008,(07):159-161.
[7] 罗伟坚.Visual C++经典游戏程序设计[M] .人民邮电出版社,2006.2.``