传统的俄罗斯方块一共有七种形状,分别以S、Z、L、J、I、O、T这7个字母的形状来命名。本节通过数组来定义这七种形状的相对虚拟坐标,并且每种形状 都有四个旋转状态,当然有的旋转状态都是一样...
传统的俄罗斯方块一共有七种形状,分别以S、Z、L、J、I、O、T这7个字母的形状来命名。本节通过数组来定义这七种形状的相对虚拟坐标,并且每种形状 都有四个旋转状态,当然有的旋转状态都是一样的,例如O形,四个旋转状态都是一个样子,尽管如此,也统一按四个状态来定。
本版本的下载地址为:http://pan.baidu.com/share/link?shareid=396056&uk=940392313 (此为百度盘的共享链接地址),进入zengl俄罗斯方块共享文件夹,在该文件夹中有个version_2_tetris.rar的压缩包就是v2版本的代码包,里面有个版本2说明.txt文件,包含了该版本的相关说明:
该版本是俄罗斯方块的第二个测试版本,该版本还没有建立任何可玩的游戏环节,运行俄罗斯方块版本2双击我运行.bat批处理文件,会从I,J,L,O,S,T,Z这七种形状中随机得到一种俄罗斯方块和随机的旋转状态,从顶部落到底部,到了底部后,就将俄罗斯方块重新初始化下落状态,并生成一个另外的随机形状继续下落,循环下去。可以按ESC键退出。如果要玩完整版,可以查看"zengl编程语言"栏目,其中的"zengl编程语言v1.0.5 编译,执行,源码调试一体化,开发俄罗斯方块"这篇文章里有俄罗斯方块正式发布版的下载地址。
如果是linux用户,在成功编译了zengl v1.0.5或更高版本的程序后(注意编译需要root权限,因为需要将.so动态链接库拷贝到/usr/lib中),可以将 version_2_tetris.rar里的version_2_tetris文件夹拷贝到zengl根目录中,最后运行./zenglrun version_2_tetris/tetris.zl -n 即可,如果要调试脚本,可以加个-d参数(参数的含义请参考上面提到的zengl v1.0.5的文章,或者通过-h参数来查看帮助)。
任何一种俄罗斯方块都是由四个小方块组成,每个俄罗斯方块也都有自己的整体虚拟坐标,而每个小方块的虚拟坐标是他的相对虚拟坐标加上整体虚拟坐标。
例如上图的I形状(用蓝色边框标记起来的),整体坐标是蓝边框左上角的(3,2) ,而I形状在垂直旋转状态下四个小方块的相对虚拟坐标为(2,0),(2,1),(2,2),(2,3),那么第一个小方块的在游戏主区域中的虚拟坐标就 是(3+2,2+0) = (5,2),第二个就是(5,3),依此类推。其他所有形状的小方块也都是相对蓝色边框的左上角的,这个蓝色边框是一个虚拟的4 X 4的区域。之所以要这么做,是为了方便定义俄罗斯方块的各种形状,同时也便于计算俄罗斯方块的整体运动坐标。
该版本tetris.zl的第167行的代码定义了所有形状和旋转状态的相对虚拟坐标:
tetris.members = array(
array(0,2),array(1,2),array(2,2),array(3,2) , array(2,0),array(2,1),array(2,2),array(2,3),
array(0,2),array(1,2),array(2,2),array(3,2) , array(2,0),array(2,1),array(2,2),array(2,3), //I形状的虚拟坐标
array(0,0),array(0,1),array(1,1),array(2,1) , array(0,2),array(1,2),array(1,1),array(1,0),
array(0,1),array(1,1),array(2,1),array(2,2) , array(2,0),array(1,0),array(1,1),array(1,2), //J形状的虚拟坐标
array(0,1),array(1,1),array(2,1),array(2,0) , array(0,0),array(1,0),array(1,1),array(1,2),
array(0,2),array(0,1),array(1,1),array(2,1) , array(1,0),array(1,1),array(1,2),array(2,2), //L形状的虚拟坐标
array(0,0),array(0,1),array(1,1),array(1,0) , array(0,0),array(0,1),array(1,1),array(1,0),
array(0,0),array(0,1),array(1,1),array(1,0) , array(0,0),array(0,1),array(1,1),array(1,0), //O形状的虚拟坐标
array(0,1),array(1,1),array(1,0),array(2,0) , array(0,0),array(0,1),array(1,1),array(1,2),
array(0,1),array(1,1),array(1,0),array(2,0) , array(0,0),array(0,1),array(1,1),array(1,2), //S形状的虚拟坐标
array(0,1),array(1,1),array(1,0),array(2,1) , array(0,1),array(1,1),array(1,0),array(1,2),
array(0,1),array(1,1),array(1,2),array(2,1) , array(1,0),array(1,1),array(1,2),array(2,1), //T形状的虚拟坐标
array(0,0),array(1,0),array(1,1),array(2,1) , array(0,2),array(0,1),array(1,1),array(1,0),
array(0,0),array(1,0),array(1,1),array(2,1) , array(0,2),array(0,1),array(1,1),array(1,0) //Z形状的虚拟坐标
俄罗斯方块的每种形状都有特定的颜色值,在后面的版本中使用的是方块图片,在本版本中为了简化代码,就用颜色来填充小方块。
下面的159行的代码设定了七种形状的颜色值:
tetris.color = array(array(0xf3,0x6c,0xe1) , //I形状的颜色值
array(0x37,0x33,0xe5) , //J形状的颜色值
array(0xde,0x9d,0x2b) , //L形状的颜色值
array(0xf1,0xf7,0x40) , //O形状的颜色值
array(0x33,0xf0,0x49) , //S形状的颜色值
array(0xd3,0x33,0xf0) , //T形状的颜色值
array(0xf6,0x10,0x36) //Z形状的颜色值
);
上面的两处代码需要注意的是array是一个函数,函数的参数中间以逗号隔开,最后一个参数后面不可以有逗号,这点和PHP不一样,所以需要特别注意,例如上面的array(0xf6,0x10,0x36)后面就没有逗号了。
该版本还添加了碰撞检测的自定义函数:
/*
对活动中的俄罗斯方块进行底部的碰撞检测,
*/
fun myCollisionDetect()
global tetris;
clsTetris tetris;
start = tetris.startindex * 16 + tetris.state * 4; //得到方块样式的索引信息
count = start + 4; //需要对四个方块都进行检测,所以加4
for(i = start ; i<count ; i++) //循环对四个小方块进行检测。判断是否到了底部
if(tetris.xy.vy + tetris.members[i].vy + 1 >= GameMainHeightNum)
return TRUE;
endif
endfor
return FALSE;
endfun
下面是俄罗斯方块运动过程中的新的虚拟坐标计算函数:
/*
计算运动中的方块的虚拟坐标,并判断是否下落到了主游戏区域的底部,如果到了底部就将俄罗斯方块重新初始化下落状态。
*/
fun myTetrisMove()
global time,isneedDraw,tetris,isinStartDroping;
clsTetris tetris;
if(sdlGetTicks() - time > 1000) //每隔1000毫秒,就进行匀速自由落体运动。
if(myCollisionDetect()) //先进行底部碰撞检测
myGetRandomIndex(); //再随机生成下一次的方块形状。
tetris.state = bltRandom()%TetrisStateNum; //设置下一次的方块旋转状态
tetris.xy.vx = bltRandom()%(GameMainWidthNum - 3); //设置随机的水平初始虚拟坐标
tetris.xy.vy = 0; //重置vy虚拟纵坐标
isneedDraw = TRUE; //因为设置了新的俄罗斯方块坐标形状等信息,所以需要重新绘制。
time = sdlGetTicks(); //重置time定时器
return;
endif
tetris.xy.vy++; //如果没发生碰撞,就让俄罗斯方块的整体虚拟坐标加一
isneedDraw = TRUE; //需要重新绘制
time = sdlGetTicks(); //重置time定时器
endif
endfun
该版本的运行截图如下:
OK,下节介绍v3的版本,休息,休息一下 O(∩_∩)O~