第六章 打地鼠
第一节 游戏描述
- 时间因素:以秒为单位限定游戏时长为60秒;
- 空间因素:用户界面分上中下三个部分,顶部显示命中率及得分,中部显示剩余时间(彩色滑动条),底部为游戏交互部分,画面上有9个洞,地鼠随机地从洞中冒出,再随机地消失;
- 角色描述:有三种地鼠,分别为幽灵地鼠(灰黑色)、普通地鼠(蓝灰色)及黄金地鼠(金黄色);
- 游戏操作:玩家用手指点击显现的地鼠,击中地鼠得分;
- 记分规则:击中普通地鼠得5分,击中幽灵地鼠得-5分,击中黄金地鼠得25分;
- 历史记录:将手机中保存游戏最高得分,每次游戏结束时,显示本次得分及历史记录,如果本地得分大于历史记录,则更新历史记录;
- 重新开始:每次游戏结束后,弹出对话框,如果玩家选择重开开始,则开始新一轮游戏;
- 退出游戏:如果玩家在游戏结束对话框中选择退出游戏,则退出该游戏。
第二节 素材准备
- 地鼠图片三张,分别为幽灵地鼠、普通地鼠及黄金地鼠;
- 背景图片一张,为草地图案,上面排列有9个小洞;
- 声音文件2个:击中黄金地鼠音效及击中幽灵地鼠音效(击中普通地鼠时发出振动)
第三节 界面设计
创建项目并命名为“打地鼠”,如图6-3所示,其中有三点需要说明:
- 三个显示数字0的标签宽度设为充满,这样可以使三个标签的宽度相等;
- 水平布局2的垂直对齐设为“居上”,使得滑动条居于标签与画布的中间位置;
- 在调整精灵在画布中的位置时,以测试设备或模拟器中的效果为准。
表6-1 组件清单
表6-2 组件属性设置
表6-3 精灵的坐标
第四节 编写程序——地鼠的闪现
一、难点分析
这个游戏的难点在于让9个精灵随机地从洞中冒出,并随机地隐藏。所谓随机,就是每个精灵出现的时间和停留的时长都不相同,这样才能使地鼠的出现具有不可预知性,游戏才能有趣味。
我们的解决方案是,将9个精灵的组件对象放在一个列表中(命名为精灵列表),利用遍历列表的循环语句,来设置每个精灵的隐现,并借助于随机小数,来产生隐现时间的差异性。
二、编写代码
在用户界面设计完成后,切换到编程视图。
(1)声明全局变量——精灵列表
(2)在屏幕初始化程序中创建精灵列表
我们希望在游戏开始时,所有地鼠处于隐藏状态,利用遍历列表循环来完成这一设置,同时,为了保持代码的简洁性,创建一个初始化精灵列表过程,将创建精灵列表及隐藏精灵两个操作归拢到该过程里,如图6-6所示。
(3)编写并调用随机显示地鼠过程
图6-7中的随机显示地鼠过程,其运行效果如何?想象一下,应用刚刚启动时,所有地鼠处于隐藏状态,计时器开始计时;当计时器到达计时点时,所有地鼠整齐划一地从洞中冒出来;当下一个计时点到达时(间隔1秒钟),所有地鼠又齐刷刷地隐匿起来;如此循环往复。为了克服这一点,我们引入随机小数,用随机小数的值来决定哪些地鼠需要隐藏或显示,代码如图6-8所示。
如图6-8所示,我们设定地鼠改变显示状态的条件为“随机小数< 0.1”,这意味着有每1秒钟地鼠改变显示或隐藏状态的几率为10%,换句话说,地鼠有90%的几率会保持它现有的状态,这样的几率设计意味着什么呢?猜猜看!对了,意味着游戏的难度很低,地鼠最长保持现有状态时间是9秒钟,等于它傻傻地呆在那里让你打,或者它藏在洞里迟迟不肯出来!改变这种结果的方法有两种:
- 缩短计时器的计时间隔,如将计时间隔设为300毫秒;
- 增加改变显示状态的几率,如将0.1该为0.3。
我们采用第二种方法,读者可以自己尝试采用第一种方法。
这种方法提供了一种改变游戏难度的思路。当我们要开发一款带有闯关模式的游戏时,可以利用概率(随机小数)的值,来逐步提高游戏的难度,概率值越大,显示状态的改变就越频繁,游戏的难度也就越大。
为了让我们的游戏更富挑战性,我们设置一个全局变量“难度”,并设它的初始值为0.1,随着游戏的进展,难度将逐渐提升。代码如图6-9所示。
这样的设置是否合理,或者是否可行,要在测试过程中给予评估,如果难度过大,可以改变提升难度的条件。现在是每隔10秒难度增加一级,可以调整为每隔15秒、20秒提升一级,只要将(计时次数/10)改为(计时次数/15)或(计时次数/20)即可。
(4)改变地鼠的外观
现有程序只能显示普通地鼠,我们希望能够有一定的几率来显示幽灵地鼠及黄金地鼠,假设这两种地鼠出现的几率均为20%,修改后的代码如图6-10所示。
也可以将出现非普通地鼠的概率与难度关联起来,如出现幽灵地鼠的几率=难度,而出现黄金地鼠的几率= 1-难度。读者可以自行决定采用哪一种方案。
第五节 编写程序——命中地鼠与得分
这个游戏中有三项数据需要显示:
- 击打次数:只要用户点击了画布,无论是否击中地鼠,都将被记入击打次数;
- 命中次数:用户击中普通地鼠及黄金地鼠的次数;
- 得分:按照规则,每击中一次地鼠,统计得分(+5、-5、+25)。
(1)显示击打次数
我们利用画布的被触摸事件来统计击打次数,代码如图6-11所示。
如果9个精灵都要分别编写上图中的程序,则要写9段几乎完全相同的程序,这不符合代码复用的编程规则,因此,我们创建一个带参数的过程——命中地鼠,来实现上述功能,代码如图6-13所示。
其他8个精灵的触摸事件处理程序也如法炮制,代码如图6-14所示。
在没有控制游戏时长的前提下,测试结果发现,当时间足够长之后,地鼠的出现与隐藏呈现出一种整齐划一的模式,原因在于难度等级逐渐加大,当难度增加到1之后,地鼠出现及隐藏的几率为100%,因此随机小数不再起作用。下面我们来限制游戏时长,并编写游戏结束程序。
第六节 编写程序——时间控制与游戏结束
(1)显示游戏剩余时间
利用数字滑动条来显示游戏的剩余时间。在计时事件处理程序中,每秒钟让滑块向左移动1个单位,当滑块位置为零时,停止计时,并弹出对话框,代码如图6-15所示。
测试结果如图6-16所示。
在测试过程中,发现两个问题:
- 在游戏最初的几秒钟内,地鼠的显现很缓慢,随着时间的增加,地鼠出现的频率加快,加快的速度过于明显;
- 命中地鼠时,虽然命中次数及分数有变化,但是用户的感觉很迷茫,不知道当前的点击是否命中了地鼠;
第一个问题的原因是难度值开始时太低,而增加得过快,可以通过修改计时间隔、难度的初始值及增量,来调节地鼠显现的频率,如将计时间隔设为500毫秒,将难度初始值设为0.2,将增量设为0.05;也可以将难度提升的时间加长,如将(计时次数/10)改为(计时次数/20),等等。综合以上方案,我们做如下调整:
- 在设计视图中,将计时器的计时间隔改为500毫秒,为此需要将数字滑动条的最大值及滑块位置改为120;
- 将难度初始值设为0.2;
- 将难度增量改为0.05;
- 将提升难度的时间长度改为20秒(计时次数为40次);
修改后的代码如图6-17所示。
情况有所改善,但感觉游戏的运行依然不够流畅,读者可以自行尝试调整上述指标,以求得更好的用户体验。
第二个问题,我们利用音效播放器组件,针对击中不同种类的地鼠,发出不同的声音,或产生振动,来反馈用户的操作,代码如图6-18所示。
(2)编写游戏结束程序
图6-16中显示的对话框只是临时用来提示游戏的结束,我们可以利用对话框显示更为复杂的内容,并利用其中的两个按钮对用户的选择做出回应。
首先创建一个游戏结束过程,将计时事件处理程序中的部分代码归拢到该过程里,并具体设置对话框的各项参数:
- 消息:显示本次游戏得分;
- 标题:显示历史记录,历史记录从本地数据库中提取,如果尚未保存过历史记录,则返回0;
- 按钮1文本:清除记录,稍后在对话框的选择完成事件中加以处理;
- 按钮2文本:退出游戏,在对话框选择完成事件中处理;
- 允许返回:值为默认的“真”,当用户点击返回按钮时,重新开始新一轮游戏。
除此之外,当本次得分高于历史记录时,将本次得分保存到本地数据库中,替代原有记录。注意:使用本地数据库组件保存及提取数据,必须使用相同的标记,这里为“打地鼠历史记录”,你也可以使用其他字符。具体代码如图6-19所示。
然后在计时事件处理程序中调用该过程,如图6-20所示。
(3)回应用户的选择
在对话框1的完成选择事件中,依据用户的选择,执行不同的操作。当用户选择退出游戏时,退出应用,否则,开始新游戏,且当用户选择清除记录时,将0保存到本地数据库中。
首先创建一个游戏初始化过程,如图6-21所示。
然后在对话框1的完成选择事件中,调用该过程,代码如图6-22所示。
经过测试,游戏运行正常,运行结果如图6-23所示。
第七节 代码整理
这是一个功能相对简单、技术并不复杂的小游戏,不过我们依然对代码进行整理,理清楚各个程序之间的关系,以便对代码进行可能的优化,图6-25中显示了程序之间的关系。
这个图为我们判断程序的机构提供了一个直观的感受,例如,在计时事件处理程序中,有三条红线直接指向变量及组件,在这种情况下,我们可以创建一个过程,将这三项操作归拢到过程里,来优化程序的结构,过程名称可以是“更新游戏进度”,代码如图6-26所示。
优化之后再来看程序之间的关系图,如图6-27所示。
这一点点改变并不提高程序的运行效率,但对于开发者来说,是一种抽象能力的提升:将若干个离散的操作用一个动宾词组加以概括,形成一个统一的概念,这有助于加深我们对程序的理解,并逐步养成一种将复杂问题简单化的思维习惯。