之前的版本,俄罗斯方块都是使用的颜色来填充,这节开始,为俄罗斯方块设置背景图片,同时为其添加上下左右键的操作功能。     下载地址为:http://pan.baidu.com/share/...
	    之前的版本,俄罗斯方块都是使用的颜色来填充,这节开始,为俄罗斯方块设置背景图片,同时为其添加上下左右键的操作功能。
	
	    下载地址为:http://pan.baidu.com/share/link?shareid=396056&uk=940392313 (百度盘共享链接地址),进入zengl俄罗斯方块共享文件夹,在该文件夹中有个version_3_tetris.rar的压缩包就是v3版本的代码包,里面有个版本3说明.txt文件,包含了该版本的相关说明:
	
	    该版本是俄罗斯方块的第三个测试版本,该版本具备基本的上下左右控制功能,运行俄罗斯方块版本3双击我运行.bat批 处理文件,会从I,J,L,O,S,T,Z这七种形状中随机得到一种俄罗斯方块和随机的旋转状态,从顶部落到底部,在下落过程中可以按左右键进行左右位 移,按上键来切换旋转状态,按下键来加速下落,到了底部后,就将俄罗斯方块重新初始化下落状态,并生成一个另外的随机形状继续下落,循环下去。可以按 ESC键退出。如果要玩完整版,可以查看"zengl编程语言"栏目,其中的"zengl编程语言v1.0.5 编译,执行,源码调试一体化,开发俄罗斯方块"这篇文章里有俄罗斯方块正式发布版的下载地址。
	
	    如果是linux用户,在成功编译了zengl v1.0.5或更高版本的程序后(注意编译需要root权限,因为需要将.so动态链接库拷贝到/usr/lib中),可以将 version_3_tetris.rar里的version_3_tetris文件夹拷贝到zengl根目录中,最后运行./zenglrun version_3_tetris/tetris.zl -n 即可,如果要调试脚本,可以加个-d参数(参数的含义请参考上面提到的zengl v1.0.5的文章,或者通过-h参数来查看帮助)。
	
	    在version_3_tetris目录中多了个tetris.png的俄罗斯方块背景图片资源:
	
	    上图就是俄罗斯方块七种形状的小方块背景图片集合。在游戏脚本中要加载这个图片资源,需要使用到sdlLoadBmp函数,该函数原型如下:
	
	sdlLoadBmp(picname,red[option],green[option],blue[option]); 第一个参数picname是位图的文件名,如果有四个参数,则使用后面的三个参数来设置位图colorkey的r,g,b值,colorkey可以过滤掉不要的颜色,产生透明背景效果。返回值为加载的位图表面指针。
	
	例如该版本的tetris.zl脚本文件的第132行:
	
	tetris.bgimg = sdlLoadBmp("tetris.png"); //俄罗斯方块背景图片
	    要将加载的位图绘制到游戏窗口中,需要使用到sdlBlitImg函数,该函数的原型如下:
	
	sdlBlitImg(src surface,src rect,dest surface,dest rect); 第一个参数src surface是要绘制的原位图表面指针,第二个参数src rect是原位图要绘制的矩形区域,如果是0,则表示将原位图的所有区域都绘制到目标表面中,如果是数组或类,则读取该数组中的前四项分别代表矩形区域的 坐标和宽高。第三个参数dest surface是要绘制的目标位图表面指针,第四个参数dest rect是要绘制的目标矩形区域,如果是0,则表示要绘制目标表面的所有区域,如果是数组或类,则表示目标矩形区域的坐标和宽高。
	
	例如tetris.zl脚本的myDrawTetris自定义函数的第12行:
	
	sdlBlitImg(tetris.bgimg,
	                    array(tetris.startindex * TetrisWidth,0,TetrisWidth,TetrisHeight),
	                    screen,
	                    array(TetrisWidth * (tetris.members[i].vx + tetris.xy.vx) + gameMainBg.pos.x,
	                            TetrisHeight * (tetris.members[i].vy + tetris.xy.vy) + gameMainBg.pos.y,
	                            TetrisWidth , TetrisHeight)
	                    );
	
	    从该版本开始,所有宏定义,类定义等都放在了tetris_def.zl脚本中。在宏定义部分,有和SDL按键事件相关的宏:
	
	//sdl event def SDL游戏引擎事件相关的宏定义
	def NoEvent 0;
	def EvKeyDown 2;
	def EvKeyUp 3;
	def KeyEsc 27;
	def KeyUp 273;
	def KeyDown 274;
	def KeyLeft 276;
	def KeyRight 275;
	def EvQuit 12;
	//sdl event def end
	
	    上面就定义了上下左右等按键的SDL值,这些值可以在SDL库的C头文件中找到,例如在windows vs2008的代码压缩包里包含了SDL-1.2.15目录,该目录中include目录下有个SDL_keysym.h头文件,里面有所有SDL按键事 件的值定义:
	
	    例如上图中的SDLK_UP按上键的值为273,对应zengl脚本中的KeyUp宏值。其他的按键宏值也是类似的定义方法。
	    为了处理这些按键事件,在游戏脚本中添加了myCalculateMove自定义函数:
	/*
	    如果按了上下左右方向键,则计算将要显示的位置和样式等信息
	*/
	fun myCalculateMove()
	    global tetris,isneedDraw,time;
	    clsTetris tetris;
	    switch(tetris.direct)
	    case KeyLeft:
	        start = tetris.startindex * 16 + tetris.state * 4;
	        if(tetris.xy.vx + tetris.members[start + 0].vx - 1 >= 0) //如果最左侧的小方块没到达主游戏区域的左边界,则将整体虚拟坐标减一
	            tetris.xy.vx--;
	        endif
	        break;
	    case KeyRight:
	        start = tetris.startindex * 16 + tetris.state * 4;
	        if(tetris.xy.vx + tetris.members[start + 3].vx + 1 < GameMainWidthNum) //如果最右侧的小方块没到达主游戏区域的右边界,则将整体虚拟坐标加一
	            tetris.xy.vx++;
	        endif
	        break;
	    case KeyUp:
	        orig_state = tetris.state;
	        tetris.state = (tetris.state + 1)%4; //按上键时,得到下一次的旋转状态
	        start = tetris.startindex * 16 + tetris.state * 4;
	        if((tetris.xy.vx + tetris.members[start + 0].vx  < 0) ||
	            (tetris.xy.vx + tetris.members[start + 3].vx  >= GameMainWidthNum) ||
	            myCollisionDetect()) //判断旋转后的状态是否超出左右边界,或者是否会发生底部碰撞,如果发生了这些情况,则将旋转状态恢复为原来的值。
	            tetris.state = orig_state;
	        endif
	        break;
	    case KeyDown:
	        if(!myCollisionDetect()) //如果按了下方向键,则进行碰撞检测,并在其中设置方块的下落速度。
	            tetris.xy.vy += tetris.speed;
	        endif
	        break;
	    default: //其他按键,直接返回
	        return;
	    endswt
	    isneedDraw = TRUE; //设置需要绘制标记
	    time = sdlGetTicks(); //重置定时器
	endfun
	
	    至于脚本中的其他代码都在重要的部分加了注释,可以结合注释和调试器进行分析,该版本的运行界面如下:
	
OK,下节介绍v4的版本,休息,休息一下 O(∩_∩)O~