最近心血来潮加上有点闲情,动手写了第一个JavaScript版的俄罗斯方块Easy Tetris.
先上Easy Tetris俄罗斯方块游戏截图:
由于某些人有cheat情节,加上了一个投影功能:^_^
由于非IE浏览器的功能键屏蔽无法完美实现,在游戏页面中的“清爽页面”用来隐藏非游戏区域的其他页面模块以清除页面滚动条,之后可以通过“展开页面”重新展开隐藏的页面。
经过一些测试发现,在某些系统下的非IE浏览器中运行Easy Tetris时,左右移动有粘滞感,有兴趣的朋友可以一起讨论下优化。
Easy Tetris实现核心部分
下一个方块
原型为一个4*4的表格加上方块展示方法,可以通过分别继承两个类(表格类,方块类),加上自身的next方法,来实现。
游戏区域
原型为一个12*20的表格,由于考虑到算法优化,直接设置为(4+12+4)*(4+20+4)的表格,该表格同时具有一个与表格中格子数相同的二维数组,用作方块的边界检测
游戏填色区域
原型为一个12*20的表格,由于考虑到算法优化,直接设置为(4+12+4)*(4+20+4)的表格,方块停止下落后,在对应的行和列中填上与下落方块相同的颜色。
当在“游戏区域”的二维数组中检测到行被填满,则删除填色区域相应的行,同时,在首行前插入相应数量的新行。
游戏方块
原型为一个4*4的表格加上方块展示方法,可以通过分别继承两个类(表格类,方块类)并且加上自身的一些方法来实现,此组件为俄罗斯方块中的重要组件,在Easy Tetris的实现中,该组件担当了大部分的游戏任务,移动,变形,边界检测等等,游戏中多数的方法都被安排在此组件上实现。
方块形状及变形
方块及形状的实现可以通过一个4*4的二维数组来实现,比如方块Z,我们可以写为:
[
[1,1,0,0]
[0,1,1,0]
[0,0,0,0]
[0,0,0,0]
]
1,表示这个位置是一个方块,0表示什么都没有,是不是很简单?由于这种写法会造成数据量的增大,我们可以将此数据形式压缩为16进制形式,还是以Z为例。
1100011000000000 -> 转为16进制 -> 0xc600,于是上面的数组可以简写为:
[0xc600]
数据量大大缩减,然后在程序中需要有一个反转的过程,将此16进制数据转换到2进制数据,需要注意的是,你可能会发现一些16进制的数据转换到2进制后不够如上面数组中的16个元素,你需要在转换后的2进制数据前补足相应个数的 0。
变形部分相对简单,如,Z的变形为:
[
[0,0,1,0]
[0,1,1,0]
[0,1,0,0]
[0,0,0,0]
]
只要将此形状同时保存到方块数组中即可,由于所有方块中,最多变形次数为4次,所以,所有方块都4个一组的来表示,每一个维度表示每一次形变后的形状,在变形方法中只要通过这个索引值来进行递增即可获得下一次形变的样子,然后重新渲染出来即可。
投影部分
需要一个和方块部分一一对应的数组,记录每个方块的投影区域,还是以Z为例,它可以表示为:
[1,1,1,0,1,1,0,0]
前4位 1,1,1,0 表示,在一个4列的格子中,Z,前面3个格子是要进行投影的
后4位 1,1,0,0 表示,投影跟随下落方块的时候,Y坐标在下落方块下面第1个位置(1的个数-1)
投影部分除了需要一个对应的数据外,还需要一个DOM元素进行表示,很简单,就是一个1*4的表格,它需要在下落方块移动、变形的时候做相应的处理。
边界检测
边界检测应该是俄罗斯方块中最重要的算法部分了。在Easy Tetris中采用的是“位与”判断的方法进行处理,即,将下落的方块4*4个区域与即将落在的游戏区域中相应的4*4个区域进行“位与”比较,如果返回0,则说明可以移动,否则,不能移动。
下落的方块每调用一次“移动”的方法之前,都要进行边界检测;
下落的方块每调用一次“变形“的方法之前,也要进行边界检测;
所以,如果你能够足够的优化移动、变形、边界检测这三部分的算法,那么你的俄罗斯方块将会给玩家一个非常高的控制灵敏度,从而大大提高可玩性!
好了,在WEB中用JavaScript编写俄罗斯方块的大体原理就是这样了,下面,我们一起来玩玩这个写好的俄罗斯方块游戏Easy Tetris吧:
http://www.v-ec.com/games/tetris/