第28章 案例开发
第28章 案例开发
(视频讲解:23分钟)
对于JavaScript初学者来说,尝试开发小型的难度适中的应用程序或游戏,能够培养学习乐趣,激发开发热情。本章将通过两个相对复杂的案例,帮助读者上机进行JavaScript实战训练,为日后的开发实习积累经验。
【学习重点】
▲ 使用JavaScript开发Web应用程序
▲ 使用HTML5+JavaScript开发Web游戏
28.1 设计小程序:万年历
本例设计一个既可以查看公历,又可以查看农历的万年历,并且在日期的下面显示了公历与农历的各个节日及农历的节气,运行结果如图28-1所示。
图28-1 万年历演示效果
本例主要利用Date对象来获取指定日期的相关信息,并用Lunar对象将指定日期转换成相应的农历日期。Date对象是一个有关日期和时间的对象,详细说明和用法请参阅第10章内容。
【操作步骤】
第1步,新建文档,保存为index.html,在页面中插入一个表单
标签,在其中嵌套一个表格。定义表格7列,两行,其中第1行为合并单元格,第2行为标题行,手动输入一周简称,代码如下:第2步,使用JavaScript代码在Menu组件中动态添加下拉菜单(年)。
第3步,使用JavaScript代码在Menu组件中动态添加下拉菜单(月)。
第4步,使用JavaScript代码在表格中添加6行7列的单元格,代码如下:
第5步,下面介绍如何编写用于实现公历日历与农历日历的JavaScript代码。在头部位置插入<script type=“text/<span id=” sensitive"="" class=“keyword-match”>JavaScript">标签。
第6步,使用数组记录日历中的相关信息。
第7步,使用数组保存公历的节日。
//公历节日
var sFtv=new Array(
“0101元旦”,
“0214情人节”,
“0308妇女节”,
“0312植树节”,
“0315消费者权益日”,
“0401愚人节”,
“0501劳动节”,
“0504青年节”,
“0512护士节”,
“0601儿童节”,
“0701建党节”,
“0801建军节”,
“0910教师节”,
“0928孔子诞辰”,
“1001国庆节”,
“1006老人节”,
“1024联合国日”,
“1224平安夜”,
“1225圣诞节”)
第8步,使用数组保存农历的节日。
var lFtv=new Array(
“0101春节”,
“0115元宵节”,
“0505端午节”,
“0707七夕情人节”,
“0715中元节”,
“0815中秋节”,
“0909重阳节”,
“1208腊八节”,
“1224小年”)
第9步,自定义函数lYearDays(y),用于返回农历y年的总天数。
第10步,自定义函数leapDays(y),用于返回农历y年闰月的天数。
第11步,自定义函数leapMonth(y),用于判断y年的农历中哪个月是闰月,不是闰月返回0。
第12步,自定义函数monthDays(y,m),用于返回农历y年m月的总天数。
第13步,自定义函数Dianaday(),用于计算出当前月第一天的农历日期和当前农历日期下一个月农历的第一天日期。
第14步,自定义函数solarDays(y,m),用于返回公历y年m+1月的天数。
第15步,自定义函数calElement()用于记录公历和农历某天的日期。
第16步,自定义函数sTerm(y,n)用于返回某年的第n个节气为几日(从小寒算起)。
第17步,自定义函数calendar(y,m)用于保存y年m+1月的相关信息。
第18步,自定义函数cDay(d),用中文显示农历的日期。
第19步,自定义函数drawCld(SY,SM),在表格中显示公历和农历的日期以及相关节日。
第20步,自定义函数changeCld(),在下拉列表中选择年或月时,调用自定义函数drawCld()显示公历和农历的相关信息。
第21步,自定义函数initial(),打开网页时,在下拉列表中显示当前年月,并调用自定义函数drawCld(),显示公历和农历的相关信息。
第22步,在页面初始化完成事件onload中调用自定义函数initial()。
28.2 设计游戏:俄罗斯方块
俄罗斯方块是一款单机休闲小游戏。在俄罗斯方块的游戏界面中,有一组正在下落的方块,方块通常有4个,组合成各种不同的形状,游戏玩家需要控制正在下落的方块的移动,将这组方块摆放到合适的位置。只要下面某一行全部充满方块,没有空缺,那么这行就可以消除,上面的所有方块会整体掉下来。
俄罗斯方块的游戏界面比较简单,游戏的实现逻辑也不太复杂,非常适合JavaScript初学者作为进阶训练项目。本例采用HTML5的canvas来绘制游戏界面,用Local Storage来记录游戏状态。游戏演示效果如图28-2所示。
28.2.1 设计游戏界面
俄罗斯方块的游戏界面分为两个区域:速度、积分显示区;主游戏界面区。
【操作步骤】
第1步,新建网页文档,保存为index.html。
图28-2 俄罗斯方块游戏演示效果
第2步,使用
第3步,游戏主界面通过HTML5的canvas进行绘制,由JavaScript动态生成。在网页头部区域插入<script type=“text/<span id=” sensitive"="" class=“keyword-match”>JavaScript">标签。
第4步,为了让程序可以动态地改变界面大小,canvas的大小是由程序动态计算得到的,下面是动态计算、生成画布的JavaScript脚本。
上面代码动态创建了一个canvas组件,该组件的高度、宽度是由程序动态计算得到,同时使用路径绘制了横向、竖向的线条,用于表示俄罗斯方块游戏界面上的网格。
28.2.2 设计游戏模型
俄罗斯方块的游戏界面是一个N×M的网格,每个网格上显示一张图片,这个网格用一个二维数组来定义,而每个网格上所显示的色块,对于底层的数学模型来说,不同的色块对应于不同的数值即可。本例直接使用一个二维数组来保存游戏的状态数据,不过由于JavaScript是动态语言,因此使用二维数组时依然是一维数组。
【操作步骤】
第1步,俄罗斯方块的游戏界面上还有一组正在下落的方块。这组正在下落的方块通常有4个,这4个方块的位置随时在改变,因此采用一个长度为4的数组来记录这4个方块的位置。
在上面数组中,每个数组元素都是一个对象,对象包括x、y、color 3个属性,分别代表了该方块所在的位置、颜色值。
第2步,为了初始化游戏状态,创建一个二维数组,这个二维数组记录了游戏界面上每个位置的方块值(不同的值代表不同的颜色)。具体代码如下:
上面代码创建了一个二维数组,并将这个二维数组的每个数组元素都赋值为NO BLOCK(也就是0),这代表该游戏界面上还没有方块。
第3步,为了能随机生成各种向下掉的方块组合(4个方块组成一组),预先把各种组合定义出来,然后每次需要开始掉落新的方块组时,随机取出一组即可。下面是随机获取掉落的方块组的代码:
上面的代码先定义了一个数组,这个数组定义了所有可能出现的方块组合,这里一共定义了7种组合。由于程序随机从上面的数组中取出可能出现的方块组合,因此在游戏中完全可能出现上面7种掉落的方块组合。
28.2.3 实现游戏功能
定义了游戏状态模型之后,接下来处理方块组合的掉落,在掉落过程中还需要处理方块组合左移、右移、旋转等动画。
【操作步骤】
第1步,处理方块掉落。
让方块组合掉落,只需把每个方块的y属性增加1即可,但在处理方块组合掉落之前,需要判断方块组合是否可以掉落。如果出现如下两种情况,方块组合则不能掉落。
☑ 如果方块组合中任意一个方块已经到了最底部。
☑ 如果方块组合中任意一个方块的下面已有方块。
如果方块组合可以掉落,需要把方块组合原来所在位置的颜色清除,再把方块组合中每个方块的y属性增加1,最后把当前方块所在位置涂上相应的颜色。
当每次方块掉落之后,还需要逐行扫描每一行,判断是否某一行的方块已满,当方块已满时,将该行方块消除,并增加积分。
下面moveDown()函数定义了方块掉落的实现方法:
上面的代码先定义了一个canDown变量,该变量用于标识方块组合是否能掉落。如果方块组合的任一方块已经到了最底下,或者方块组合的任一方块下方已有方块,将canDown变量值设为false。
当方块组合能掉落时,则先清除该方块组合所在位置的背景色,然后控制方块组合向下掉落,最后把掉落一格后的方块组合所在位置的背景涂上相应的颜色。
当方块组合不能向下掉落时,则执行如下几个任务:
☑ 如果某个方块已经到了最上面,则表明游戏已经结束,玩家输了。当游戏结束时,需要再执行如下几个任务。
▶ 清空Local Storage中的当前游戏积分、当前游戏速度、当前游戏状态。
▶ 使用confirm对话框提示用户。
▶ 将isPlaying变量设为false。
▶ 清除计时器,该计时器控制方块组合不断地向下掉落。
☑ 判断是否有可消除的行。
☑ 使用Local Storage记录当前俄罗斯方块的游戏状态。
☑ 调用initBlock()方法开始一组新的方块。
上面的代码采用了Local Storage记录当前俄罗斯方块的游戏状态,就是把记录游戏状态的二维数组转换为字符串后写入Local Storage,这样即可保证游戏状态不会丢失,下次打开浏览器时还可以接着上次的游戏状态继续。
initBlock()函数用来判断是否有可消除的行,如果发现某一行的方块已满,则程序处理积分增加,并且该行上面的所有行整体下移一行。下面是lineFul()函数的详细代码:
当某行的所有位置都有方块之后,需要增加curScore游戏积分。除此之外,如果游戏积分已经达到了升级界限,将增加游戏速度,并清空原有的计时器,根据现有的游戏速度启用新的游戏计时器。
当游戏消除了指定某一行的所有方块之后,需要调用drawBlock()函数绘制tetris_status数组中的所有方块。drawBlock()函数代码如下:
上面的drawBlock()函数负责把俄罗斯方块的数据模型转换成可视化的方块图。
第2步,处理方块左移。
先给键盘事件绑定事件监听器,当用户按下不同按键时,调用不同的方法进行处理。下面是为按键事件绑定监听器的代码:
在上面的代码中,当按下向左箭头时,如果还处于游戏中,则调用moveLeft()函数处理方块组合左移;相反按下向右箭头时,如果还处于游戏中,则调用moveRight()函数处理方块组合右移;当按下向上箭头时,如果还处于游戏中,则调用rotate()函数处理方块组合旋转。
方块组合左移实现比较简单,只要将方块组合中所有方块的x属性减1即可。但在左移之前先要判断是否可以左移。如果方块组合已经到了最左边,或者方块组合的左边已有方块,那么方块组合就不能左移。详细代码如下:
第3步,处理方块右移。
与方块组合左移的思路基本相似,都是先判断方块组合能否右移,如果可以右移,则将方块移动之前位置的背景色清空,将每个方块的x属性加1,再将移动后的方块所在位置的背景涂上相应的颜色即可。详细代码如下:
第4步,处理方块旋转。
处理方块旋转是最复杂的,因为需要动态地计算方块旋转后的坐标。当然,在对方块组进行旋转之前,同样需要先判断是否可以旋转方块,只有当方块可以旋转时才去进行旋转。下面是控制方块组合逆时针旋转的代码:
第5步,初始化游戏状态。
在游戏过程中,使用了Local Storage保存游戏状态,包括游戏的当前积分、游戏速度、已有方块的状态等。为了正常使用Local Storage所记录的游戏状态,可以在页面初始化后通过Local Storage读取这些数据,并把这些数据显示出来,具体代码如下:
上面的代码在游戏开始时需要完成如下事情。
☑ 调用createCanvas创建canvas组件。
☑ 读取Local Storage记录的已有方块的状态。
☑ 读取Local Storage记录的当前积分数据。
☑ 读取Local Storage记录的当前速度数据。
☑ 读取Local Storage记录的最高积分数据。
☑ 初始化正在掉落的方块。
☑ 启动计时器,控制方块掉落。
【小结】在学习本例时,读者需要熟悉本游戏的玩法,然后能够理解界面设计的思路和实现途径。同时应该熟练掌握使用JavaScript操控canvas和Local Storage技术的能力。