JavaScript版俄罗斯方块Easy Tetris实现原理

dh20156 2009-06-22 09:19:59
加精
最近心血来潮加上有点闲情,动手写了第一个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/
...全文
1127 158 打赏 收藏 转发到动态 举报
写回复
用AI写文章
158 条回复
切换为时间正序
请发表友善的回复…
发表回复
oulei123 2010-09-19
  • 打赏
  • 举报
回复
值得学习
幻冰之吻 2010-07-05
  • 打赏
  • 举报
回复
太牛了
dpsing 2010-01-20
  • 打赏
  • 举报
回复
好东东,
tutu_gaga 2009-12-30
  • 打赏
  • 举报
回复
收藏了~
audryhepburn 2009-12-06
  • 打赏
  • 举报
回复
没有源码呀!
shenzhenNBA 2009-11-24
  • 打赏
  • 举报
回复
[Quote=引用 148 楼 cuixiping 的回复:]
我的“Javascript漂亮俄罗斯方块”新鲜出炉了

1、按键反应灵敏(摒弃了onkeydown的系统自动repeat)
2、支持换皮肤,可以设置方块图案(预置5种方块图案)、背景图案(预置10位美女图)、网格。
3、自定义初始速度
4、积分历史记录
5、自定义按键(呕心之作!目前支持自定义按键的俄罗斯方块太少太少了。)
6、配置自动保存(存于Cookie中),下次游戏时,皮肤设置、速度设置、按键设置、积分记录会自动载入。
7、兼容性(搞过WEB前端的童鞋都知道兼容的痛),我测试通过了IE8.0,IE7.0,IE6.0,Firefox3.0,Opera9.6(为了它颇费一番工夫),其他浏览器因环境限制暂时没有测试。
8、全部采用DIV+CSS,摒弃传统的以表格显示方块的做法。

特别是按键自定义功能,增添了游戏的方便性和趣味性。(1)玩家可以一只手控制左右、另一只手控制旋转(我喜欢用左手按Ctrl旋转),双手配合比只使用一只手轻松多了!(2)也可以锻炼一下逆向思维,左右键功能互换,上下键功能互换,看看你脑子转不转得过来!

CSDN散分帖子:
http://topic.csdn.net/u/20090722/02/69c1ffb6-670f-4ad3-a8f6-baf494979914.html

CSDN博客全文:
http://blog.csdn.net/cuixiping/archive/2009/07/22/4369090.aspx

在线试玩:
http://www.cuixiping.com/jsgame/tetris-cxp/
[/Quote]
支持,很牛,这个我常上去玩的,呵呵。。。
maogubeijing 2009-10-03
  • 打赏
  • 举报
回复
厉害厉害~~~~~
saltprune 2009-09-14
  • 打赏
  • 举报
回复
哇,太强了,学习了。
cuixiping 2009-07-27
  • 打赏
  • 举报
回复
有个小bug:很多方块移动到靠边或者是快靠边(还空一格距离)的时候,就不能变形(旋转)了。
cuixiping 2009-07-22
  • 打赏
  • 举报
回复
我的“Javascript漂亮俄罗斯方块”新鲜出炉了

1、按键反应灵敏(摒弃了onkeydown的系统自动repeat)
2、支持换皮肤,可以设置方块图案(预置5种方块图案)、背景图案(预置10位美女图)、网格。
3、自定义初始速度
4、积分历史记录
5、自定义按键(呕心之作!目前支持自定义按键的俄罗斯方块太少太少了。)
6、配置自动保存(存于Cookie中),下次游戏时,皮肤设置、速度设置、按键设置、积分记录会自动载入。
7、兼容性(搞过WEB前端的童鞋都知道兼容的痛),我测试通过了IE8.0,IE7.0,IE6.0,Firefox3.0,Opera9.6(为了它颇费一番工夫),其他浏览器因环境限制暂时没有测试。
8、全部采用DIV+CSS,摒弃传统的以表格显示方块的做法。

特别是按键自定义功能,增添了游戏的方便性和趣味性。(1)玩家可以一只手控制左右、另一只手控制旋转(我喜欢用左手按Ctrl旋转),双手配合比只使用一只手轻松多了!(2)也可以锻炼一下逆向思维,左右键功能互换,上下键功能互换,看看你脑子转不转得过来!

CSDN散分帖子:
http://topic.csdn.net/u/20090722/02/69c1ffb6-670f-4ad3-a8f6-baf494979914.html

CSDN博客全文:
http://blog.csdn.net/cuixiping/archive/2009/07/22/4369090.aspx

在线试玩:
http://www.cuixiping.com/jsgame/tetris-cxp/
antybaby 2009-07-11
  • 打赏
  • 举报
回复
强大
zyongking 2009-07-11
  • 打赏
  • 举报
回复
upup
antybaby 2009-07-11
  • 打赏
  • 举报
回复
先顶个先...再慢慢看
redhat4 2009-07-05
  • 打赏
  • 举报
回复
楼主很强大, 讲解的很详细
foxmt 2009-07-04
  • 打赏
  • 举报
回复
不错! ^_^
qr11121223 2009-06-26
  • 打赏
  • 举报
回复
楼主做的出来就厉害了,还能讲的这么详细太强大了
vivian_000 2009-06-26
  • 打赏
  • 举报
回复
玩了一下,感觉还不错,呵呵
dh20156 2009-06-26
  • 打赏
  • 举报
回复
感谢愚公提的几点意见! ^_^

FF下的迟钝可能并不是事件处理不当造成,更多的与FF(Mozilla系列浏览器同样)的Reflow效率有关,你可以亲自测试一下,在不同的浏览器下,相同的代码,cpu占用基本一致,只有Mozilla系列浏览器占用最高

至于按钮开关,选择级别,之前是有的,你看1楼的贴图也可以看到,后来都去掉了 - -!~

方块及所有形变都是静态数据

表格和div的选择,可能表格还是更合理的,当你自己亲手去做的时候,你可能会发现 ^_^

边界检测部分,你说的不错,我确实偷了懒,没有足够去优化,不过这样更安全不是么 ^_^


另,Easy Tetris正在举办人工智能AI比赛,欢迎大家踊跃尝试:

Easy Tetris正在举办人工智能AI大赛页面:
http://www.v-ec.com/games/tetris/ai.htm
cuixiping 2009-06-26
  • 打赏
  • 举报
回复
没有看楼主的代码算法,我说说我自己的想法。

我打开楼主的网址玩了一下,感觉对按键的反应很迟钝(一秒钟最快要能旋转20次以上才算可以),我是FF3。可能你的事件处理没弄好。

功能上,我想楼主至少应该的改进是:1.提供按钮点击来实现开局功能,2.直接选择相应的速度基本来玩,每次玩1级真的很没劲,我都是直接从第十级玩的。

总共只有7种基本图案。这7种进行顺时针或逆时针旋转,一共能产生19种不同状态图案。
每种图案的每种状态都用常量保存下来,就能优化算法速度,减少很多计算。
还有就是,楼主用表格恐怕也不是效率最好的,应该做更多一点比较才知道,至少应该比较一下和纯DIV的效率对比,我直觉上使用DIV会更高效,因为移动和消除都更简洁方便。


至于边界检测,也不是每次移动或旋转都需要检测,上面几行是空行不需要检测(只需要判断行号),每次方块落定后计算出底下有几行方块,下次就能直接比较了,可以省去将近一半的边界检测(只有移到最左边或最右边才检测,但比较简单)。




1.棍子(2种状态)
 ■■■■

2.T (4种状态)
 ■■■
  ■

3.立方 (1种状态)
 ■■
 ■■
 
4.L (4种状态)
   ■
 ■■■

5.反L(L的镜像) (4种状态)
 ■
 ■■■

6.Z (2种状态)
 ■■
  ■■

7.S(Z的镜像) (2种状态)
  ■■
 ■■



wu18sd1 2009-06-25
  • 打赏
  • 举报
回复
good
加载更多回复(137)

87,901

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧