俄罗斯方块逻辑
博客地址http://blog.只写了这么一个
写一个俄罗斯方块的游戏需要些什么?它简单的难以想象.我尽量不用程序语言来表达,你们只需要一个思想而已,一个逻辑思想.有些地方我会使用C/C++代码,但它非常简单只是一些声明或者条件语句.
在开始前确保你在你的程序语言上会做以下4件事:
1.定时器申请.你必须学会使用定时器,比如每3秒在屏幕上打印一句话或者弹出一个消息框,能够做到这个已经足够了.
2.键盘消息.当你按下某个键的时候打印一句话或者一个消息框,如果你不会这个怎么去控制游戏呢,除非你有其他的代替.
3.图形显示.这个就随便你了,你可以用DOS窗口,也可以用个界面然后上面画点控件之类的.后面我会讲到逻辑地图和图形界面的链接,使用的是OpenGL,不过这里只是一个方法,任何图形显示都是这个方法,非常简单.
4.你对你的设计语言非常了解,比如循环,条件,数组,随机函数.逻辑部分只要这4个.
好吧开始了,最开始我们需要一张地图,准确点说是两张.如果你对我的逻辑有些混乱,那就多添加几张,没什么大不了的.
int map[10][20]; //定义一个整形的二维数组,它的宽度是10长度是20,这就是我们的地图了.
如果你不能理解二维数组教你个简单的方法 int mapx[10],mapy[20]; 怎么样,一维数组总好理解了吧.这个地图就是玩的时候用的,在里面放零件消除填满的方块.接着我们还要定义一张小的地图,这张小的地图就是用来显示当前控制的东东,它可能是一个长条也可能是一个方块.和大地图一样我们这样定义它 int play[4][4]; 长宽都是4个,这已经足够了因为我们的零件最大就是这个程度.
好了现在我们有了2样东西,10x20的大地图和4x4的小地图.我们再要一些俄罗斯方块的那些小零件就齐全了.怎么去定义那些零件呢?用一个变量,零件存放的地方我还是用整形数组来表示,不过这次是三维的.我希望你们对数组真的没有什么问题.
首先画一个正方形吧,这里有2种状态,当值为0时表示不显示,值为1时是现实:
int tool[7][4][4];
第一个值表示我们的零件一共有7样,不要把零件的整个形态都写出来,取一种就够了,比如长条,你决定是横着的还是竖着的,因为到时候游戏开始后玩家可以控制它是横还是竖,不过它出场的时候就一个形态就够了.后面2个值和我们的小地图是对接起来的,地图多大它就多大,这样方便映射.
好开始画了,这样很直观也很方便,你肯定能理解:
tool[0]={{0,0,0,0},
{0,1,1,0},
{0,1,1,0},
{0,0,0,0}};
我把它画在中间了,你自己决定你要怎么做.这不难理解,tool的第1个形状是个正方形,第一个括号和最后一个括号链接,中间有4个相关联的括号,每个括号里又有4个值,这表示了前面的4x4的矩形零件.不要偷懒,把剩下的6个全部画出来.你应该知道俄罗斯方块有哪些种类,每个种类只取一个形态.拿张纸比划一下,不要设计的太离谱了,因为后面我们要考虑到旋转.
在画好所有零件后我们就可以开始工作了,现在我们有3样东西了:零件(tool),大地图(map),小地图(play).再声明2个变量 int x,y; 它表明零件在大地图上的位置
逻辑部分开始了,游戏开始前先清空我们的大地图,用一个循环语句,把他们全部设置成0.注意!底部和两边设置成1,这样有利于我们做碰撞测试.这就叫初始化
[提取零件函数]用随机数0~6提取一个零件,并用循环语句把它装到小地图里.设置x和y的值让它出现在正上方比如x=4;y=0;现在我的大地图值是向下和向右扩展的.map[0][0]表示我的左上角,map[9][19]表示我的右下角.首先做个碰撞测试,先取得x和y的值,这个值表示小地图(play)的左上角这个点实际映射地址是play[0][0];做个循环条件的比较.先测试play[0][0]和map[x][y]是否都为1,如果是那说明已经碰撞了,gameover.如果没有再测试play[0][1]和map[x][y+1],做个循环做16次比较.安全的话进行下一步.
[自动下落函数]在移动前先做判断,而不管这里是否有定时器或者键盘控制的发生.定时器的作用开始了,进过了某些毫秒,先做碰撞测试,碰撞测试和上面的有些不同,在碰撞测试前,将y值向下移动一位,也就是y+1,然后进行测试play[0][0]和map[x][y+1]是否都为1(注意要循环整个play哦).如果是就发生[写入函数],那么如果下面没有问题,y的值就要真正的加1了.然后等待定时器重复上面的动作.在定时器动作开始的时候将键盘控制给禁掉,禁止任何键盘动作,比如写个keydown(true)在定时器动作结束的时候keydown(false).
[写入函数]就将小地图(play)写到大地图(map)里.0和0的继续是0,0和1的就变成1.紧接着要验证是否填满了,取得y值,依次检查map[0到9][y到y+4]如果那一行确实满了,就把上面一行复制下来,不停的复制,直到大地图(map)的最上面一行,然后把最上面一行清空.然后跳出这个函数要重新提取零件了.
[旋转函数]它定位于空格键,我们把空格键作为控制旋转.循环将play的矩阵做个旋转,自己思考一下.可以申请另一个大小的地图作为存放.旋转前做个碰撞测试,是否能够旋转.
[左右移动函数]它定位于方向键左和右,在移动前同样做碰撞测试,向左就x-1,向右就x+1,y不变.这个逻辑很好理解嘛.
你能理解它怎么运作的吗?我想肯定能了,如果不能,那可能是我表达的不清楚~~~ (-_-)!!
现在怎么把这个逻辑地图和图形显示对接起来呢,非常简单.如果你是使用16位程序DOS在显示那就不要看了,直接照屏幕打印地图就完了.如果是32位程序有个界面,你可以先用控件,比如说按钮.对接的原理就是循环判断逻辑地图如果是1就将控件(也许是按钮)show出来,如果是0就隐藏控件啦.注意大地图和小地图要显示在一起哦,前面我所说的x和y的值就是小地图在大地图的位置.如果要提前显示下一个零件,那就提前随机算好下一个零件,直接打印tool在左上角或者右上角不相关的地方.
对于OpenGL或者D3D,SDL之类的,图形显示为所做即所得的形式就更加方便了.
/*一堆GL初始化代码*/
/*GL的显示列表完成*/
//自己估量好x,y的间隔,用循环打印下面的box(你的方块)
x=0;y=0;
while(x<=9){
while(y<=19){
glLoadIdentity();
glTranslatef(x,y,-6.0f);
if(map[x][y]==1)glCallList(box);
y+=1;
}
x+=1;
图形显示和逻辑地图+控制+定时器完全没有任何联系,它所要做的就是以正确的方位和正确的图片来显示它的位置.